Bug 26224

Summary: [GLSL] Cannot get location of a uniform struct member
Product: Mesa Reporter: Митко Мошев <Mo6eeeB>
Component: Mesa coreAssignee: mesa-dev
Status: RESOLVED FIXED QA Contact:
Severity: normal    
Priority: medium    
Version: 7.6   
Hardware: x86-64 (AMD64)   
OS: Linux (All)   
Whiteboard:
i915 platform: i915 features:
Bug Depends on:    
Bug Blocks: 29044    

Description Митко Мошев 2010-01-25 09:53:48 UTC
Hello,

using the below fragment and vertex shaders, I am unable to obtain the location of Material.color, Material.emission or Material.specular. After successfully compiling the shaders and linking a program, calling

glUniformLocation(program, "Material.color");
glUniformLocation(program, "Material.emission");
glUniformLocation(program, "Material.specular");

all return -1; and glGetError() returns GL_NO_ERROR.

Strangely,

glUniformLocation(program, "Material");

returns a valid uniform location, which can be set using glUniform1f and corresponds to Material.color.r .

Even more perplexingly, calling glGetActiveUniform returns the following info:

Name: Material
Size: 2
Type: 5126 (GL_FLOAT)

I can get the location of Material[0] and Material[1] (and even higher indices without raising errors).
Setting Material[0] has the same effect as setting Material.color.r and
setting Material[1] has the same effect as setting Material.specular.
Setting any higher index does not have a discernible effect.

My hardware is an Intel GM45 Express IGP.
I'm using Mesa 7.6 from Ubuntu 9.10 with a 2.6.32.2 kernel.

Vertex shader:
uniform mat4 MV;
uniform mat4 MVP;
uniform mat3 N;

varying vec3 EyeN;
varying vec4 EyeV;

void main() {
    gl_PointSize = 1;
    gl_Position = MVP * gl_Vertex;
    
    EyeV = MV * gl_Vertex;
    EyeN = normalize( N * gl_Normal );
}

Fragment shader:
struct TMaterial {
    vec3 color;
    float emission;
    float specular;
};

uniform TMaterial Material;

uniform float LightAmbient;

varying vec3 EyeN;
varying vec4 EyeV;

void main() {
    vec3 v3EyeV = vec3(EyeV / EyeV.w);
    float emissionAttenuation = dot(v3EyeV, v3EyeV);
    float effEmission = Material.emission / (1 + emissionAttenuation);
    vec3 effColor = Material.color * ( effEmission + LightAmbient );
    gl_FragColor = vec4(effColor, 1);        
}
Comment 1 Митко Мошев 2010-01-30 09:27:05 UTC
Update:
After some more testing, I found out that varying parameters are not passed correctly between the vertex and fragment shaders. Using the following vertex shader:

uniform mat4 MV;
uniform mat4 MVP;
uniform mat3 N;

varying vec3 blue;
varying vec3 green;

void main() {
    gl_PointSize = 1;
    gl_Position = MVP * gl_Vertex;
    
    blue = vec3(0, 0, 1, 1);
    green = vec3(0, 1, 0, 1);
}

and fragment shader:

varying vec3 blue;
varying vec3 green;

void main() {
	gl_FragColor = vec4(green, 1);
}


I see everything rendered blue, NOT green. If I do

gl_FragColor = vec4(blue, 1);

I see nothing, i.e. a black screen.

Additionally, using the software renderer, everything works.
Comment 2 Eric Anholt 2010-08-17 08:41:02 UTC
I think your struct issues should be fixed with the glsl2 merge to Mesa master.  Also, I stuffed your two shaders at the bottom into a shader_runner test, and it came out fine (after fixing the vec3 constructor to actually have 3 arguments).  So this should be fixed now.

If you've got issues with structure usage still, could you make a piglit shader_runner test for it?

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.