4
$\begingroup$

I have this GLSL function that I am trying to optimize because it is going to be ran on many pixels of an older devices GPU. There is no room for branching inefficiency. Essentially this function returns a 0 or a 1 based on the variables actualY shouldY and state

float val = 0.0;
if (actualY < shouldY) {
    val = 1.0;
}

if (state >= 20.0 && state < 40.0) { //The equal/not equals is VERY important
  return 1.0 - val;
}
return val;

Usually I am fairly good at removing branching from GLSL code but I really don't know what to do with the range check for the state variable.

$\endgroup$
  • 2
    $\begingroup$ Are you sure that the code you've written results in branches? Most simple if statements are compiled to parallel evaluation with a multiply-add to select the desired output. You should check with the profiling tool that goes with your target GPU. $\endgroup$ – Dan Hulme Dec 22 '17 at 10:28
9
$\begingroup$

This could be done that way:

First condition is float val = 1.0-step(shouldY, ActualY);

Then, the condition: state >= 20.0 && state < 40.0 can be changed to

step(20.0, state) - step(40.0, state). This equals 0.0 if outside of range and 1.0 if inside.

Let a = step(20.0, state) - step(40.0, state)

Then we know that mix function:

genType mix(genType x,
    genType y,
    genType a);

Is $$x * (1 - a) + y * a = val * (1 - a) + (1 - val) * a = val - 2*a*val + a$$

So final code is:

float val = 1.0-step(shouldY, ActualY);
float a = step(20.0, state) - step(40.0, state);
return val - 2.0*a*val + a;
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.