PDA

View Full Version : can for loops terminate with a uniform?



cyrfer
06-30-2010, 12:13 PM
Hi,
I'm trying to do something that I think many people want to do, but I have not found evidence that it is possible. I have had success terminating a for loop with a compile-time constant (preprocessor define NUM_LIGHTS), but I have not had good results when using an uniform to terminate the for loop in a fragment shader. I'm testing on a NVIDIA GeForce 8800 GTX, with very recent drivers. Thanks!


PS. For example, should this code work?

[FRAGMENT SHADER]

#ifndef MAX_LIGHTS
#define MAX_LIGHTS 4
#endif // MAX_LIGHTS

uniform vec4 light_position_vs[MAX_LIGHTS];

uniform int light_count;

void main()
{
for(unsigned int i=0; i<light_count; ++i)
{
vec4 L = light_position_vs[i];
}
}

aqnuep
06-30-2010, 01:58 PM
As far as I remember uniform based for loops are in fact supported by SM4 based cards like the GF8 series, however indexing with uniforms into a uniform array is not supported, only by SM5 cards so your code won't work in that form.

aqnuep
06-30-2010, 02:13 PM
To be more precise indexing into a uniform array can be happen only with a constant expression, that's why this for loop is not working.
When you have a constant in the termination condition of a for loop and you do the uniform array indexing, it works, but that not proves that the problem is with your for loop. If you use a constant, then the compiler will unroll the for loop and so the uniform array indexing is done with constant indices, but it cannot unroll if the termination condition contains a uniform as it is not known at compile time so there the indexing is not done with constant expression and that's why this shader does not compile.

cyrfer
06-30-2010, 02:35 PM
Hi,
Interesting. The shader actually compiles, but the contents of the for loop seem to be ignored. I'm a little confused because I don't think of my loop index variable as being a uniform. Only the termination variable is a uniform. Regardless, it looks like I have another reason to want a SM5 card, the coding just gets easier.
Thanks for the reply.

Alfonse Reinheart
06-30-2010, 03:47 PM
To be more precise indexing into a uniform array can be happen only with a constant expression, that's why this for loop is not working.

That's not true at all. Accessing uniform arrays with non-constant expressions has been around forever. Since the days of assembly shaders and ARB_vertex_program.

somboon
06-30-2010, 05:00 PM
Hi Alfonse , can you give a little detail about this issue ?

I am also facing problem about adding dynamic lighting support to my forward-rendering code path.

what kind of hardware/OpenGL version support index into array with uniform ?

Alfonse Reinheart
06-30-2010, 05:42 PM
Hi Alfonse , can you give a little detail about this issue ?

Not really. The OP hasn't provided enough information to diagnose and correct his problem. I only posted because I saw some blatantly incorrect information and moved to correct it before anyone got the wrong idea.


what kind of hardware/OpenGL version support index into array with uniform ?

I thought "Accessing uniform arrays with non-constant expressions has been around forever. Since the days of assembly shaders and ARB_vertex_program," was clear enough. I'm not sure how I can make that clearer. If you can use shaders at all, then you can access uniform arrays with non-constant expressions.

Dark Photon
06-30-2010, 06:11 PM
As I recall when working with this, one of the cons for using uniform arrays is glGetActiveUniform() did not return the "used" length of the uniform array in the shader code, it returned the "max" dimensioned length always. So you had to know the shader guts to know how many array elements the shader needs populated.

Been about a year since I did that test so if that's a bug (my read is it is), then maybe it's been fixed by now... Might double-check if you care.

Alfonse Reinheart
06-30-2010, 08:24 PM
As I recall when working with this, one of the cons for using uniform arrays is glGetActiveUniform() did not return the "used" length of the uniform array in the shader code, it returned the "max" dimensioned length always.

The length of any array must be a compile-time constant. So I'm not sure what the difference between the "used" length and "max" length is supposed to be.

Dark Photon
07-01-2010, 05:27 AM
The length of any array must be a compile-time constant. So I'm not sure what the difference between the "used" length and "max" length is supposed to be.


If one or more elements of an array are active, the name of the array is returned in name, the type is returned in type, and the size parameter returns the highest array element index [B]used, plus one, as determined by the compiler and/or linker. Only one active uniform variable will be reported for a uniform array.

uniform vec4 light_diffuse[10];

...reference light_diffuse[0]
...reference light_diffuse[1]

From this, I'd presume that "used" length (active length) was 2 above, and max length is 10.

Similar to how general uniforms clearly declared in the shader are not returned by glGetActiveUniform() if they are not referenced in the shader code. That's pretty much the purpose of this call, to distinguish declared from actually used by the code.

Alfonse Reinheart
07-01-2010, 12:01 PM
But if you're not using a compile-time constant as an index, you can't determine the "used" size and therefore must assume that the entire range is used.

This is an optimization, like active uniforms vs. non-active uniforms. If implementations don't want to take advantage of the potential to optimize them, so be it.