【问题标题】:How do I use MetalKit texture loader with Metal heaps?如何将 MetalKit 纹理加载器与金属堆一起使用?
【发布时间】:2018-08-12 22:40:12
【问题描述】:

我有一组金属纹理,它们作为纹理集存储在 Xcode 资产目录中。我正在使用MTKTextureLoader.newTexture(name:scaleFactor:bundle:options) 加载这些内容。

然后我使用 MTLArgumentEncoder 将所有纹理编码到 Metal 2 参数缓冲区中。

这很好用。但是,Introducing Metal 2 WWDC 2017 会议recommends combining argument buffers with resource heaps for even better performance,我非常想尝试一下。根据Argument Buffer documentation,您不必在参数缓冲区中的每个纹理上调用MTLRenderCommandEncoder.useResource,只需在分配纹理的堆上调用useHeap

但是,我还没有找到将MTKTextureLoaderMTLHeap 一起使用的简单方法。它似乎没有从堆中分配纹理的加载选项。

我猜的方法是:

  • MTKTextureLoader加载纹理
  • 为每个纹理逆向设计一组MTLTextureDescriptor 对象
  • 使用纹理描述符创建大小合适的MTLHeap
  • MTLHeap 分配一组新的纹理
  • 使用某种方法复制纹理,可能是replaceBytes,甚至可能是MTLBlitCommandEncoder
  • 释放使用MTKTextureLoader 加载的原始纹理

这似乎是一个相当冗长的方法,我还没有看到任何这样的例子,所以我想我会先在这里问一下,以防我遗漏了一些明显的东西。

我是否应该放弃MTKTextureLoader,并搜索一些关于从资产目录加载纹理的 pre-MetalKit 艺术?

我正在使用 Swift,但很高兴接受 Objective-C 的答案。

【问题讨论】:

    标签: metal xcasset metalkit


    【解决方案1】:

    嗯,我上面概述的方法似乎有效。正如预测的那样,它相当冗长。我很想知道是否有人有更优雅的东西。

    enum MetalError: Error {
        case anErrorOccured
    }
    
    extension MTLTexture {
        var descriptor: MTLTextureDescriptor {
            let descriptor = MTLTextureDescriptor()
            descriptor.width = width
            descriptor.height = height
            descriptor.depth = depth
            descriptor.textureType = textureType
            descriptor.cpuCacheMode = cpuCacheMode
            descriptor.storageMode = storageMode
            descriptor.pixelFormat = pixelFormat
            descriptor.arrayLength = arrayLength
            descriptor.mipmapLevelCount = mipmapLevelCount
            descriptor.sampleCount = sampleCount
            descriptor.usage = usage
            return descriptor
        }
    
        var size: MTLSize {
            return MTLSize(width: width, height: height, depth: depth)
        }
    }
    
    extension MTKTextureLoader {
        func newHeap(withTexturesNamed names: [String], queue: MTLCommandQueue, scaleFactor: CGFloat, bundle: Bundle?, options: [MTKTextureLoader.Option : Any]?, onCompletion: (([MTLTexture]) -> Void)?) throws -> MTLHeap {
            let device = queue.device
            let sourceTextures = try names.map { name in
                return try newTexture(name: name, scaleFactor: scaleFactor, bundle: bundle, options: options)
            }
            let storageMode: MTLStorageMode = .private
            let descriptors: [MTLTextureDescriptor] = sourceTextures.map { source in
                let desc = source.descriptor
                desc.storageMode = storageMode
                return desc
            }
            let sizeAligns = descriptors.map { device.heapTextureSizeAndAlign(descriptor: $0) }
            let heapDescriptor = MTLHeapDescriptor()
            heapDescriptor.size = sizeAligns.reduce(0) { $0 + $1.size }
            heapDescriptor.cpuCacheMode = descriptors[0].cpuCacheMode
            heapDescriptor.storageMode = storageMode
            guard let heap = device.makeHeap(descriptor: heapDescriptor),
                let buffer = queue.makeCommandBuffer(),
                let blit = buffer.makeBlitCommandEncoder()
                else {
                throw MetalError.anErrorOccured
            }
            let destTextures = descriptors.map { descriptor in
                return heap.makeTexture(descriptor: descriptor)
            }
            let origin = MTLOrigin()
            zip(sourceTextures, destTextures).forEach {(source, dest) in
                blit.copy(from: source, sourceSlice: 0, sourceLevel: 0, sourceOrigin: origin, sourceSize: source.size, to: dest, destinationSlice: 0, destinationLevel: 0, destinationOrigin: origin)
                blit.generateMipmaps(for: dest)
            }
            blit.endEncoding()
            buffer.addCompletedHandler { _ in
                onCompletion?(destTextures)
            }
            buffer.commit()
            return heap
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2020-10-29
      • 2018-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-24
      • 2019-05-18
      相关资源
      最近更新 更多