ios - 如何在 Metal 中组合使用不同着色器的渲染命令编码器

标签 ios swift graphics metal stencil-buffer

我正在用 Metal 编写一个图形引擎,并使用模板缓冲区来掩盖场景中球谐光覆盖的体积。为此,我使用两个着色器,每个灯光需要 3 次绘制调用:一个用于背面,另一个用于正面,最后使用不同的着色器进行绘制调用以实际渲染灯光。

但是,如果我很好地理解 Metal 文档,您需要“静态”定义所有 channel ,也就是说,您需要为您使用的每个着色器和渲染表面配置使用不同的渲染命令编码器。这是正确的吗?

这意味着我最终为我的灯光创建了这个循环,这感觉非常可怕,因为我正在创建很多编码器,

for l in shLights {
    let descStencil = createLightAccumulationRenderPass()
    guard let encoderStencil = commandBuffer.makeRenderCommandEncoder(descriptor: descStencil) else {
        continue
    }
    drawSHLightStencil(l, encoder: encoderStencil)
    encoderStencil.endEncoding()
    let descColor = createLightAccumulationRenderPass()
    guard let encoderColor = commandBuffer.makeRenderCommandEncoder(descriptor: descColor) else {
        continue
    }
    drawSHLight(l, encoder: encoderColor)
    encoderColor.endEncoding()
}

完整代码在这里:https://github.com/endavid/VidEngine/blob/master/VidFramework/VidFramework/sdk/gfx/plugins/DeferredLightingPlugin.swift (drawSHLights 函数)

如果您需要有关如何使用它的更多背景信息,请查看此博文:http://endavid.com/index.php?entry=85

我也尝试过重用编码器,但如果您不调用 endEncoding,Metal 会在下次调用 makeRenderCommandEncoder 时崩溃。

是否可以以任何方式组合这些编码器?

编辑: 我已经进行了 GPU 捕获,因此可以更轻松地查看整个渲染管道。这是屏幕截图,

GPU capture

它很小,但我在上面贴了一些标签。白色标签对应于循环中的内容。场景中有 3 个灯光,它们照亮了 3 个球体。

最佳答案

But, if I understood well Metal documentation, you need to define all your passes "statically", that is, you need a different Render Command Encoder for every shader and render surfaces configurations that you use. Is this correct?

不,这并不完全正确。您会注意到渲染命令编码器的一些属性是在创建编码器时通过 MTLRenderPassDescriptor 指定的,并且在创建编码器之后还通过编码器上的访问器设置了其他属性已经被创造了。前者在编码器的生命周期内是不可变的。后者可以更改。

因此,如果更改渲染目标(附件),您确实需要一个新的命令编码器。但您不需要需要新的命令编码器来更改着色器。着色器由渲染管道状态指定,并且可以使用 setRenderPipelineState(_:) 在现有命令编码器上进行更改。

如果可能的话,您确实应该在应用程序的生命周期中创建一次渲染管道状态对象。但此后您可以根据需要多次重复使用它们。

最后,我不会太担心创建多个渲染命令编码器。它们的设计成本相对较低。因此,虽然花费一些精力来将给定编码器可以完成的所有工作整合在一起很好,但当它违背事物的工作原理时,不要竭尽全力试图使某些东西变得“更简单”。

关于ios - 如何在 Metal 中组合使用不同着色器的渲染命令编码器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55442494/

相关文章:

ios - ABAddressBook:是否可以获取源的名称?

swift - 了解 Swift 中 map 函数的简写闭包语法

c++ - 在 C++ 中将 RGB 转换为 HSL

matlab - 沿曲线移动点(3D 动画图)

ios - Interface Builder 中的 WKWebView

ios - 在 View Controller 中播放视频

ios - 为什么 breaking-retain-cycle 不会像这样陷入无限循环?

ios - 在 SwiftUI 中创建 ViewModifier 和 View 扩展的区别

ios - 将委托(delegate)添加到 CalloutView

graphics - 博赫斯与图形