From f842178ac7aa36f8c12af57d54549810bbd75234 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Mon, 13 Sep 2021 07:21:18 +0200 Subject: [PATCH] gpu/internal/metal: don't copy padding during images transfers Don't copy the padding when stride is larger than the width. Applies to Texture.Upload and Framebuffer.ReadPixels. Signed-off-by: Elias Naur --- gpu/internal/metal/metal_darwin.go | 34 +++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/gpu/internal/metal/metal_darwin.go b/gpu/internal/metal/metal_darwin.go index d170a2f6..ba0ded5f 100644 --- a/gpu/internal/metal/metal_darwin.go +++ b/gpu/internal/metal/metal_darwin.go @@ -918,9 +918,18 @@ func (t *Texture) Upload(offset, size image.Point, pixels []byte, stride int) { if stride == 0 { stride = size.X * 4 } - buf, off := t.backend.stagingBuffer(len(pixels)) - store := bufferSlice(buf, off, len(pixels)) - copy(store, pixels) + dstStride := size.X * 4 + n := size.Y * dstStride + buf, off := t.backend.stagingBuffer(n) + store := bufferSlice(buf, off, n) + var srcOff, dstOff int + for y := 0; y < size.Y; y++ { + srcRow := pixels[srcOff : srcOff+dstStride] + dstRow := store[dstOff : dstOff+dstStride] + copy(dstRow, srcRow) + dstOff += dstStride + srcOff += stride + } enc := t.backend.startBlit() orig := C.MTLOrigin{ x: C.NSUInteger(offset.X), @@ -931,7 +940,7 @@ func (t *Texture) Upload(offset, size image.Point, pixels []byte, stride int) { height: C.NSUInteger(size.Y), depth: 1, } - C.blitEncCopyBufferToTexture(enc, buf, t.texture, C.NSUInteger(off), C.NSUInteger(stride), C.NSUInteger(len(store)), msize, orig) + C.blitEncCopyBufferToTexture(enc, buf, t.texture, C.NSUInteger(off), C.NSUInteger(dstStride), C.NSUInteger(len(store)), msize, orig) } func (t *Texture) Release() { @@ -1135,12 +1144,21 @@ func (f *Framebuffer) ReadPixels(src image.Rectangle, pixels []byte, stride int) height: C.NSUInteger(sz.Y), depth: 1, } - buf, off := f.backend.stagingBuffer(len(pixels)) + 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(stride), C.NSUInteger(len(pixels)), msize, orig) + C.blitEncCopyTextureToBuffer(enc, f.texture, buf, C.NSUInteger(off), C.NSUInteger(stageStride), C.NSUInteger(n), msize, orig) f.backend.endCmdBuffer(true) - store := bufferSlice(buf, off, len(pixels)) - copy(pixels, store) + store := bufferSlice(buf, off, n) + var srcOff, dstOff int + for y := 0; y < sz.Y; y++ { + dstRow := pixels[srcOff : srcOff+stageStride] + srcRow := store[dstOff : dstOff+stageStride] + copy(dstRow, srcRow) + dstOff += stageStride + srcOff += stride + } return nil }