如何将纹理存储模式设置为“私有”以从“CVMetalTextureCacheCreateTextureFromImage”创建纹理?

Posted

技术标签:

【中文标题】如何将纹理存储模式设置为“私有”以从“CVMetalTextureCacheCreateTextureFromImage”创建纹理?【英文标题】:How to set texture storage mode to `private` to texture created from `CVMetalTextureCacheCreateTextureFromImage`? 【发布时间】:2020-11-06 20:18:44 【问题描述】:

Xcode 的GPU frame capture 将多个表达式突出显示为紫色,并说我应该将纹理存储模式设置为private,因为只有 GPU 可以访问它。我正在尝试修复紫色建议。

Memory Usage'Texture:0x10499ae00 "CoreVideo 0x6000017f2bc0"' 具有存储模式 'Managed' 但仅由 GPU 访问

当使用device.makeBuffer(bytes:length:options:)创建MTLTexture时,我可以在参数options中将storageMode设置为private

但是当从CVPixelBufferCVMetalTextureCacheCreateTextureFromImage()创建MTLTexture时,我不知道如何为创建的纹理配置存储模式。

我尝试过的方法:

将纹理属性字典传递给CVMetalTextureCacheCreateTextureFromImage(..., _ textureAttributes: CFDictionary?, ...) 中的textureAttributes 参数
var textureAttrs: [String: Any] = [:]
if #available(macOS 10.15, *) 
    textureAttrs[kCVMetalTextureStorageMode as String] = MTLStorageMode.private

CVMetalTextureCacheCreateTextureFromImage(,,,textureAttrs as CFDictionary,..., &texture)

if let texture = texture,
    let metalTexture = CVMetalTextureGetTexture(texture) 
        print(metalTexture.storageMode.rawValue)
    


我的操作系统已经是 10.15.4,但创建的 MTLTexture 仍然有 storageMode 作为 managed/rawValue: 1

将相同的属性传递给CVMetalTextureCacheCreate(),这会在cacheAttributestextureAttributes 中为CVMetalTextureCacheCreateTextureFromImage 创建缓存。

结果是一样的。

问题:

是我的属性字典设置了错误的键值对吗?苹果文档没有描述需要设置哪些键和值。 或者有正确的配置方式 还是目前还不支持?

参考资料:

makeBuffer(bytes:length:options:) CVMetalTextureCacheCreateTextureFromImage(::::::::_:) CVMetalTextureCacheCreate(::::_:) maxOS 10.15+ kCVMetalTextureStorageMode

【问题讨论】:

我也遇到了同样的问题...你找到什么了吗? @vtruant 还没有。还在等待答案。 【参考方案1】:

我有使用 Metal 的经验并且遇到过同样的问题。没有办法改变纹理storageMode 一个苍蝇。您必须使用所需的storageMode 创建另一个MTLTexture 并使用MTLBlitCommandEncoder 将数据复制到其中。

这是我项目中的一段代码:

    MTLTextureDescriptor* descriptor = [[MTLTextureDescriptor alloc] init];
    descriptor.storageMode = MTLStorageModePrivate;
    descriptor.pixelFormat = MTLPixelFormatRGBA8Unorm;
    descriptor.width = width;
    descriptor.height = height;

    id<MTLTexture> texture = [__metal_device newTextureWithDescriptor: descriptor];

    if ((data != NULL) && (size > 0)) 
        id<MTLCommandQueue> command_queue = [__metal_device newCommandQueue];
        id<MTLCommandBuffer> command_buffer = [command_queue commandBuffer];
        id<MTLBlitCommandEncoder> command_encoder = [command_buffer blitCommandEncoder];
        id<MTLBuffer> buffer = [__metal_device newBufferWithBytes: data
                                                           length: size
                                                          options: MTLResourceStorageModeShared];
        [command_encoder copyFromBuffer: buffer
                           sourceOffset: 0
                      sourceBytesPerRow: (width * 4)
                    sourceBytesPerImage: (width * height * 4)
                             sourceSize: (MTLSize) width, height, 1 
                              toTexture: texture
                       destinationSlice: 0
                       destinationLevel: 0
                      destinationOrigin: (MTLOrigin) 0, 0, 0 ];

        [command_encoder endEncoding];
        [command_buffer commit];
        [command_buffer waitUntilCompleted];
    

【讨论】:

【参考方案2】:

要设置纹理属性 - 您可以使用 rawValueMTLStorageMode。例如:

    var textureAttrs: [String: Any] = [:]
    
    if #available(macOS 10.15, *) 
        result[kCVMetalTextureStorageMode as String] = MTLStorageMode.managed.rawValue
    

    var textureCache: CVMetalTextureCache!
    let textureCache = CVMetalTextureCacheCreate(
            nil, nil, device, textureAttrs as CFDictionary, &self.textureCache)

使用这些纹理属性创建缓存后,您可以在创建每个纹理时将 nil 作为纹理属性传递给 CVMetalTextureCacheCreateTextureFromImage,因为它将使用创建缓存时使用的任何存储模式。例如:

      var cvTexture: CVMetalTexture?
      CVMetalTextureCacheCreateTextureFromImage(nil, textureCache, pixelBuffer, nil, .bgra8Unorm, width, height, 0, &cvTexture)

注意事项 - 我在 Xcode 中收到金属警告,提示我的纹理应该设为私有而不是托管,但是在将缓存设置为私有存储模式时,出现以下错误:

failed assertion 'Texture Descriptor Validation iosurface textures must use MTLStorageModeManaged'

这是因为这些纹理是 IOSurface 支持的。所以现在我一直在管理它。

【讨论】:

以上是关于如何将纹理存储模式设置为“私有”以从“CVMetalTextureCacheCreateTextureFromImage”创建纹理?的主要内容,如果未能解决你的问题,请参考以下文章

如何运行 sql 脚本以从 java 代码更新 Derby 模式?

如何从Blender导出fbx纹理以用于Monogame

如何在Matlab中将字符串存储在xml中以从opencv读取它

如何将私有存储库分支也设为私有?

从旧的 Git 提交中删除私有信息

将 SQL Server 存储过程转换为 Oracle 过程以从表中查询