PDA

View Full Version : Attribute locations of mat4x4: driver bug?



Heiko
11-03-2009, 03:43 AM
When reading the specs I understood that a mat4x4 vertex attribute needs 4 attribute locations:

glspec32.core.20090803.pdf (page 52):

When an attribute variable is declared as a mat2x4, mat3x4 or mat4, its matrix columns are taken from the (x; y; z; w) components of generic attributes i and i+1 (mat2x4), from attributes i through i + 2 (mat3x4), or from attributes i through i + 3 (mat4).
However, when using the vertex shader below and (after linking) querying the active attributes, and requesting their names one by one, it seems like the mat4x4 attributes take only one attribute location. Did I misinterpret the specs? Or is it a bug in the OpenGL driver (AMD 9.10 Linux driver). Perhaps the spec is wrong? (I couldn't find a similar phrase for the active uniforms, but I could have overlooked it).

When using `in vec4 arrayOfvalues[4]', it uses four attribute locations (as expected).



// vertex shader

precision highp float;

in int material;
in mat4x4 vertex;
in mat4x4 normal;
in mat4x4 colour;

uniform mat4x4 nor_matrix;
uniform mat4x4 mvp_matrix;

smooth out vec4 ocolour;
smooth out vec4 onormal;
flat out int omaterial;

void main(void)
{
ocolour = vec4(1.1, 1.2, 1.3, 1.4) * colour;
onormal = vec4(1.1, 1.2, 1.3, 1.4) * nor_matrix * normal;
omaterial = material;
gl_Position = vec4(1.1, 1.2, 1.3, 1.4) * mvp_matrix * vertex;
}


// for completeness sake, the accompanying fragment shader

#version 140
precision highp float;

smooth in vec4 ocolour;
smooth in vec4 onormal;
flat in int omaterial;

out vec4 fragcolour;
void main(void)" << endl
{
fragcolour = onormal;
};


Output of querying the active attributes and uniforms:



active_attributes: 4
active_attributes_max_length: 9
active_uniforms: 2
active_uniform_max_length: 11

// name - index - size - type (obtained with glGetActiveAttrib)
`colour': 0 (size: 1, 35676)
`material': 1 (size: 1, 5124)
`normal': 2 (size: 1, 35676)
`vertex': 3 (size: 1, 35676)

// name - index - size - type (obtained with glGetActiveUniform)
`mvp_matrix': 0 (size: 1, 35676)
`nor_matrix': 1 (size: 1, 35676)

Can anybody provide some insight in what is going on?

skynet
11-03-2009, 08:12 AM
There is no way GL can return more than one location for a single attribute (which your matrices are). So it returns the first location and expects you to know and apply the spec rules (i.e. use the next consecutive locations for each column). I didn't see glGetAttribLocation() in your code, did you use it at all?

Heiko
11-03-2009, 08:34 AM
There is no way GL can return more than one location for a single attribute (which your matrices are). So it returns the first location and expects you to know and apply the spec rules (i.e. use the next consecutive locations for each column). I didn't see glGetAttribLocation() in your code, did you use it at all?

No, I haven't used glGetAttribLocation. Instead I'm using glGetActiveAttrib for indices 0, ..., n (n obtained with glGetProgramiv() with GL_ACTIVE_ATTRIBUTES); As shown in my example code this returns the three matrices in my example for consecutive indices. Whereas reading the spec I would have expected that a mat4x4 would have counted as 4 active attributes (because the spec mentions generic attributes i + 3 for the mat4x4 type).

I would have expected something similar to handing over an array of say vec4 attributes. In case you have the following line in your vertex shader:

in vec4 myArray[4];

You'll get 4 active attributes (assuming you are using all elements from the array in the vertex shader) according to glGetProgramiv (with GL_ACTIVE_ATTRIBUTES). Querying all attributes with indices 0, .., 3 using glGetActiveAttrib gives: `myArray[0]', `myArray[1]', `myArray[2]', `myArray[3]'.

I could try using glGetAttribLocation, but I thought using glGetActiveAttrib using the indices would just give me the same info (but the other way around... with getGetAttribLocation you'll give a name and get the index, with getGetActiveAttrib you'll give an index and get a name).

[edit]
Tried using glGetAttribLocation I got some other results indeed:



// name - location obtained with glGetAttribLocation
colour: 0
material: 4
normal: 5
vertex: 9

This shows indeed that the matrix takes up 4 attribute locations. This also means that the index given to glGetActiveAttrib is not the same as the attribute location obtained with glGetAttribLocation (and this is what I would have expected).

Even with a mat4x4 glGetActiveAttrib could have said something like:



myMatrix.column[0] // when applying index 0
myMatrix.column[1] // when applying index 1
myMatrix.column[2] // when applying index 2
myMatrix.column[3] // when applying index 3

When querying the names of the active attributes.

skynet
11-03-2009, 09:51 AM
You mix up two different kinds of indices.
The one that glGetActiveAttrib() returns indexes the attribute variable within the specific shader. It is used to "address" the attribute in further queries. See it as kind of numerical name for the attribute. You have no direct influence on the vaue of that index.

The other index is the attribute location index. It binds the attribute to a specific generic vertex array (the index that glVertexAttribPointer takes). You can either let the linker assign the attribute location index and query it via glGetAttribLocation() or you can even assign the attribute location index yourself (via glBindAttribLocation)

Heiko
11-03-2009, 10:05 AM
You mix up two different kinds of indices.
The one that glGetActiveAttrib() returns indexes the attribute variable within the specific shader. It is used to "address" the attribute in further queries. See it as kind of numerical name for the attribute. You have no direct influence on the vaue of that index.

The other index is the attribute location index. It binds the attribute to a specific generic vertex array (the index that glVertexAttribPointer takes). You can either let the linker assign the attribute location index and query it via glGetAttribLocation() or you can even assign the attribute location index yourself (via glBindAttribLocation)

Thanks for the explanation. I realize now how I've mixed up the functions. I knew about glBindAttribLocation and glGetAttribLocation, just thought using glGetActiveAttrib was another way of handling the vertex attributes and their indices. However, I now realize you can only use that function to query the active attributes for their name, type and size.