我试图在MTLTexture
内渲染到MTKView
,然后将整个区域拉回GPU,并让清晰的RGBA = 0x00000000的alpha像素值真正从GPU脱离就是这样-在那些我什么都没画的区域。
相反,所有未渲染的区域都会变成鲜红色,这对于Metal如何在屏幕上渲染顶点/片段着色器无法渲染的区域来说很典型。
但是,我将其范围缩小到此测试用例-在这种情况下,我实际上不渲染任何东西,而是在往返于GPU并返回的情况下发送清晰的纹理:
MTLStorageModeManaged
)我很困惑。
这是设置:
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];
此时,当我中断调试纹理例程(如下)时,看到的像素字节为0x0000ffff,而不是预期的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
}