金属Alpha通道奇数

时间:2019-01-01 22:06:56

标签: metal metalkit

我试图在MTLTexture内渲染到MTKView,然后将整个区域拉回GPU,并让清晰的RGBA = 0x00000000的alpha像素值真正从GPU脱离就是这样-在那些我什么都没画的区域。

相反,所有未渲染的区域都会变成鲜红色,这对于Metal如何在屏幕上渲染顶点/片段着色器无法渲染的区域来说很典型。

但是,我将其范围缩小到此测试用例-在这种情况下,我实际上不渲染任何东西,而是在往返于GPU并返回的情况下发送清晰的纹理:

  • 我用0x00000000像素值创建自己的纹理('clearTexture')
  • 此纹理结束了GPU(MTLStorageModeManaged
  • 然后我将纹理从GPU('testTexture')中拉出
  • 我抓住那个纹理的像素字节
  • 我注意到什么?像素值为0x0000ffff(纯红色)

我很困惑。

这是设置:

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
}

0 个答案:

没有答案