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

时间:2011-03-17 14:15:11

标签: rendering shader hlsl pixel-shader

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

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

1 个答案:

答案 0 :(得分:20)

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

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

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

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

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

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

因为片段组具有屏幕上的位置,所以如果您的分支具有类似的屏幕上位置,则会有所帮助。见下图:

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

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

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

其他参考:GPU Gems 2: Chapter 34. GPU Flow-Control Idioms