Apple 在他们的着色器最佳实践中说到 avoid branching如果可能的话,尤其是对在着色器中计算的值进行分支。所以我用内置的 clamp()
函数替换了一些 if
语句。我的问题是,clamp()
、min()
和 max()
可能更高效,还是它们仅仅是方便(即宏)函数,可以简单地扩展到 if
block ?
我意识到答案可能取决于实现。在任何情况下,这些函数显然都更清晰并且明确了意图,编译器可以用它来做一些事情。
最佳答案
从历史上看,GPU 支持按片段指令(例如 MIN
和 MAX
)的时间比它们支持任意条件分支的时间要长得多。桌面 OpenGL 中的一个示例是 GL_ARB_fragment_program
扩展(现已被 GLSL 取代),它明确声明它不支持分支,但它确实为 MIN
和MAX
以及其他一些条件指令。
鉴于 min()
、max()
和 clamp( )
在着色器中。规范不保证这一点,因为实现可以优化代码,但它认为合适,但在现实世界中,您应该使用 GLSL 的内置函数,而不是自己动手。
唯一的异常(exception)是如果您的条件被用于避免大量额外的片段处理。在某些时候,分支的成本将低于在分支中运行所有代码的成本,但这里的平衡将非常依赖于硬件,您必须进行基准测试以查看它是否真的对您的应用程序有帮助目标硬件。这是我的意思:
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,理论上我们可以通过分支避免这种开销。这种事情并不总是性能获胜的原因是它非常依赖于硬件如何实现着色器分支。
关于ios - 条件的 OpenGL ES 最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17852752/