Shader optimization: Is a ternary operator equivalent to branching?

sharoz picture sharoz · Feb 6, 2011 · Viewed 18.1k times · Source

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!

Answer

Olhovsky picture Olhovsky · Feb 6, 2011

A ternary operator is just syntactic sugar for an if statement. They are the same.

If you had more to write inside of your if statement, there might be some optimization that could be done here, but with so little inside of either branch, there is nothing to optimize really.

Often branching is not used by default.

In your case, the ternary operator (or if statement) is probably evaluating both sides of the condition first and then discarding the branch that was not satisfied by the condition.

In order to use branching, you need to set the branching compiler flag in your shader code, to generate assembly that instructs the GPU to actually attempt to branch (if the GPU supports branching). In that case, the GPU will try to branch only if the branch predictor says that some predefined number of cores will take one of the branches.

Your mileage may vary from one compiler and GPU to another.