gpu: fold driver.Framebuffer functionality into driver.Texture

driver.Device.NewFramebuffer doesn't provide additional information over
driver.Device.NewTexture, so Texture can hold its (optional) framebuffer
on behalf of the renderers. Metal don't even need a separate framebuffer
object.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2021-09-19 19:36:48 +02:00
parent b599a6d1c5
commit 0bdd24c51e
9 changed files with 135 additions and 204 deletions
+18 -37
View File
@@ -407,6 +407,7 @@ type Texture struct {
sampler C.CFTypeRef
width int
height int
foreign bool
}
type Shader struct {
@@ -424,12 +425,6 @@ type Pipeline struct {
topology C.MTLPrimitiveType
}
type Framebuffer struct {
backend *Backend
texture C.CFTypeRef
foreign bool
}
type Buffer struct {
backend *Backend
size int
@@ -469,7 +464,7 @@ func newMetalDevice(api driver.Metal) (driver.Device, error) {
return b, nil
}
func (b *Backend) BeginFrame(target driver.RenderTarget, clear bool, viewport image.Point) driver.Framebuffer {
func (b *Backend) BeginFrame(target driver.RenderTarget, clear bool, viewport image.Point) driver.Texture {
if b.lastCmdBuffer != 0 {
C.cmdBufferWaitUntilCompleted(b.lastCmdBuffer)
b.stagingOff = 0
@@ -477,13 +472,11 @@ func (b *Backend) BeginFrame(target driver.RenderTarget, clear bool, viewport im
if target == nil {
return nil
}
var texture C.CFTypeRef
switch t := target.(type) {
case driver.MetalRenderTarget:
texture = C.CFTypeRef(t.Texture)
return &Framebuffer{texture: texture, foreign: true}
case *Framebuffer:
texture = C.CFTypeRef(t.texture)
texture := C.CFTypeRef(t.Texture)
return &Texture{texture: texture, foreign: true}
case *Texture:
return t
default:
panic(fmt.Sprintf("metal: unsupported render target type: %T", t))
@@ -503,10 +496,10 @@ func (b *Backend) startBlit() C.CFTypeRef {
return b.blitEnc
}
func (b *Backend) CopyTexture(dst driver.Texture, dorig image.Point, src driver.Framebuffer, srect image.Rectangle) {
func (b *Backend) CopyTexture(dst driver.Texture, dorig image.Point, src driver.Texture, srect image.Rectangle) {
enc := b.startBlit()
dstTex := dst.(*Texture).texture
srcTex := src.(*Framebuffer).texture
srcTex := src.(*Texture).texture
ssz := srect.Size()
C.blitEncCopyFromTexture(
enc,
@@ -718,13 +711,6 @@ func pixelFormatFor(f driver.TextureFormat) C.MTLPixelFormat {
}
}
func (b *Backend) NewFramebuffer(tex driver.Texture) (driver.Framebuffer, error) {
t := tex.(*Texture)
C.CFRetain(t.texture)
fbo := &Framebuffer{backend: b, texture: t.texture}
return fbo, nil
}
func (b *Backend) NewBuffer(typ driver.BufferBinding, size int) (driver.Buffer, error) {
// Transfer buffer contents in command encoders on every use for
// smaller buffers. The advantage is that buffer re-use during a frame
@@ -921,6 +907,9 @@ func (t *Texture) Upload(offset, size image.Point, pixels []byte, stride int) {
}
func (t *Texture) Release() {
if t.foreign {
panic("metal: release of external texture")
}
C.CFRelease(t.texture)
C.CFRelease(t.sampler)
*t = Texture{}
@@ -1076,7 +1065,7 @@ func (b *Buffer) Release() {
*b = Buffer{}
}
func (f *Framebuffer) ReadPixels(src image.Rectangle, pixels []byte, stride int) error {
func (t *Texture) ReadPixels(src image.Rectangle, pixels []byte, stride int) error {
if len(pixels) == 0 {
return nil
}
@@ -1092,10 +1081,10 @@ func (f *Framebuffer) ReadPixels(src image.Rectangle, pixels []byte, stride int)
}
stageStride := sz.X * 4
n := sz.Y * stageStride
buf, off := f.backend.stagingBuffer(n)
enc := f.backend.startBlit()
C.blitEncCopyTextureToBuffer(enc, f.texture, buf, C.NSUInteger(off), C.NSUInteger(stageStride), C.NSUInteger(n), msize, orig)
f.backend.endCmdBuffer(true)
buf, off := t.backend.stagingBuffer(n)
enc := t.backend.startBlit()
C.blitEncCopyTextureToBuffer(enc, t.texture, buf, C.NSUInteger(off), C.NSUInteger(stageStride), C.NSUInteger(n), msize, orig)
t.backend.endCmdBuffer(true)
store := bufferSlice(buf, off, n)
var srcOff, dstOff int
for y := 0; y < sz.Y; y++ {
@@ -1108,10 +1097,10 @@ func (f *Framebuffer) ReadPixels(src image.Rectangle, pixels []byte, stride int)
return nil
}
func (b *Backend) BeginRenderPass(fbo driver.Framebuffer, d driver.LoadDesc) {
func (b *Backend) BeginRenderPass(tex driver.Texture, d driver.LoadDesc) {
b.endEncoder()
b.ensureCmdBuffer()
f := fbo.(*Framebuffer)
f := tex.(*Texture)
col := d.ClearColor
var act C.MTLLoadAction
switch d.Action {
@@ -1151,12 +1140,4 @@ func (b *Backend) endEncoder() {
}
}
func (f *Framebuffer) Release() {
if f.foreign {
panic("metal: invalid release of external framebuffer")
}
C.CFRelease(f.texture)
*f = Framebuffer{}
}
func (f *Framebuffer) ImplementsRenderTarget() {}
func (f *Texture) ImplementsRenderTarget() {}