Conditionals in a Fragment Shader

I currently have a master shader that I customize as I compile it by tagging the appropriate last line on, which defines the main I need. It handles 20 or so different pixel formats, and makes a shader to order to convert to RGBA 16F.

I used this approach to keep conditionals out, based on anecdotal evidence that it’s a ‘bad thing’. Now I’m planning on trying to use OpenSceneGraph as a back-end, and I don’t want to create the shaders on the fly, as it will be on the same thread. My eventual approach will be to compile the ‘pieces’ of my shader, and link it differently depending on what I need though.

For now though, I just want to get rolling, so I’m considering a switch inside a single shader that switches on the source pixel format. Does it still have to be if/else if, or did a switch statement get added yet?

But the real question is, since this shader is running on HD sized video frames, will the conditional every pixel completely kill me, or is workable on modern hardware and drivers? I’m targeting Mac OS 10.5 and later and high end Linux cards with current drivers.

Regards,

Bruce Wheaton

Your question is very valid as still many people are afraid of conditionals in the shaders.

First, switch statement is supported by the GLSL.

Second, conditionals are supported in shaders for a while, but weren’t really efficient in the past. What I can say is that on Shader Model 4.0 hardware it is already fast enough to be practical for general use. Actually, on my ATI card I barely noticed any significant slowdown due to conditionals.

Still, there is no perfect receipt for how to use conditionals efficiently as the behavior of GPUs is quite different between subsequent generations and vendors. For some time it was advised to put conditionals at the beginning of the shaders, after that it was told to spread them as well as possible. My advise is that you should use them in whatever way you wish, just keep their number small and you’ll most probably won’t meet performance issues.

OK, cool. I wonder is there a best way to tell the shader about the conditional to help it between pixels? Like, to tell it that - for this entire pass, this conditional will evaluate to the same path?

Bruce

Most drivers are smart enough to statically detect what can be statically detected and optimized out. For example, this:


if(1 == 1)
{
  //something
}
else
{
  //something else
}

will almost certainly be optimized out. As long as it is compile-time defined, you shouldn’t worry about it.

If it is something based on uniform values, those are not compile-time defined. NVIDIA drivers on Windows had the habit of sometimes recompiling drivers based on uniforms to achieve optimum performance. But that’s not something you should rely on.

I’m targeting Mac OS 10.5 and later and high end Linux cards with current drivers.

If you’re targeting MacOSX, be advised that they still currently only support GL 2.1 (+ extensions) and GLSL v1.20 (+ extensions). Switch statement support was added in GLSL v1.40, so you won’t be able to use that.

Even if this isn’t something that can be optimized at compile/link time, if there is high coherence between adjacent pixels you should be ok. By high coherence, I mean that adjacent pixels in screen space should take the same branch.

Regards,
Patrick

Looks like switch was added in GLSL 1.3, which isn’t on Mac, as you say.

I can do if/else no problem. I can only presume Nvidia’s compiler is smart enough to optimize that the same as a switch, since I’m sure a lot of code hasn’t moved to the newer syntax.

And yes, I should have ‘high coherence’ since in this whole render pass I’m just doing a video sized flat quad to convert colorspaces - every pixel will take the same path.

Bruce