如何将纹理存储模式设置为“私有”以从“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
。
但是当从CVPixelBuffer
到CVMetalTextureCacheCreateTextureFromImage()
创建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()
,这会在cacheAttributes
和textureAttributes
中为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】:要设置纹理属性 - 您可以使用 rawValue
或 MTLStorageMode
。例如:
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 模式?