gpt4 book ai didi

c++ - OSX MetalKit CVMetalTextureCacheCreateTextureFromImage失败,状态:-6660

转载 作者:行者123 更新时间:2023-12-01 14:48:43 44 4
gpt4 key购买 nike

我正在尝试首先从 RAW 内存中制作CVPixelBuffer然后是MTLTexture中的CVPixelBuffer,但是
运行以下代码后,我总是出错

CVMetalTextureCacheCreateTextureFromImage failed, status: -6660 0x0



这个错误是从哪里来的?
    id<MTLTexture> makeTextureWithBytes(id<MTLDevice> mtl_device, 
int width,
int height,
void *baseAddress, int bytesPerRow)
{

CVMetalTextureCacheRef textureCache = NULL;

CVReturn status = CVMetalTextureCacheCreate(kCFAllocatorDefault, nullptr, mtl_device, nullptr, &textureCache);
if(status != kCVReturnSuccess || textureCache == NULL)
{
return nullptr;
}

NSDictionary* cvBufferProperties = @{
(__bridge NSString*)kCVPixelBufferOpenGLCompatibilityKey : @YES,
(__bridge NSString*)kCVPixelBufferMetalCompatibilityKey : @YES,
};

CVPixelBufferRef pxbuffer = NULL;

status = CVPixelBufferCreateWithBytes(kCFAllocatorDefault,
width,
height,
kCVPixelFormatType_32BGRA,
baseAddress,
bytesPerRow,
releaseCallback,
NULL/*releaseRefCon*/,
(__bridge CFDictionaryRef)cvBufferProperties,
&pxbuffer);

if(status != kCVReturnSuccess || pxbuffer == NULL)
{
return nullptr;
}

CVMetalTextureRef cvTexture = NULL;

status = CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
textureCache,
pxbuffer,
nullptr,
MTLPixelFormatBGRA8Unorm,
1920,
1080,
0,
&cvTexture);

if(status != kCVReturnSuccess || cvTexture == NULL)
{
std::cout << "CVMetalTextureCacheCreateTextureFromImage failed, status: " << status << " " << cvTexture << std::endl;
return nullptr;
}
id<MTLTexture> metalTexture = CVMetalTextureGetTexture(cvTexture);

CFRelease(cvTexture);

return metalTexture;
}

最佳答案

IOSurface不支持CVPixelBuffer时,会发生错误。但是,您不能从字节制作IOSurface支持的CVPixelBuffer。因此,尽管设置了kCVPixelBufferMetalCompatibilityKey,但CVPixelBufferCreateWithBytes(及其平面对应项)仍不会使用IOSurface支持缓冲区。

两种解决方法(可能的第三种)

  • 创建一个空的CVpixelBuffer并使用memcpy。您需要在每个循环中创建一个新的pixelbuffer,因此建议使用PixelBufferPool。
  • CVPixelBufferPoolRef pixelPool; // initialised prior
    void *srcBaseAddress; // initialised prior

    CVPixelBufferRef currentFrame;
    CVPixelBufferPoolCreatePixelBuffer(nil, pixelPool, &currentFrame);

    CVPixelBufferLockBaseAddress(currentFrame,0);
    void *cvBaseAddress=CVPixelBufferGetBaseAddress(currentFrame);
    size_t size= CVPixelBufferGetDataSize(currentFrame);
    memcpy(cvBaseAddress,srcBaseAddress,size);
  • 完全跳过CVPixelBuffer并直接写入MTLTexture内存;只要金属支持您的像素格式。但是,由于可能要渲染为RGB显示,因此可以编写自己的金属内核以转换为RGB。请记住首先使用metalTextureDescriptor制作纹理。
  • id<MTLDevice> metalDevice; // You know how to get this
    unsigned int width; // from your source image data
    unsigned int height;// from your source image data
    unsigned int rowBytes; // from your source image data

    MTLTextureDescriptor *mtd = [MTLTextureDescriptor
    texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRG422
    width:width
    height:height
    mipmapped:NO];

    id<MTLTexture> mtlTexture = [metalDevice newTextureWithDescriptor:mtd];


    [mtlTexture replaceRegion:MTLRegionMake2D(0,0,width,height)
    mipmapLevel:0
    withBytes:srcBaseAddress
    bytesPerRow:rowBytes];

    第三种方法可能是将CVPixelBuffer转换为CIImage,并使用金属支持的CIContext。像这样的东西;
    id<MTLDevice> metalDevice;
    CIContext* ciContext = [CIContext contextWithMTLDevice:metalDevice
    options:[NSDictionary dictionaryWithObjectsAndKeys:@(NO),kCIContextUseSoftwareRenderer,nil]
    ];
    CIImage *inputImage = [[CIImage alloc] initWithCVPixelBuffer:currentFrame];

    [ciContext render:inputImage
    toMTLTexture:metalTexture
    commandBuffer:metalCommandBuffer
    bounds:viewRect
    colorSpace:colorSpace];

    我成功地使用它来直接渲染到CAMetalLayer的可绘制纹理,但是没有足够的运气来渲染中间纹理(不是我非常努力地使其工作),希望其中的一项对您有用。

    关于c++ - OSX MetalKit CVMetalTextureCacheCreateTextureFromImage失败,状态:-6660,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60303458/

    44 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com