optimizationgraphicsshader

Shader optimization: Is a ternary operator equivalent to branching?


I'm working on a vertex shader in which I want to conditionally drop some vertices:

float visible = texture(VisibleTexture, index).x;
if (visible > threshold)
    gl_Vertex.z = 9999; // send out of frustum

I know that branches kill performance when there's little commonality between neighboring data. In this case, every other vertex may get a different 'visible' value, which would be bad for the performance of the local shader core cluster (from my understanding).

To my question: Is a ternary operator better (irrespective of readability issues)?

float visible = texture(VisibleTexture, index).x;
gl_Vertex.z = (visible > threshold) ? 9999 : gl_Vertex.z;

If not, is converting it into a calculation worthwhile?

float visible = texture(VisibleTexture, index).x;
visible = sign(visible - threshold) * .5 + .5; // 1=visible, 0=invisible
gl_Vertex.z += 9999 * visible; // original value only for visible

Is there an even better way to drop vertices without relying on a Geometry shader?

Thanks in advance for any help!


Solution

  • Unlike what is said above, if statements and ternary operators are not the same in shaders, and in fact can have a very different performance profile. Note what graphics guru Inigo Quilez (if you don't know him, look him up!) has to say in the comments here: https://www.shadertoy.com/view/4llXD7

    You are also wrong in that the ternary operation uses branches - it doesn't, it uses a conditional moves (CMOV), which does not branch nor pollute the instruction cache or anything.

    You probably have read some of the blog posts out there that are spreading misinformation about this issue; I know a few.

    I tested this myself with HLSL in Unity, using either ifs to simply select a variable based on a condition, or the ternary operator. When doing this in a loop of 50000 on my 3060M, the ifs run at 25FPS, and the ternary condition at 200+, same as if the operation is fully commented out. So Inigo is right, and anything else is misinformation.