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
}
func (b *Backend) BeginFrame() {
func (b *Backend) BeginFrame() backend.Framebuffer {
return b.currentFramebuffer()
}
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
}
func (b *Backend) CurrentFramebuffer() backend.Framebuffer {
func (b *Backend) currentFramebuffer() backend.Framebuffer {
renderTarget := b.dev.ctx.OMGetRenderTargets()
if renderTarget != nil {
// Assume someone else is holding on to it.
_IUnknownRelease(unsafe.Pointer(renderTarget), renderTarget.vtbl.Release)
}
if renderTarget == b.fbo.renderTarget {
if b.fbo != nil && renderTarget == b.fbo.renderTarget {
return b.fbo
}
return &Framebuffer{dev: b.dev, renderTarget: renderTarget, foreign: true}
@@ -823,7 +824,7 @@ func (f *Framebuffer) Invalidate() {
func (f *Framebuffer) Release() {
if f.foreign {
panic("cannot release Framebuffer from CurrentFramebuffer")
panic("framebuffer not created by NewBuffer")
}
if f.renderTarget != nil {
_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
// operations.
type Device interface {
BeginFrame()
BeginFrame() Framebuffer
EndFrame()
Caps() Caps
NewTimer() Timer
@@ -20,7 +20,6 @@ type Device interface {
// are valid at the point of call.
IsTimeContinuous() bool
NewTexture(format TextureFormat, width, height int, minFilter, magFilter TextureFilter, bindings BufferBinding) (Texture, error)
CurrentFramebuffer() Framebuffer
NewFramebuffer(tex Texture, depthBits int) (Framebuffer, error)
NewImmutableBuffer(typ BufferBinding, data []byte) (Buffer, error)
NewBuffer(typ BufferBinding, size int) (Buffer, error)
+2 -4
View File
@@ -29,7 +29,6 @@ type compute struct {
cache *resourceCache
maxTextureDim int
defFBO backend.Framebuffer
programs struct {
elements backend.Program
tileAlloc backend.Program
@@ -197,7 +196,6 @@ func newCompute(ctx backend.Device) (*compute, error) {
}
g := &compute{
ctx: ctx,
defFBO: ctx.CurrentFramebuffer(),
cache: newResourceCache(),
maxTextureDim: maxDim,
conf: new(config),
@@ -290,7 +288,7 @@ func (g *compute) Frame() error {
Y: (viewport.Y + tileHeightPx - 1) / tileHeightPx,
}
g.ctx.BeginFrame()
defFBO := g.ctx.BeginFrame()
defer g.ctx.EndFrame()
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 {
return err
}
g.ctx.BindFramebuffer(defFBO)
g.blitOutput(viewport)
g.cache.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
// format we can't use glBlitFramebuffer, because it does sRGB conversion.
func (g *compute) blitOutput(viewport image.Point) {
g.ctx.BindFramebuffer(g.defFBO)
g.ctx.Viewport(0, 0, viewport.X, viewport.Y)
g.ctx.BindTexture(0, g.output.image)
g.ctx.BindProgram(g.output.blitProg)
+4 -3
View File
@@ -167,9 +167,10 @@ func NewBackend(ctx Context) (*Backend, error) {
return b, nil
}
func (b *Backend) BeginFrame() {
func (b *Backend) BeginFrame() backend.Framebuffer {
// Assume GL state is reset between frames.
b.state = glstate{}
return b.currentFramebuffer()
}
func (b *Backend) EndFrame() {
@@ -228,7 +229,7 @@ func (b *Backend) NewFramebuffer(tex backend.Texture, depthBits int) (backend.Fr
return fbo, nil
}
func (b *Backend) CurrentFramebuffer() backend.Framebuffer {
func (b *Backend) currentFramebuffer() backend.Framebuffer {
fboID := glimpl.Framebuffer(b.funcs.GetBinding(glimpl.FRAMEBUFFER_BINDING))
return &gpuFramebuffer{backend: b, obj: fboID, foreign: true}
}
@@ -802,7 +803,7 @@ func (f *gpuFramebuffer) Invalidate() {
func (f *gpuFramebuffer) Release() {
if f.foreign {
panic("cannot release framebuffer created by CurrentFramebuffer")
panic("framebuffer not created by NewBuffer")
}
f.backend.funcs.DeleteFramebuffer(f.obj)
if f.hasDepth {
+5 -8
View File
@@ -48,7 +48,6 @@ type GPU interface {
type gpu struct {
cache *resourceCache
defFBO backend.Framebuffer
profile string
timers *timers
frameStart time.Time
@@ -395,10 +394,8 @@ func New(ctx backend.Device) (GPU, error) {
}
func newGPU(ctx backend.Device) (*gpu, error) {
defFBO := ctx.CurrentFramebuffer()
g := &gpu{
defFBO: defFBO,
cache: newResourceCache(),
cache: newResourceCache(),
}
g.drawOps.pathCache = newOpCache()
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 {
g.ctx.BeginFrame()
defFBO := g.ctx.BeginFrame()
defer g.ctx.EndFrame()
viewport := g.renderer.blitter.viewport
for _, img := range g.drawOps.imageOps {
@@ -452,7 +449,7 @@ func (g *gpu) Frame() error {
if g.drawOps.profile {
g.zopsTimer.begin()
}
g.ctx.BindFramebuffer(g.defFBO)
g.ctx.BindFramebuffer(defFBO)
g.ctx.DepthFunc(backend.DepthFuncGreater)
// 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.
@@ -472,13 +469,13 @@ func (g *gpu) Frame() error {
g.renderer.intersect(g.drawOps.imageOps)
g.stencilTimer.end()
g.coverTimer.begin()
g.ctx.BindFramebuffer(g.defFBO)
g.ctx.BindFramebuffer(defFBO)
g.ctx.Viewport(0, 0, viewport.X, viewport.Y)
g.renderer.drawOps(g.cache, g.drawOps.imageOps)
g.ctx.SetBlend(false)
g.renderer.pather.stenciler.invalidateFBO()
g.coverTimer.end()
g.ctx.BindFramebuffer(g.defFBO)
g.ctx.BindFramebuffer(defFBO)
g.cleanupTimer.begin()
g.cache.frame()
g.drawOps.pathCache.frame()