gpu,gpu/backend: don't assume constant output framebuffer

Return the output framebuffer from BeginFrame, to make it clear that
it may change between frames. Delete CurrentFramebuffer which is no
longer needed.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2021-03-02 20:43:59 +01:00
parent 3d3ff575e3
commit 25a19481e3
5 changed files with 17 additions and 21 deletions
+5 -4
View File
@@ -274,7 +274,8 @@ func NewBackend(d *Device) (*Backend, error) {
return b, nil return b, nil
} }
func (b *Backend) BeginFrame() { func (b *Backend) BeginFrame() backend.Framebuffer {
return b.currentFramebuffer()
} }
func (b *Backend) EndFrame() { func (b *Backend) EndFrame() {
@@ -368,13 +369,13 @@ func (b *Backend) NewTexture(format backend.TextureFormat, width, height int, mi
return &Texture{backend: b, format: d3dfmt, tex: tex, sampler: sampler, resView: resView, bindings: bindings, width: width, height: height}, nil return &Texture{backend: b, format: d3dfmt, tex: tex, sampler: sampler, resView: resView, bindings: bindings, width: width, height: height}, nil
} }
func (b *Backend) CurrentFramebuffer() backend.Framebuffer { func (b *Backend) currentFramebuffer() backend.Framebuffer {
renderTarget := b.dev.ctx.OMGetRenderTargets() renderTarget := b.dev.ctx.OMGetRenderTargets()
if renderTarget != nil { if renderTarget != nil {
// Assume someone else is holding on to it. // Assume someone else is holding on to it.
_IUnknownRelease(unsafe.Pointer(renderTarget), renderTarget.vtbl.Release) _IUnknownRelease(unsafe.Pointer(renderTarget), renderTarget.vtbl.Release)
} }
if renderTarget == b.fbo.renderTarget { if b.fbo != nil && renderTarget == b.fbo.renderTarget {
return b.fbo return b.fbo
} }
return &Framebuffer{dev: b.dev, renderTarget: renderTarget, foreign: true} return &Framebuffer{dev: b.dev, renderTarget: renderTarget, foreign: true}
@@ -823,7 +824,7 @@ func (f *Framebuffer) Invalidate() {
func (f *Framebuffer) Release() { func (f *Framebuffer) Release() {
if f.foreign { if f.foreign {
panic("cannot release Framebuffer from CurrentFramebuffer") panic("framebuffer not created by NewBuffer")
} }
if f.renderTarget != nil { if f.renderTarget != nil {
_IUnknownRelease(unsafe.Pointer(f.renderTarget), f.renderTarget.vtbl.Release) _IUnknownRelease(unsafe.Pointer(f.renderTarget), f.renderTarget.vtbl.Release)
+1 -2
View File
@@ -12,7 +12,7 @@ import (
// APIs such as OpenGL, Direct3D useful for rendering Gio // APIs such as OpenGL, Direct3D useful for rendering Gio
// operations. // operations.
type Device interface { type Device interface {
BeginFrame() BeginFrame() Framebuffer
EndFrame() EndFrame()
Caps() Caps Caps() Caps
NewTimer() Timer NewTimer() Timer
@@ -20,7 +20,6 @@ type Device interface {
// are valid at the point of call. // are valid at the point of call.
IsTimeContinuous() bool IsTimeContinuous() bool
NewTexture(format TextureFormat, width, height int, minFilter, magFilter TextureFilter, bindings BufferBinding) (Texture, error) NewTexture(format TextureFormat, width, height int, minFilter, magFilter TextureFilter, bindings BufferBinding) (Texture, error)
CurrentFramebuffer() Framebuffer
NewFramebuffer(tex Texture, depthBits int) (Framebuffer, error) NewFramebuffer(tex Texture, depthBits int) (Framebuffer, error)
NewImmutableBuffer(typ BufferBinding, data []byte) (Buffer, error) NewImmutableBuffer(typ BufferBinding, data []byte) (Buffer, error)
NewBuffer(typ BufferBinding, size int) (Buffer, error) NewBuffer(typ BufferBinding, size int) (Buffer, error)
+2 -4
View File
@@ -29,7 +29,6 @@ type compute struct {
cache *resourceCache cache *resourceCache
maxTextureDim int maxTextureDim int
defFBO backend.Framebuffer
programs struct { programs struct {
elements backend.Program elements backend.Program
tileAlloc backend.Program tileAlloc backend.Program
@@ -197,7 +196,6 @@ func newCompute(ctx backend.Device) (*compute, error) {
} }
g := &compute{ g := &compute{
ctx: ctx, ctx: ctx,
defFBO: ctx.CurrentFramebuffer(),
cache: newResourceCache(), cache: newResourceCache(),
maxTextureDim: maxDim, maxTextureDim: maxDim,
conf: new(config), conf: new(config),
@@ -290,7 +288,7 @@ func (g *compute) Frame() error {
Y: (viewport.Y + tileHeightPx - 1) / tileHeightPx, Y: (viewport.Y + tileHeightPx - 1) / tileHeightPx,
} }
g.ctx.BeginFrame() defFBO := g.ctx.BeginFrame()
defer g.ctx.EndFrame() defer g.ctx.EndFrame()
if err := g.uploadImages(g.drawOps.allImageOps); err != nil { if err := g.uploadImages(g.drawOps.allImageOps); err != nil {
@@ -305,6 +303,7 @@ func (g *compute) Frame() error {
if err := g.render(tileDims); err != nil { if err := g.render(tileDims); err != nil {
return err return err
} }
g.ctx.BindFramebuffer(defFBO)
g.blitOutput(viewport) g.blitOutput(viewport)
g.cache.frame() g.cache.frame()
g.drawOps.pathCache.frame() g.drawOps.pathCache.frame()
@@ -331,7 +330,6 @@ func (g *compute) Profile() string {
// shader can only write to RGBA textures, but since we actually render in sRGB // shader can only write to RGBA textures, but since we actually render in sRGB
// format we can't use glBlitFramebuffer, because it does sRGB conversion. // format we can't use glBlitFramebuffer, because it does sRGB conversion.
func (g *compute) blitOutput(viewport image.Point) { func (g *compute) blitOutput(viewport image.Point) {
g.ctx.BindFramebuffer(g.defFBO)
g.ctx.Viewport(0, 0, viewport.X, viewport.Y) g.ctx.Viewport(0, 0, viewport.X, viewport.Y)
g.ctx.BindTexture(0, g.output.image) g.ctx.BindTexture(0, g.output.image)
g.ctx.BindProgram(g.output.blitProg) g.ctx.BindProgram(g.output.blitProg)
+4 -3
View File
@@ -167,9 +167,10 @@ func NewBackend(ctx Context) (*Backend, error) {
return b, nil return b, nil
} }
func (b *Backend) BeginFrame() { func (b *Backend) BeginFrame() backend.Framebuffer {
// Assume GL state is reset between frames. // Assume GL state is reset between frames.
b.state = glstate{} b.state = glstate{}
return b.currentFramebuffer()
} }
func (b *Backend) EndFrame() { func (b *Backend) EndFrame() {
@@ -228,7 +229,7 @@ func (b *Backend) NewFramebuffer(tex backend.Texture, depthBits int) (backend.Fr
return fbo, nil return fbo, nil
} }
func (b *Backend) CurrentFramebuffer() backend.Framebuffer { func (b *Backend) currentFramebuffer() backend.Framebuffer {
fboID := glimpl.Framebuffer(b.funcs.GetBinding(glimpl.FRAMEBUFFER_BINDING)) fboID := glimpl.Framebuffer(b.funcs.GetBinding(glimpl.FRAMEBUFFER_BINDING))
return &gpuFramebuffer{backend: b, obj: fboID, foreign: true} return &gpuFramebuffer{backend: b, obj: fboID, foreign: true}
} }
@@ -802,7 +803,7 @@ func (f *gpuFramebuffer) Invalidate() {
func (f *gpuFramebuffer) Release() { func (f *gpuFramebuffer) Release() {
if f.foreign { if f.foreign {
panic("cannot release framebuffer created by CurrentFramebuffer") panic("framebuffer not created by NewBuffer")
} }
f.backend.funcs.DeleteFramebuffer(f.obj) f.backend.funcs.DeleteFramebuffer(f.obj)
if f.hasDepth { if f.hasDepth {
+5 -8
View File
@@ -48,7 +48,6 @@ type GPU interface {
type gpu struct { type gpu struct {
cache *resourceCache cache *resourceCache
defFBO backend.Framebuffer
profile string profile string
timers *timers timers *timers
frameStart time.Time frameStart time.Time
@@ -395,10 +394,8 @@ func New(ctx backend.Device) (GPU, error) {
} }
func newGPU(ctx backend.Device) (*gpu, error) { func newGPU(ctx backend.Device) (*gpu, error) {
defFBO := ctx.CurrentFramebuffer()
g := &gpu{ g := &gpu{
defFBO: defFBO, cache: newResourceCache(),
cache: newResourceCache(),
} }
g.drawOps.pathCache = newOpCache() g.drawOps.pathCache = newOpCache()
if err := g.init(ctx); err != nil { if err := g.init(ctx); err != nil {
@@ -443,7 +440,7 @@ func (g *gpu) Collect(viewport image.Point, frameOps *op.Ops) {
} }
func (g *gpu) Frame() error { func (g *gpu) Frame() error {
g.ctx.BeginFrame() defFBO := g.ctx.BeginFrame()
defer g.ctx.EndFrame() defer g.ctx.EndFrame()
viewport := g.renderer.blitter.viewport viewport := g.renderer.blitter.viewport
for _, img := range g.drawOps.imageOps { for _, img := range g.drawOps.imageOps {
@@ -452,7 +449,7 @@ func (g *gpu) Frame() error {
if g.drawOps.profile { if g.drawOps.profile {
g.zopsTimer.begin() g.zopsTimer.begin()
} }
g.ctx.BindFramebuffer(g.defFBO) g.ctx.BindFramebuffer(defFBO)
g.ctx.DepthFunc(backend.DepthFuncGreater) g.ctx.DepthFunc(backend.DepthFuncGreater)
// Note that Clear must be before ClearDepth if nothing else is rendered // Note that Clear must be before ClearDepth if nothing else is rendered
// (len(zimageOps) == 0). If not, the Fairphone 2 will corrupt the depth buffer. // (len(zimageOps) == 0). If not, the Fairphone 2 will corrupt the depth buffer.
@@ -472,13 +469,13 @@ func (g *gpu) Frame() error {
g.renderer.intersect(g.drawOps.imageOps) g.renderer.intersect(g.drawOps.imageOps)
g.stencilTimer.end() g.stencilTimer.end()
g.coverTimer.begin() g.coverTimer.begin()
g.ctx.BindFramebuffer(g.defFBO) g.ctx.BindFramebuffer(defFBO)
g.ctx.Viewport(0, 0, viewport.X, viewport.Y) g.ctx.Viewport(0, 0, viewport.X, viewport.Y)
g.renderer.drawOps(g.cache, g.drawOps.imageOps) g.renderer.drawOps(g.cache, g.drawOps.imageOps)
g.ctx.SetBlend(false) g.ctx.SetBlend(false)
g.renderer.pather.stenciler.invalidateFBO() g.renderer.pather.stenciler.invalidateFBO()
g.coverTimer.end() g.coverTimer.end()
g.ctx.BindFramebuffer(g.defFBO) g.ctx.BindFramebuffer(defFBO)
g.cleanupTimer.begin() g.cleanupTimer.begin()
g.cache.frame() g.cache.frame()
g.drawOps.pathCache.frame() g.drawOps.pathCache.frame()