条件和未使用的采样器/纹理添加到SM2/3像素着色器的性能有多大?

Mr.*_*Boy 11 shader rendering hlsl pixel-shader

我们在HLSL中有一个像素着色器,它在一些地方用于稍微不同的东西,因此有几个条件块意味着在某些情况下省略了复杂的功能.同样,这意味着我们将纹理作为采样器参数传递,而这些参数可能并不总是被使用.

我不知道这两件事增加了多少性能,但特别是因为我们在集成图形芯片上支持SM2.0,效率低下是个问题.那么,传递纹理而不使用它意味着任何额外的开销吗?并且使用if简单的行为来添加一些指令,还是会因为停顿等而对其进行大幅度的影响,就像进行CPU优化一样?

And*_*ell 20

在GPU上设置纹理需要一些CPU时间,但与实际批处理成本相比,它相当小.更重要的是,如果着色器从不引用它,它对实际着色器执行应该没有任何影响.

现在,有三种方法可以处理分支:

首先,如果分支条件始终是相同的(如果它只依赖于编译时常量),那么分支的一侧可以完全内联.在许多情况下,如果可以通过这种方式消除重要分支,则可以优先编译着色器的多个版本.

第二种技术是着色器可以评估分支的两侧,然后根据条件选择正确的结果,所有这些都没有实际分支(它是算术的).当分支中的代码很小时,这是最好的.

最后,它实际上可以使用分支指令.首先,分支指令具有适度的指令计数成本.然后是管道.x86有一个很长的串行管道,你可以很容易地停止.GPU具有完全不同的并行管道.

GPU并行评估片段组(像素),一次为多个片段执行一次片段程序.如果组中的所有片段采用相同的分支,那么您只有该分支的执行成本.如果它们采用两个(或更多)分支,则必须对该组碎片执行多次着色器以覆盖所有分支.

由于片段组具有屏幕上的位置,因此如果您的分支具有类似的屏幕上位置,则会有所帮助.见这个图:

http://http.developer.nvidia.com/GPUGems2/elementLinks/34_flow_control_01.jpg

现在,着色器编译器通常可以很好地选择使用最后两种方法中的哪一种(对于第一种方法,编译器将为您内联,但您必须自己制作多个着色器版本).但是,如果您正在优化性能,那么查看编译器的实际输出会很有用.为此,fxc.exe在DirectX SDK Utilities中使用该/Fc <file>选项获取已编译着色器的反汇编视图.

(因为这是性能建议:记住要始终测量你的性能,找出你遇到的限制,然后担心优化它.例如,如果你的纹理获取绑定,优化你的着色器分支没有意义.)

附加参考:GPU Gems 2:第34章.GPU流控制习语.

  • 由于问题中明确提到了SM2硬件,请允许我稍微澄清一下这个非常好的答案:SM2硬件将_always_执行`if`语句的两个分支的指令,然后是条件移动.这与任何条件或模式无关,因为它是所有硬件都能够做到的.对于SM3硬件,分支采用/不采用模式起主要作用,实际分支是便宜的(2-3个周期),但性能等于经线中最慢的分支组合. (2认同)