我正在使用AVFoundation获取相机流。 我正在使用此代码从以下位置获取MTLTextures:
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
id<MTLTexture> texture = nil;
{
size_t width = CVPixelBufferGetWidth(pixelBuffer);
size_t height = CVPixelBufferGetHeight(pixelBuffer);
MTLPixelFormat pixelFormat = MTLPixelFormatBGRA8Unorm;
CVMetalTextureRef metalTextureRef = NULL;
CVReturn status = CVMetalTextureCacheCreateTextureFromImage(NULL, _textureCache, pixelBuffer, NULL, pixelFormat, width, height, 0, &metalTextureRef);
if(status == kCVReturnSuccess)
{
texture = CVMetalTextureGetTexture(metalTextureRef);
if (self.delegate){
[self.delegate textureUpdated:texture];
}
CFRelease(metalTextureRef);
}
}
}
它工作正常,除了生成的 MTLTexture 对象没有被mipmaped(只有一个mip级别)。 在这个电话中:
CVMetalTextureCacheCreateTextureFromImage(NULL, _textureCache, pixelBuffer, NULL, pixelFormat, width, height, 0, &metalTextureRef);
有一个名为“ textureAtributes ”的第三个参数,我认为可以指定我想要mipmaped纹理,但是我没有在文档中找到任何单词完全去那里。我也没有找到传递其他东西而不是NULL的源代码。
对于 iOS 的 OpenGLES ,有类似的方法,参数相同,文档中也没有单词。
答案 0 :(得分:2)
刚收到Metal工程师here的答复。这是一个引用:
不,无法从a生成mipmapped纹理 CVPixelBuffer直接。
CVPixelBuffer 图片通常具有线性/跨步布局,因为非GPU硬件模块可能会与这些模块进行交互,而且大多数GPU 硬件仅支持平铺纹理的mipmapping。你需要 发出一个blit,从线性 MTLTexture 复制到私有 您自己创建的 MTLTexture ,然后生成mipmap。
对于 textureAttributes ,只支持一个键:kCVMetalTextureCacheMaximumTextureAgeKey
答案 1 :(得分:1)
没有一种方法可以直接获取mipmap纹理,但你可以很容易地自己生成一个纹理。
首先使用您的Metal设备创建一个空的Metal纹理,其大小和格式与现有纹理相同,但具有完整的mipmap链。 See newTexture documentation
使用MTLCommandBuffer对象创建blitEncoder对象。 See blitCommandEncoder documentation
使用blitEncoder从相机纹理复制到空纹理。 destinationLevel应为零,因为您只复制顶级mipmap。 See copyFromTexture documentation
最后使用blitEncoder通过调用generateMipmapsForTexture生成所有mip级别。 See generateMipMapsForTexture documentation
在这结束时,你有一个带有完整mip链的相机的金属质感。