dmitri.shuralyov.com/gpu/mtl/...

add BlitCommandEncoder.CopyFromTexture, Texture.ReplaceRegion

These were needed for a Metal API-based driver for x/exp/shiny.
dmitshur committed 2 weeks ago commit 666a987793e9432fbb48592aa2f3bf3463685dfa
mtl.go
@@ -549,10 +549,40 @@ func (rce RenderCommandEncoder) DrawPrimitives(typ PrimitiveType, vertexStart, v
 // Reference: https://developer.apple.com/documentation/metal/mtlblitcommandencoder.
 type BlitCommandEncoder struct {
 	CommandEncoder
 }
 
+// CopyFromTexture encodes a command to copy image data from a slice of
+// a source texture into a slice of a destination texture.
+//
+// Reference: https://developer.apple.com/documentation/metal/mtlblitcommandencoder/1400754-copyfromtexture.
+func (bce BlitCommandEncoder) CopyFromTexture(
+	src Texture, srcSlice, srcLevel int, srcOrigin Origin, srcSize Size,
+	dst Texture, dstSlice, dstLevel int, dstOrigin Origin,
+) {
+	C.BlitCommandEncoder_CopyFromTexture(
+		bce.commandEncoder,
+		src.texture, C.uint_t(srcSlice), C.uint_t(srcLevel),
+		C.struct_Origin{
+			X: C.uint_t(srcOrigin.X),
+			Y: C.uint_t(srcOrigin.Y),
+			Z: C.uint_t(srcOrigin.Z),
+		},
+		C.struct_Size{
+			Width:  C.uint_t(srcSize.Width),
+			Height: C.uint_t(srcSize.Height),
+			Depth:  C.uint_t(srcSize.Depth),
+		},
+		dst.texture, C.uint_t(dstSlice), C.uint_t(dstLevel),
+		C.struct_Origin{
+			X: C.uint_t(dstOrigin.X),
+			Y: C.uint_t(dstOrigin.Y),
+			Z: C.uint_t(dstOrigin.Z),
+		},
+	)
+}
+
 // Synchronize flushes any copy of the specified resource from its corresponding
 // Device caches and, if needed, invalidates any CPU caches.
 //
 // Reference: https://developer.apple.com/documentation/metal/mtlblitcommandencoder/1400775-synchronize.
 func (bce BlitCommandEncoder) Synchronize(resource Resource) {
@@ -600,10 +630,29 @@ func NewTexture(texture unsafe.Pointer) Texture {
 }
 
 // resource implements the Resource interface.
 func (t Texture) resource() unsafe.Pointer { return t.texture }
 
+// ReplaceRegion copies a block of pixels into a section of texture slice 0.
+//
+// Reference: https://developer.apple.com/documentation/metal/mtltexture/1515464-replaceregion.
+func (t Texture) ReplaceRegion(region Region, level int, pixelBytes *byte, bytesPerRow uintptr) {
+	r := C.struct_Region{
+		Origin: C.struct_Origin{
+			X: C.uint_t(region.Origin.X),
+			Y: C.uint_t(region.Origin.Y),
+			Z: C.uint_t(region.Origin.Z),
+		},
+		Size: C.struct_Size{
+			Width:  C.uint_t(region.Size.Width),
+			Height: C.uint_t(region.Size.Height),
+			Depth:  C.uint_t(region.Size.Depth),
+		},
+	}
+	C.Texture_ReplaceRegion(t.texture, r, C.uint_t(level), unsafe.Pointer(pixelBytes), C.size_t(bytesPerRow))
+}
+
 // GetBytes copies a block of pixels from the storage allocation of texture
 // slice zero into system memory at a specified address.
 //
 // Reference: https://developer.apple.com/documentation/metal/mtltexture/1515751-getbytes.
 func (t Texture) GetBytes(pixelBytes *byte, bytesPerRow uintptr, region Region, level int) {
mtl.h
@@ -97,10 +97,14 @@ void CommandEncoder_EndEncoding(void * commandEncoder);
 void RenderCommandEncoder_SetRenderPipelineState(void * renderCommandEncoder, void * renderPipelineState);
 void RenderCommandEncoder_SetVertexBuffer(void * renderCommandEncoder, void * buffer, uint_t offset, uint_t index);
 void RenderCommandEncoder_SetVertexBytes(void * renderCommandEncoder, const void * bytes, size_t length, uint_t index);
 void RenderCommandEncoder_DrawPrimitives(void * renderCommandEncoder, uint8_t primitiveType, uint_t vertexStart, uint_t vertexCount);
 
+void BlitCommandEncoder_CopyFromTexture(void * blitCommandEncoder,
+	void * srcTexture, uint_t srcSlice, uint_t srcLevel, struct Origin srcOrigin, struct Size srcSize,
+	void * dstTexture, uint_t dstSlice, uint_t dstLevel, struct Origin dstOrigin);
 void BlitCommandEncoder_Synchronize(void * blitCommandEncoder, void * resource);
 
 void * Library_MakeFunction(void * library, const char * name);
 
+void Texture_ReplaceRegion(void * texture, struct Region region, uint_t level, void * pixelBytes, size_t bytesPerRow);
 void Texture_GetBytes(void * texture, void * pixelBytes, size_t bytesPerRow, struct Region region, uint_t level);
mtl.m
@@ -154,18 +154,39 @@ void RenderCommandEncoder_DrawPrimitives(void * renderCommandEncoder, uint8_t pr
 	[(id<MTLRenderCommandEncoder>)renderCommandEncoder drawPrimitives:(MTLPrimitiveType)primitiveType
 	                                                      vertexStart:(NSUInteger)vertexStart
 	                                                      vertexCount:(NSUInteger)vertexCount];
 }
 
+void BlitCommandEncoder_CopyFromTexture(void * blitCommandEncoder,
+	void * srcTexture, uint_t srcSlice, uint_t srcLevel, struct Origin srcOrigin, struct Size srcSize,
+	void * dstTexture, uint_t dstSlice, uint_t dstLevel, struct Origin dstOrigin) {
+	[(id<MTLBlitCommandEncoder>)blitCommandEncoder copyFromTexture:(id<MTLTexture>)srcTexture
+	                                                   sourceSlice:(NSUInteger)srcSlice
+	                                                   sourceLevel:(NSUInteger)srcLevel
+	                                                  sourceOrigin:(MTLOrigin){srcOrigin.X, srcOrigin.Y, srcOrigin.Z}
+	                                                    sourceSize:(MTLSize){srcSize.Width, srcSize.Height, srcSize.Depth}
+	                                                     toTexture:(id<MTLTexture>)dstTexture
+	                                              destinationSlice:(NSUInteger)dstSlice
+	                                              destinationLevel:(NSUInteger)dstLevel
+	                                             destinationOrigin:(MTLOrigin){dstOrigin.X, dstOrigin.Y, dstOrigin.Z}];
+}
+
 void BlitCommandEncoder_Synchronize(void * blitCommandEncoder, void * resource) {
 	[(id<MTLBlitCommandEncoder>)blitCommandEncoder synchronizeResource:(id<MTLResource>)resource];
 }
 
 void * Library_MakeFunction(void * library, const char * name) {
 	return [(id<MTLLibrary>)library newFunctionWithName:[NSString stringWithUTF8String:name]];
 }
 
+void Texture_ReplaceRegion(void * texture, struct Region region, uint_t level, void * pixelBytes, size_t bytesPerRow) {
+	[(id<MTLTexture>)texture replaceRegion:(MTLRegion){{region.Origin.X, region.Origin.Y, region.Origin.Z}, {region.Size.Width, region.Size.Height, region.Size.Depth}}
+	                           mipmapLevel:(NSUInteger)level
+	                             withBytes:(void *)pixelBytes
+	                           bytesPerRow:(NSUInteger)bytesPerRow];
+}
+
 void Texture_GetBytes(void * texture, void * pixelBytes, size_t bytesPerRow, struct Region region, uint_t level) {
 	[(id<MTLTexture>)texture getBytes:(void *)pixelBytes
 	                      bytesPerRow:(NSUInteger)bytesPerRow
 	                       fromRegion:(MTLRegion){{region.Origin.X, region.Origin.Y, region.Origin.Z}, {region.Size.Width, region.Size.Height, region.Size.Depth}}
 	                      mipmapLevel:(NSUInteger)level];