有条件的OpenGL ES最佳实践

时间:2013-07-25 08:24:35

标签: ios opengl-es-2.0 shader

如果可能的话,Apple在他们的着色器最佳实践中avoid branching说,特别是在着色器中计算出的值的分支。所以我用内置的if函数替换了一些clamp()语句。我的问题是,clamp()min()max()可能更有效,还是只是简单地扩展到if块的便利(即宏)功能?

我意识到答案可能依赖于实现。在任何情况下,函数显然都更清晰,并且明确了编译器可以做某事的意图。

1 个答案:

答案 0 :(得分:9)

从历史上来说,GPU支持每个片段指令(例如MINMAX)的时间比支持任意条件分支的时间长得多。桌面OpenGL中的一个示例是GL_ARB_fragment_program扩展(现在由GLSL取代),它明确声明它不支持分支,但它确实提供了MINMAX的指令。以及其他一些条件指示。

我非常有信心,鉴于着色器中min()max()clamp()的共同点,所有GPU仍然会为这些操作提供专用硬件。规范无法保证这一点,因为实现可以优化代码,但是在现实世界中,您应该使用GLSL的内置函数而不是自己编写。

唯一的例外是如果使用条件来避免大量额外的片段处理。在某些时候,分支的成本将低于运行分支中所有代码的成本,但是这里的平衡将非常依赖于硬件,您必须进行基准测试以确定它是否真的有助于您的应用程序目标硬件。这就是我的意思:

void main() {
    vec3 N = ...;
    vec3 L = ...;
    float NDotL = dot(N, L);
    if (NDotL > 0.0)
    {
        // Lots of very intensive code for an awesome shadowing algorithm that we
        // want to avoid wasting time on if the fragment is facing away from the light
    }
}

只需将NDotL钳位到0-1,然后始终只处理每个片段上的影子代码,只需将NDotL乘以最终影子词,这是NDotL的大量浪费。最初< = 0,理论上我们可以通过分支避免这种开销。这种事情并不总是表现胜利的原因在于它非常依赖于硬件如何实现着色器分支。