PDA

View Full Version : Strange behaviour with length()



FrankBoltzmann
09-29-2015, 05:40 AM
Hi, I have a very complex piece of shader and this problem will be very hard to replicate so I just need some insights on what might be happening and what I can test to see where exactly the problem is so I can fix it.



float fragdot = length(frag_list[frag_idx].normal);
if (abs(diff) < 0.04 && fragdot > -1.0)
keep = false;


When I have this code, my shader renders nothing.



float fragdot = length(frag_list[frag_idx].normal);
if (abs(diff) < 0.04 && true)
keep = false;


When I have this code, my shader renders properly.

In the first example, shouldn't the length of a vec3 ALWAYS return a value greater or equal to zero? The two code examples should have the same behaviour... unless length has some behaviour that I misread?

Sorry I know these examples are not enough to determine the problem or try to replicate it, but maybe some experts could tell me what could wrong inside that length() function? It compiles perfectly and doesn't freeze or crash the graphics driver.

Alfonse Reinheart
09-29-2015, 06:11 AM
In the first example, shouldn't the length of a vec3 ALWAYS return a value greater or equal to zero?

That depends on whether `frag_list[frag_ix].normal` is a well-defined expression. And if it doesn't contain floating-point NaNs and such. If it does, all bets are off.

FrankBoltzmann
09-29-2015, 08:48 AM
That depends on whether `frag_list[frag_ix].normal` is a well-defined expression. And if it doesn't contain floating-point NaNs and such. If it does, all bets are off.

Thanks for the reply, I forgot to look out for NaNs, that's probably the origin of my problem. This frag_list is an SSBO with an array of structs that have a vec3 "normal" in them, frag_idx is an unsigned int, so either "normal" is not well defined or frag_idx is out of bounds.

FrankBoltzmann
09-29-2015, 09:27 AM
This works properly:


float tmptmp = length(curr_frag.normal);

if (...)
{
if (...)
{
...
}
else
{
for (...)
{
if (abs(diff) < 0.04 && tmptmp > -1.0)
keep = false;

This doesn't:


vec3 tmptmp = curr_frag.normal;

if (...)
{
if (...)
{
...
}
else
{
for (...)
{
if (abs(diff) < 0.04 && length(tmptmp) > -1.0)
keep = false;

I've only moved length() to be calculated later, tmptmp isn't used anywhere else in the code. This implies that tmptmp changes at some point between the declaration of tmptmp and the if statement. If curr_frag.normal is a valid vector when declaring tmptmp (since its length is valid in the first example) then shouldn't tmptmp be valid at all points in the code if no changes were made?

(My code has a lot of branching, I am aware, could this be creating incoherence for my local variables? Maybe too many local variables?)

Alfonse Reinheart
09-29-2015, 09:34 AM
Looks like a compiler bug. Someone's compiler is doing a few too many optimizations and is confusing themselves.