金属:我需要多个RenderPipelines才能拥有多个着色器吗?

时间:2017-11-24 07:40:15

标签: ios swift graphics metal

我对金属非常新,所以请耐心等待,因为我正在从丑陋的OpenGL状态机调用过渡到现代图形框架。我真的想确保我理解一切是如何运作的。

我已经阅读了大部分Apples文档,但它更好地描述了各个组件的功能,而不是它们如何结合在一起。

我试图理解我的情况是否应该有多个renderPipelines和renderEncoders。

在高级别描述我的管道是正在发生的事情:

  1. 从渲染到的屏幕外纹理中检索前一帧的内容,并在其上绘制一些新内容。
  2. Swith在屏幕上渲染。将步骤1中的纹理绘制到屏幕上。
  3. 进行一些后期处理(原生分辨率)。
  4. 将ontop上的UI绘制为四边形。 (意图重复2)
  5. 所以本质上会有以下顶点/片段着色器对

    • 绘制实体(步骤1)
    • 在特定区域绘制四边形(步骤2和4)
    • 后处理着色器1(步骤3)使用与D不同的输入,并且无法在同一着色器中完成
    • 后处理着色器2(步骤3)使用与C不同的输入,无法在同一着色器中完成

    将有以下纹理组

    • 每个UI元素的纹理
    • 步骤1中完成的屏幕外绘制的纹理
    • 根据金属性能
    • ,可能会在后期处理中使用更多的屏幕外纹理

    最终我的困惑是:

    • Q1。渲染管道只需要一个顶点和一个片段函数,这是否意味着我需要有4个渲染管道,即使我的绘图程序只有3个独特的步骤?
    • Q2。我怎么能在一个编码器中使用多个管道? .setRenderPipelineState上的每次过度呼叫都不会覆盖之前的呼叫吗?
    • Q3。您是否建议在创建我的编码器后立即保留所有.setFragmentTexture电话,或者我是否需要在需要之前设置这些电话。
    • Q4。即使在pipelineStates之间切换,保持我的depthState是否有效是否有效?如何确保第1步中的实体呈现深度,但确保帧之间的深度信息丢失,以便实体全部位于之前的内容之上?
    • Q5。如何处理渲染步骤3,我有两个后处理步骤?那些必须是单独的管道吗?
    • Q6。我怎么能有效地构建我的管道知道步骤2和4基本上只是用不同的输入相同?

    我想如果有人能指导我完成我需要的renderPipelineObjects以及为什么,这对我有帮助。了解某些renderCommandEncoder命令在伪代码级别上的外观也很有用。

1 个答案:

答案 0 :(得分:4)

  

Q1。渲染管道只需要一个顶点和一个片段函数,所以这意味着我需要有4个渲染管道,即使我的绘图程序只有3个独特的步骤吗?

如果有4种独特的着色器功能组合,那么“我的绘图程序只有3个独特的步骤”是不正确的。在任何情况下,是的,您需要为着色器函数的每个唯一组合(以及您需要更改的渲染管道状态描述符的任何其他属性)单独的渲染管道状态对象。

  

Q2。我怎么能在一个编码器中使用多个管道?不会对.setRenderPipelineState的每次过度调用都覆盖前一个吗?

当您将绘制方法发送到渲染命令编码器时,该绘制命令将使用所有相关的当前状态进行编码并写入命令缓冲区。如果稍后更改与编码器关联的渲染管道状态(不影响先前编码的命令),则仅影响后续编码的命令。

  

Q3。您是否建议在创建编码器后立即保留所有.setFragmentTexture调用,或者我是否需要在需要之前设置它们。

只有需要才能在使用它们的绘图命令进行编码之前设置它们。除此之外,设置它们并不重要。我会为最清晰,最易读的代码做任何事情。

  

Q4。即使我在pipelineStates之间切换,保持我的depthState是否有效?

是的,或者没有单独的方法来独立设置它们。将有一种方法来设置它们。

  

如何确保第1步中的实体呈现深度,但确保帧之间的深度信息丢失,以便实体全部位于之前的内容之上?

在渲染过程描述符中为深度附件配置loadAction以使用适当的值(例如1.0)清除。如果您正在使用多个渲染命令编码器,当然只对第一个执行此操作。同样,最后(或唯一)渲染命令编码器的渲染过程描述符可以/应该使用storeAction .dontCare

  

Q5。如何处理渲染步骤3,我有两个后处理步骤?那些必须是单独的管道吗?

嗯,你的场景的描述有点模糊。但是,如果你想使用不同的着色器函数,那么,是的,你需要使用不同的渲染管道状态对象。

  

Q6。我怎样才能有效地构建我的管道知道步骤2和4基本上只是用不同的输入相同?

同样,您的描述完全过于含糊,无法知道如何回答这个问题。这些步骤在哪些方面相同?他们在哪些方面有所不同?你对不同的输入意味着什么?

在任何情况下,只要看起来像最简单,最直接的方式,即使它似乎效率低下也是如此。以后担心优化。到那时,打开一个新问题并显示您的实际工作代码,并具体询问。