I'm trying to render to a MTLTexture
within an MTKView
and then pull the entire region back off the GPU and have an alpha pixel values of clear RGBA=0x00000000 really come off the GPU as just that -- in those regions where I haven't drawn anything.
Instead, all un-rendered areas come off as bright red, which is typical for how Metal renders areas on-screen that have otherwise not been rendered to by a vertex/fragment shader.
However, I've narrowed it down to this test case -- in which I don't actually render anything and send a clear texture on a round trip to the GPU and back:
MTLStorageModeManaged
)I'm baffled.
Here's the setup:
CGSize textureSize = CGSizeMake(1920,1080);
// create metalTextureDescriptor
MTLTextureDescriptor *metalTextureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm
width:textureSize.width height:textureSize.height mipmapped:NO];
metalTextureDescriptor.storageMode = MTLStorageModeManaged;
metalTextureDescriptor.usage = MTLTextureUsageUnknown;
// create clear Texture
vector_uchar4 clearPixel = {0x00,0x00,0x00,0x00};
id<MTLTexture> clearTexture = [self fillTextureOfSize:textureSize withPixel:clearPixel];
// pull texture off GPU
id<MTLCommandBuffer> commandBuffer = [metalCommandQueue commandBuffer];
id<MTLTexture> testTexture = [self pullTextureOffGPU:clearTexture
withCommandBuffer:commandBuffer];
// a bunch of other rendering (I leave 'testTexture' untouched)
[commandBuffer commit];
[commandBuffer waitUntilCompleted];
// I then check out the pixels
[self debugTexture:testTexture];
At this point, when I break in the debug texture routine (below), the pixel bytes seen are 0x0000ffff and not the expected 0x00000000.
-(id<MTLTexture>)fillTextureOfSize:(CGSize)size withPixel:(vector_uchar4)pixel
{
id<MTLTexture> texture = [self.device newTextureWithDescriptor:metalTextureDescriptor];
NSUInteger pixelCount = size.width*size.height;
vector_uchar4 *buff = malloc(pixelCount*sizeof(vector_uchar4));
for (NSUInteger i=0; i<pixelCount; i++)
buff[i]=pixel;
[blackTexture replaceRegion:MTLRegionMake2D(0, 0, size.width, size.height)
mipmapLevel:0
withBytes:buff
bytesPerRow:size.width*sizeof(vector_uchar4)];
free(buff);
return texture;
}
-(id<MTLTexture>) pullTextureOffGPU:(id<MTLTexture>)inputTexture
withCommandBuffer:(id<MTLCommandBuffer>)commandBuffer
{
id<MTLTexture> retTexture = [self.device newTextureWithDescriptor:metalTextureDescriptor];
if (retTexture) {
id<MTLBlitCommandEncoder> blit = [commandBuffer blitCommandEncoder];
[blit copyFromTexture:inputTexture
sourceSlice:0
sourceLevel:0
sourceOrigin:MTLOriginMake(0, 0, 0)
sourceSize:MTLSizeMake(inputTexture.width,inputTexture.height,1)
toTexture:retTexture
destinationSlice:0
destinationLevel:0
destinationOrigin:MTLOriginMake(0, 0, 0)];
[blit synchronizeTexture:retTexture slice:0 level:0];
[blit endEncoding];
}
return retTexture;
}
-(void)debugTexture:(id<MTLTexture>)theTexture
{
NSInteger width = theTexture.width;
NSInteger height = theTexture.height;
void *buffer = malloc(width*height*4);
[theTexture getBytes:buffer
bytesPerRow:width*4
fromRegion:MTLRegionMake2D(0,0,width,height)
mipmapLevel:0];
free(buffer); // break here to examine buffer
}
User contributions licensed under CC BY-SA 3.0