Can for loops terminate with a uniform?

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];
}
}

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.

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.

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.

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.

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 ?

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.

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.

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.

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.

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.

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