Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What happens when you divide by 0 in a shader?

Branching is known to be particularly computationally expensive in a OpenGL ES shader. In such a shader, I check if a value is null before dividing by it, for example:

if(value == 0.0)
    other_value = 0.0;
else
    other_value = 1.0 / value;

In order to speed things up, I would like to avoid this if by doing directly:

other_value = 1.0 / value;

I wonder what happened if value happens to equal 0, which is a bit rare in my treatment, this is why it is not trivial to test it. Does the shader crash? Does the application crash?

like image 406
Stéphane Péchard Avatar asked Apr 27 '11 10:04

Stéphane Péchard


2 Answers

Instead of

float invert_value(in float value)
{
if(value == 0.0)
    return 0.0;
else
    return 1.0 / value;
}

you can write

float invert_value_ifless(in float value)
{
float sign_value = sign(value);
float sign_value_squared = sign_value*sign_value;
return sign_value_squared / ( value + sign_value_squared - 1.0);
}

This returns exactly what you want and has

  1. no ifs
  2. no divisions by 0

I am not sure if this is actually any faster on recent hardware with predication though.

like image 122
Leszek Avatar answered Oct 21 '22 10:10

Leszek


Undefined indeed.

On the iPad simulator, dividing the red component by 0.0 gives 0 (all red is gone from this picture).

enter image description here

On the iPad hardware, dividing the r component by 0.0 saturates it to full red (ie +infinity clamped).

enter image description here

So no, you can't rely on undefined behavior at all to produce a consistent result, but nothing bad happens by dividing by 0 in and of itself.

In my shader, I'm dividing rgb values by alpha. It just so happens that if the alpha value is 0, the pixel doesn't show up anyway, so I don't have a problem with the division going either way (giving 0 or +inf).

like image 44
bobobobo Avatar answered Oct 21 '22 10:10

bobobobo