I ran around in circles for a couple of weeks now trying to figure out why a certain change in my shader caused everything to go haywire. I've nailed now the problem and it looks to me like it's a driver bug not me understanding some specs wrong. I would like to confirm with others here if this is the case or if something slipped me.

I found this bug on ATI 12.6_beta_pre897:legacy as well as 13.1_beta_pre897:legacy . The graphic card is a Radeon 4870 HD.

The bug happens with uniform buffer objects in connection with row-major oriented matrices. The test shader looks like this (fragment shader only, vertex shader is basic in-out position):

precision highp float; precision highp int; layout (std140, row_major) uniform TestParameters{ mat4x3 pMatrix1; mat3 pMatrix2; }; out vec3 outColor; void main( void ){ mat4x3 indirectAccess = pMatrix1; vec3 normal = indirectAccess * vec4( vec3( 0.0, 0.0, 1.0 ), 1.0 ); outColor = normal * vec3( 0.5 ) + vec3( 0.5 ); }

This test is run on a 1x1 screen so the result can be easily verfied by testing the result of a single pixel. The UBO in question is laid out like this with each [X] being one float value aligned in rows to 4 floats for readability:

[ a11 ][ a12 ][ a13 ][ a14 ] [ a21 ][ a22 ][ a23 ][ a24 ] [ a31 ][ a32 ][ a33 ][ a34 ] [ b11 ][ b12 ][ b13 ][ 0 ] [ b21 ][ b22 ][ b23 ][ 0 ] [ b31 ][ b32 ][ b33 ][ 0 ]

aXY refers to matrix1[X][Y] and bXY to matrix2[X][Y] both in row-major order. For testing the following values are written in the UBO:

[ 0 ][ 0 ][ 0 ][ 0 ] [ 0 ][ 0 ][ 0 ][ 0 ] [ 0 ][ 0 ][ 0 ][ 1 ] [ 1 ][ 0 ][ 0 ][ 0 ] [ 0 ][ 0 ][ 0 ][ 0 ] [ 0 ][ 0 ][ 0 ][ 0 ]

You can verify that if the data is read as row-major you end up with a matrix producing the output vector (0,0,1) while in colon-major you end up with (1,0,0).

If I run this shader I should get (0,0,1) but I get actually (1,0,0) hence the matrix is incorrectly read as colon-major if copied first to a matrix of the same type ( indirectAccess == pMatrix1 ). If the shader is changed to this (using pMatrix1 directly):

precision highp float; precision highp int; layout (std140, row_major) uniform TestParameters{ mat4x3 pMatrix1; mat3 pMatrix2; }; out vec3 outColor; void main( void ){ vec3 normal = pMatrix1 * vec4( vec3( 0.0, 0.0, 1.0 ), 1.0 ); // ****************** outColor = normal * vec3( 0.5 ) + vec3( 0.5 ); }

the output is (0,0,1) as it should be. I ended up with this bug as I had to multiply two matrices together in the shader to do a bunch of calculations. The result never had been right because the driver reads the matrix incorrectly from the UBO data storage.

So my questions are not these:

1) Can somebody else confirm this bug using this simple test-case?

2) Or do I misunderstand something about the specs stating that accessing a matrix directly uses the row-major qualifier while using the matrix indirectly ignores it?

EDIT:

I should note that UBO is working properly so far. The problem started when I tried doing a more complex shader where I had to access matrices indirectly. So far I wrote all my shaders to access matrices directly so the bug never showed before.