wrong array indexing on ATI HD4670

I have a custom structure to hold lighting parameter


struct ST_LightParameter{
vec4 position;
vec4 diffuse;
vec4 specular;
float radius;
};

and then declared uniform variable like this in vertex/fragment shader


uniform ST_LightParameter lightParam[2];

On my main program, I uploaded the data by using uniform location get from
lightParam[0].diffuse,lightParam[0].position,lightParam[1].position …etc

The problem is when access the data in fragment/vertex shader.

When i try to get data from lightParam[1].position,
the data return are from lightParam[0].position (checked by sending color data and render to screen).

the funny thing is lightParam[1].diffuse return correct data (again checking by render to screen)

the same program run with out any error on my NVIDIA 9800GT , even the
intel GMA X3100 on my laptop produced correct result.

Are there any limitation on using array/custom structure on ATI card ?

There should be no such limitation. That’s not to say that there are no bugs… I assume you’re using the latest Catalysts (9.11). If so, can you send me a test case?

Cheers,

Graham

Thank for your fast replied.

Actually i use 9.9 , trying to install 9.11 on my XP system a few minute ago but result in blue screen error. so I will have to stick with 9.9 for now.

The actual shader are a little more complicate than what i post here
(involed texture look up in vertex shader for hardware skinning).

I have a feeling that if i write a very basic shader just to check the value the bug may be gone.

I will try my best to reproduced the error in smaller app.

It look like the problem appear when I try to pass loop counter to function

for example



struct ST_LightParameter{
vec4 position;
vec4 diffuse;
vec4 specular;
float radius;
};

uniform ST_LightParameter stLightSource[2];
uniform sampler2D baseTexture;
uniform sampler2D cellShadeTexture;

uniform vec4 globalAmbient;
varying vec3 intLightVec[2];
varying vec3 intEye;
varying vec4 debugColor;
varying vec3 intNorm;

vec4 diffuseTerm = vec4(0.0,0.0,0.0,1.0);
vec4 diffuseCellShadeTerm = vec4(0.0,0.0,0.0,1.0);
vec4 specularTerm = vec4(0.0,0.0,0.0,1.0);

void diffuseHemiSphere(vec4 diffuse,vec3 normal,vec3 lightVec,float attenuation){

	vec4 GroundColor = vec4(0.2,0.2,0.2,1.0);	
	float costheta = dot(normal, lightVec);
	float a = 0.5 + 0.5 * costheta;
	
	diffuseTerm += (a*diffuse + (1.0-a)*GroundColor)*gl_FrontMaterial.diffuse*attenuation;
	
}

void diffuseCellShadeTexture(vec4 diffuse,vec3 normal,vec3 lightVec,float attenuation){

		
	float ln = dot(normal, lightVec);
	ln = (ln+1.0)/2.0;
	if(ln > 0.99){
		ln = 0.99;
	}
	vec4 cellColor = texture2D(cellShadeTexture,vec2(ln,0.5).st);
	cellColor[3] = 1.0; 
	
	
	diffuseCellShadeTerm += cellColor;
		
}

void specular(vec4 specular,vec3 normal,vec3 lightVec,vec3 eye,float attenuation){


	vec3 halfVector = normalize(lightVec + eye);
	
	float nDotVP = max(0.0, dot(normal, lightVec));
	float nDotHV = max(0.0, dot(normal, halfVector));
	float pf;	

	if (nDotVP == 0.0)
		pf = 0.0;
	else
		pf = pow(nDotHV, gl_FrontMaterial.shininess);

	specularTerm += specular*gl_FrontMaterial.specular*pf*attenuation;
	
}

float getAttenuationRadiusBased(float radius,vec3 ulVec){
	
	vec3 aUL = ulVec/radius;
	float atten = max(0.0, 1.0 - dot(aUL,aUL));
	return atten;
}

void pointLightByRadiusCellShade(int i,vec3 norNorm,vec3 eyeNorm){

	float attenuation = getAttenuationRadiusBased(stLightSource[i].radius,intLightVec[i]);
	vec3 lightVec = normalize(intLightVec[i]);
	diffuseCellShadeTexture(stLightSource[i].diffuse,norNorm,lightVec,attenuation);
	diffuseHemiSphere(stLightSource[i].diffuse,norNorm,lightVec,attenuation);
	specular(stLightSource[i].specular,norNorm,lightVec,eyeNorm,attenuation);

}


void main()
{
	
	vec3 eyeNorm = normalize(intEye); 
	vec3 norNorm = normalize(intNorm);		
	
	for(int i=0;i<2;i++){
		pointLightByRadiusCellShade(i,norNorm,eyeNorm);
	}

	
	vec4 texColor = texture2D(baseTexture,gl_TexCoord[0].st);
	vec4 finalColor = (diffuseTerm*diffuseCellShadeTerm + specularTerm + globalAmbient*gl_FrontMaterial.ambient)*texColor;
	
	gl_FragData[0] = finalColor;
	gl_FragData[1] = vec4(norNorm,1.0);

		
}


will give an error result (only diffuse value appear to be correct on both i =0 & i=1 , the position value will alway be of i=0 )

but if i remove the function and do something like this instead.

for(int i=0;i<2;i++){
float attenuation = getAttenuationRadiusBased(stLightSource[i].radius,intLightVec[i]);
vec3 lightVec = normalize(intLightVec[i]);
diffuseCellShadeTexture(stLightSource[i].diffuse,norNorm,lightVec,attenuation);
diffuseHemiSphere(stLightSource[i].diffuse,norNorm,lightVec,attenuation);
specular(stLightSource[i].specular,norNorm,lightVec,eyeNorm,attenuation);
}

the result are correct as expected.

Is this a bug or GLSL limited ?, since both code doesn’t report any compilation error.

Behavior of the code inside the function call should be the same as inlined code. This is probably a bug, but if you’re testing on Catalyst 9.9, it could be fixed already. I’ll let our compiler guys know about your example.

Cheers,

Graham

Hi,

The compiler team reproduced the issue on the code you posted and believe they have fixed the problem. If you can, please try Catalyst 9.12 (or 10.1, which should be available in a few days) and let us know if you have any more problems.

Cheers,

Graham

Thank for your great support. :slight_smile: