Strange behaviour with length()

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.

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.

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.

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?)

Looks like a compiler bug. Someone’s compiler is doing a few too many optimizations and is confusing themselves.

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