Array access in vertex and fragment programs

Hi,

i’ve been looking all over the place for the answer to this!

by passing an array as a uniform variable to a vertex program, defined with size

 uniform vec4 myArray[50] 

the runtime allows you to populate the array using glUniform4fvARB, and then you can index the array in the vertex program with a variable instead of a compile time constant. This works

However, in a fragment shader, indexing with a variable instead of a compile time constant causes a bad link (no error reported, other than churning out the intermediate assembly code with INVALID written in place of variables in array brackets).

The GLSL spec suggests that this is possible as it doesnt talk about any restrictions, and the ARB registry asks questions on the subject but provides no resolution.

is it possible to address arrays with variables in the fragment processor??

if not, is this intended to be a future addition??

I would be grateful for any insight

Thanks

I don’t think any hardware supports that.

Really? So we can never loop over an array using the loop variable to address it? That’s seems very restricting.

Well even though my 9800xt in work can’t address an array with a variable, my FX5900 at home handles it just fine.

This is definitely something ATI needs to address.

Really? So we can never loop over an array using the loop variable to address it? That’s seems very restricting.
It’s been a while since I’ve read ARB_fp, but answer this. Does ARB_fp allow for array indexing like ARB_vp does? I don’t recall it providing this functionality. And, if ARB_fp doesn’t have it, then neither does the R3xx line or the R42x line.

Originally posted by Humus:
I don’t think any hardware supports that.
Realizm series cards supports that.
If I understand well, the problem is caused in a program like this:

uniform float array[5];
void main()
{
vec4 color;
for(int i=0;i<4;i++)
color[i] = array[i]*array[4];
gl_FragColor = color;
}

I’ve tried with some values for the array and the color output seems right

Originally posted by Korval:
And, if ARB_fp doesn’t have it, then neither does the R3xx line or the R42x line.
Well that’s all well and good, but if both nVidia and 3Dlabs support it then it’s a bit of a let-down on ATI’s side as far as I’m concerned. I’d consider addressing arrays with variables as a fairly fundamental part of a high-level language - if you can’t loop over an array then it’s not half as useful as it could be.

Back to the old works-with-this-vendor-doesnt-work-with-that-vendor… I was really hoping GLSL would put an end to that. Who was I kidding?!

Originally posted by Ffelagund:
[b] [quote]Originally posted by Humus:
I don’t think any hardware supports that.
Realizm series cards supports that.
If I understand well, the problem is caused in a program like this:

uniform float array[5];
void main()
{
vec4 color;
for(int i=0;i<4;i++)
color[i] = array[i]*array[4];
gl_FragColor = color;
}

I’ve tried with some values for the array and the color output seems right[/b][/QUOTE]A program like this will compile and run just fine. That’s because it doesn’t really need constant addressing. The compiler will instead unroll the loop and access each element directly, which doesn’t need any particular hardware support. This is not a problem on ATI hardware, the compiler deals with these kinds of constructs just fine.

Originally posted by satchmo:
[b]Well that’s all well and good, but if both nVidia and 3Dlabs support it then it’s a bit of a let-down on ATI’s side as far as I’m concerned. I’d consider addressing arrays with variables as a fairly fundamental part of a high-level language - if you can’t loop over an array then it’s not half as useful as it could be.

Back to the old works-with-this-vendor-doesnt-work-with-that-vendor… I was really hoping GLSL would put an end to that. Who was I kidding?![/b]
I would be very surprised if nVidia’s hardware actually supported that functionality. This isn’t even included in PS3.0 in DirectX. You can however implement this functionality in HLSL, but that will under the hood the expanded into a huge switch case, which of course is extremely inefficient but at least does the work. If it works at all on nVidia, I assume this is also what their GLSL driver does.

This:

varying float x;

uniform vec4 array[10];

void main(){
   gl_FragColor = array[x];
}

will essentially create this:

varying float x;

uniform vec4 array[10];

void main(){
   if (x == 0){
      gl_FragColor = array[0];
   } else if (x == 1){
      gl_FragColor = array[1];
   } else if (x == 2){
      gl_FragColor = array[2];
   } else if (x == 3){
      gl_FragColor = array[3];
   } else if (x == 4){
      gl_FragColor = array[4];
   } else if (x == 5){
      gl_FragColor = array[5];
   } else if (x == 6){
      gl_FragColor = array[6];
   } else if (x == 7){
      gl_FragColor = array[7];
   } else if (x == 8){
      gl_FragColor = array[8];
   } else if (x == 9){
      gl_FragColor = array[9];
   } else {
      gl_FragColor = array[10];
   }
}

I don’t think that’s what you want. The best way to access lookup tables in a fragment shader is through a texture. A small 1D texture takes no time to upload if you would require this to be done dynamically, and it also gives you clamping/repeating and linear filtering for free if that’s desireable.

Okay yeah I see where you’re coming from. The case I was looking at though didn’t use a uniform or a varying to address the array (I can see how this might be infeasible alright).

I’ve done a bit more investigating though and the problem I’m having seems to be when a variable plus or minus a value is used to address the array - for example this fragment program seems to hang my 9800 without crashing or drawing anything:

uniform float values[24];

void main(){
	float temp=0.0;
	for(int i=0;i<23;i++){
		temp += values[i]+values[i+1];
	}
	gl_FragColor = vec4(temp);
}

If I take out the ‘+values[i+1]’ part (and change 23 to 24, because it gives me a GL_INVALID_VALUE if I don’t use the whole array for some reason), it works just fine! Am I doing something wrong?

Originally posted by Humus:
[b] [quote]Originally posted by Ffelagund:
[b] [quote]Originally posted by Humus:
I don’t think any hardware supports that.
Realizm series cards supports that.
If I understand well, the problem is caused in a program like this:

uniform float array[5];
void main()
{
vec4 color;
for(int i=0;i<4;i++)
color[i] = array[i]*array[4];
gl_FragColor = color;
}

I’ve tried with some values for the array and the color output seems right[/b][/QUOTE]A program like this will compile and run just fine. That’s because it doesn’t really need constant addressing. The compiler will instead unroll the loop and access each element directly, which doesn’t need any particular hardware support. This is not a problem on ATI hardware, the compiler deals with these kinds of constructs just fine.[/b][/QUOTE]Tried with an uniform for the number of iterations gives me the same result:

uniform float array[5];
uniform int index;
void main()
{
vec4 color;
for(int i=0;i<index;i++)
color[i] = array[i];
gl_FragColor = color;
}

As far I know, this can’t be unrolled by the compiler, correct me if I am wrong please :slight_smile:

EDIT:
I must rectify, I checked this program wrongly. it doesn’t work on my Realizm card, when the array limit is a value passed as uniform. Only shows garbage
Humus you were right.

Sorry for my error checking that :rolleyes:

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