swift - Metal:将 MTLRenderCommandEncoder 纹理加载限制为仅部分纹理

标签 swift textures metal

我确实有一个 Metal 渲染管道设置,它对渲染命令进行编码并在 texture: MTLTexture 对象上进行操作以加载和存储输出。此纹理相当大,并且每个渲染命令仅对整个纹理的一小部分进行操作。基本设置大致如下:

// texture: MTLTexture, pipelineState: MTLRenderPipelineState, commandBuffer: MTLCommandBuffer

// create and setup MTLRenderPassDescriptor with loadAction = .load
let renderPassDescriptor = MTLRenderPassDescriptor()
if let attachment = self.renderPassDescriptor?.colorAttachments[0] {
    attachment.clearColor = MTLClearColorMake(0.0, 0.0, 0.0, 0.0)
    attachment.texture = texture // texture size is rather large
    attachment.loadAction = .load
    attachment.storeAction = .store
}

// create MTLRenderCommandEncoder
guard let renderCommandEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor) else { return }

// limit rendering to small fraction of texture
let scissorRect = CGRect(origin: CGPoint.zero, size: 0.1 * CGSize(width: CGFloat(texture.width), height: CGFloat(texture.height))) // create rect begin small fraction of texture rect
let metalScissorRect = MTLScissorRect(x: Int(scissorRect.origin.x), y: Int(scissorRect.origin.y), width: Int(scissorRect.width), height: Int(scissorRect.height))
            renderCommandEncoder.setScissorRect(metalScissorRect)

renderCommandEncoder.setRenderPipelineState(pipelineState)
renderCommandEncoder.setScissorRect(metalScissorRect)

// encode some commands here

renderCommandEncoder.endEncoding()

实际上,会创建许多 renderCommandEncoder 对象,每次只对一小部分纹理进行操作。 不幸的是,每次提交renderCommandEncoder时,整个纹理都会被加载并存储在最后,这是由renderPassDescriptor指定的,因为相应的设置其 colorAttachment loadActionstoreAction

我的问题是:
是否可以将加载和存储过程限制在纹理的区域?(以避免在仅加载和存储纹理的大部分时浪费计算时间)需要一小部分)

最佳答案

避免将整个纹理加载和存储到渲染管道中的一种方法可能如下,假设您的剪刀矩形在绘制调用之间保持不变:

  1. Blit (MTLBlitCommandEncoder) 将感兴趣的区域从大纹理转移到较小的(例如剪刀矩形的大小)中间纹理。

  2. 仅在较小的中间纹理上加载和存储以及绘制/操作。

  3. 完成编码后,将结果位 block 传输回较大纹理的原始源区域。

通过这种方式,您可以在管道中仅加载和存储感兴趣的区域,仅增加维护较小的中间纹理所需的恒定内存成本(假设感兴趣的区域在绘制调用之间是恒定的)。

Blitting 是一种快速操作,因此上述方法应该优化您当前的管道。

关于swift - Metal:将 MTLRenderCommandEncoder 纹理加载限制为仅部分纹理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59111013/

相关文章:

ios - 字符串到 int 的转换不能快速工作

ios - 写入 MTLTexture 会导致 fatal error

ios - 当图像较小时,MPSImageIntegral 返回全零

arrays - String.init(stringInterpolation :) with an array of strings

ios - BLE 设备在 cancelPeripheralConnection 后重新连接(如何忘记 BLE 设备?)

Swift DispatchQueue 与 Firebase 同步

ios - OpenGL ES 纹理不渲染

opengl - glSubTexImage 会阻塞吗?

ios - 如何限制 gcd 队列缓冲区大小

ios - 我在哪里正确初始化我的 MTLCommandBuffer?