文章主要思路来源如下,为方便查找,阐述自己理解于此。
http://theorangeduck.com/page/avoiding-shader-conditionals
在shader里执行条件结构对性能会有很大影响。这是因为除了某些现代GPU可以正确执行分支外,绝大多数GPU都会将所有分支全部执行一遍,然后丢弃错误的结果。除非分支中包含大量代码,否则这样做会严重影响性能。
其次哪怕GPU可以正确执行分支,以片段着色器为例,一个片段采用一个分支而另一个片段不采用该分支,代价等同于所有的片段都执行两个分支。因为对于高度并行的GPU来说,出于同步的要求,最慢的case会造成短板效应。
为了避免这种情况,可以设计一系列的函数来执行通常由条件语句来完成的事情。这些函数执行一些比较,然后对TRUE返回1.0,对False返回0.0。
例如,若希望在某些情况下执行add操作,通常会这样写:
if (x == 0) {
y += 5;
}
这可以转化如下:
y += 5 * when_eq(x, 0)
这样便可以提升效率。
全套函数如下:
vec4 when_eq(vec4 x, vec4 y) {
return 1.0 - abs(sign(x - y));
}
vec4 when_neq(vec4 x, vec4 y) {
return abs(sign(x - y));
}
vec4 when_gt(vec4 x, vec4 y) {
return max(sign(x - y), 0.0);
}
vec4 when_lt(vec4 x, vec4 y) {
return max(sign(y - x), 0.0);
}
vec4 when_ge(vec4 x, vec4 y) {
return 1.0 - when_lt(x, y);
}
vec4 when_le(vec4 x, vec4 y) {
return 1.0 - when_gt(x, y);
}
vec4 and(vec4 a, vec4 b) {
return a * b;
}
vec4 or(vec4 a, vec4 b) {
return min(a + b, 1.0);
}
vec4 xor(vec4 a, vec4 b) {
return (a + b) % 2.0;
}
vec4 not(vec4 a) {
return 1.0 - a;
}
内部函数都已在GLSL中定义。
另外或许你注意到它们都是用的vec4类型,这是因为使用vec4类型,比较是按照组来进行的,这意味着可以同时进行4个比较。
这些函数背后的逻辑都非常简单,也正是智能编译器为了优化条件结构进行的转换。
希望可以帮到你!