Conditional expressions and division by 0

I understand that all but the most high-end graphics cards do not do true branching, but evaluate both branches and then pick one result. Normally, I can live with that. But I’ve run into a case where evaluating the wrong branch causes a division by 0, crashing the driver, and I don’t know how to fix it.

The specific expression is

(q <= 0.0)? v : floor( v * q + vec3(0.5) ) / q

where q is a uniform float and v is a local vec3. Any ideas?

Actually, I’d be a bit concerned that a divide-by-zero is crashing something. It should come up with garbage, not crash.

However, you could add to ‘q’ something suitably insignificantly small for whatever the values of ‘q’ are. That shouldn’t through off the computation too much, and it would keep you from dividing by zero. Just make sure it isn’t too small; GPUs are only required to have 24-bits of precision and none of them handle denormalized floats.

Don’t forget the case of q== -epsilon :slight_smile:
So, one way is:
(q <= 0.0)? v : floor( v * q + vec3(0.5) ) / ((abs(q)+0.0001)

and the other is a trick to the compiler, producing slower code and requiring Shader3 gpu:
vec3 result;
for(;;){
if(q<=0.0){ result=v; break; }else{result = floor( v * q + vec3(0.5) ) / q; break;}
}

Could it be that your shader is actually being emulated? PerfHUD might be doing this afaik. (can’t install perfhud on my win2k to test…)

I suppose it’s possible. I know how to find out on the Mac, but not on Windows, and the floating point exception happened on Windows. But wait, emulated by what? Apple has a software renderer capable of handling GLSL, but Microsoft doesn’t.

I don’t know what PerfHUD is, so I suppose that means I’m not using it.

Thanks for the suggestions, but I decided to use different shader code depending on whether q is zero or not, eliminating the branch.

Here is what you can do to avoid that division by 0:

float safeq = (q <= 0.0) ? 1.0 : q;

then your expression use safeq instead of q in the result part:

(q <= 0.0)? v : floor( v * safeq + vec3(0.5) ) / safeq

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.