11

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

我不知道这两个东西增加了多少性能,但特别是因为我们在集成图形芯片上支持 SM2.0,效率低下是一个问题。那么,传入纹理而不使用它是否意味着任何额外的开销?并且使用if简单的动作来添加几条指令还是会因为停顿等而严重影响事情,比如在进行 CPU 优化时?

4

1 回答 1

22

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

现在,可以通过三种方式处理分支:

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

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

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

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

因为片段组具有屏幕上的位置,所以如果您的分支具有相似的屏幕上的位置,这会有所帮助。看这张图:


(来源:nvidia.com

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

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

附加参考:GPU Gems 2: Chapter 34. GPU Flow-Control Idioms

于 2011-03-19T12:17:31.777 回答