NV bug (tested on 314.14) using storage buffer objects

UPDATE:Sorry for poor code pasting I was testing correct code (with semicolons and defined g_mProjectionInv like mat4x4 so doesn’t change any observation)
Hi I seem to have found a bug using storage buffer objects porting deferred+ code to GLSL
I tried to use a storage buffer instead of default uniform buffer to see only how affected perf… so


#ifdef USE_SBO
layout(binding = 0) buffer cbPerObject 
#else
uniform cbPerObject
#endif
{
    mat4x4  g_mWorldViewProjection;     
    mat4x4  g_mWorldView;               
    mat4x4  g_mWorld;                   
    float4  g_MaterialAmbientColorUp;
    float4  g_MaterialAmbientColorDown;
};
has code like accessing


either using
g_mProjectionInv[2].w
or
g_mProjectionInv[2][3]

shader compiles (ie. generates NV assembly but fails with:


-- error message --
line 710, column 30:  error: expected ';'
line 711, column 29:  error: expected ';'
-- internal assembly text --
!!NVcp5.0

offending lines:
LDB.F32X4 R3.x, sbo_buf1[112].w;
LDB.F32X4 R2.x, sbo_buf1[96].w;

so seems doesn’t like .w modifier and seems coming from access to matrices mat4x4

According to the GLSL spec the only way to access members of a matrix is using array subscripting syntax:

5.6 Matrix Components
[INDENT]The components of a matrix can be accessed using array subscripting syntax. Applying a single subscript
to a matrix treats the matrix as an array of column vectors, and selects a single column, whose type is a
vector of the same size as the matrix. The leftmost column is column 0. A second subscript would then
operate on the column vector, as defined earlier for vectors. Hence, two subscripts select a column and
then a row.

mat4 m;
m[1] = vec4(2.0); // sets the second column to all 2.0
m[0][0] = 1.0; // sets the upper left element to 1.0
m[2][3] = 2.0; // sets the 4th element of the third column to 2.0

Behavior is undefined when accessing a component outside the bounds of a matrix with a non-constant
expression. It is an error to access a matrix with a constant expression that is outside the bounds of the
matrix.[/INDENT]

It should not work when using a uniform buffer as well. It seems the NVIDIA compiler is taking another path there.

If you change

g_mProjectionInv[2].w

to

g_mProjectionInv[2][3]

it should work.

so seems doesn’t like .w modifier and seems coming from access to matrices mat4x4

It’s more likely that you didn’t use semicolons. Especially considering that, well, there aren’t any semicolons anywhere in the code you posted. You should add some and get back to us.

@AHeumann: That doesn’t make sense. An array of column vectors would treat arc[0] as a vector. And it is legal to do .w on a vector. Therefore, if arc is an array of column vectors, arc[0].w should be legal GLSL code.

You are right, I just read the sentence on array access and did not read the sentence on vector access.

just quickly threw something together that compiles just fine. As the others mentioned the code you show wouldn’t compile at all? g_mProjectionInv doesn’t exist in the struct either?

First sorry for poor posting I’m using semicolons of course but not posted here… also I have another Storage buffer or uniform buffer and it contains g_mProjectionInv see here (I cleaned semicolons for not showing commented HSLS port:


#define matrix mat4x4
#ifdef USE_SBO
/*cbuffer*/layout(binding = 0) buffer cbPerFrame //: register( b1 )
#else
uniform cbPerFrame
#endif
{
    matrix              g_mProjection           ;//: packoffset( c0 );
    matrix              g_mProjectionInv        ;//: packoffset( c4 );
    float3              g_vCameraPos            ;//: packoffset( c8 );
    float               g_fAlphaTest            ;//: packoffset( c8.w );
    uint                g_uNumLights            ;//: packoffset( c9 );
    uint                g_uWindowWidth          ;//: packoffset( c9.y );
    uint                g_uWindowHeight         ;//: packoffset( c9.z );
    uint                g_uMaxNumLightsPerTile  ;//: packoffset( c9.w );
};

anyway tested that offensive line is:


 z = 1.f / (z*g_mProjectionInv[2].w + g_mProjectionInv[3].w);

changing to


  z = 1.f / (z*g_mProjectionInv[2][3]+ g_mProjectionInv[3][3]);

doesn’t fix nothing as still generates same nv assembly code with .w
as said using uniform objects fixes issue so it’s a bug in NV compiler…
I can post full code if needed but issue is good isolated now…

Ok I post a minimal repro case:


#version 430 core

#define TILE_RES 16

layout(binding = 0) buffer cbPerFrame 
{
    mat4x4             g_mProjectionInv;
};

layout(binding = 3, r32f) uniform imageBuffer g_PerTileLightIndexBufferOut; 

layout (local_size_x = TILE_RES, local_size_y = TILE_RES) in;
void main(  )
{
    float z;
    mat4x4 matr=g_mProjectionInv;
    z=1.f / (z*matr[2][1] + matr[3][1]);
    imageStore(g_PerTileLightIndexBufferOut,int(1),vec4(z));
}

and compiler error:


Compute info
------------
0(16) : warning C7050: "z" might be used before being initialized
Internal error: assembly compile error for compute shader at offset 619:
-- error message --
line 19, column 29:  error: expected ';'
line 20, column 29:  error: expected ';'
-- internal assembly text --
!!NVcp5.0
OPTION NV_shader_storage_buffer;
OPTION NV_shader_atomic_float;
GROUP_SIZE 16 16;
# cgc version 3.1.0001, build date Feb 28 2013
# command line args:
#vendor NVIDIA Corporation
#version 3.1.0.1
#profile gp5cp
#program main
#semantic g_PerTileLightIndexBufferOut : IMAGE[3]
#semantic cbPerFrame : SBO_BUFFER[0]
#var int g_PerTileLightIndexBufferOut.__remap :  : c[0] : -1 : 1
#var float4x4 g_mProjectionInv : SBO_BUFFER[0] : sbo_buffer[0][0], 4 : -1 : 1
PARAM c[1] = { program.local[0] };
STORAGE sbo_buf0[] = { program.storage[0] };
TEMP R0, R1;
IMAGE images[] = { image[0..7] };
LDB.F32X2 R1.x, sbo_buf0[48].y;
LDB.F32X2 R0.x, sbo_buf0[32].y;
MAD.F R0.x, R0.y, R0, R1;
RCP.F R0.x, R0.x;
MOV.S R0.y, c[0].x;
STOREIM.F images[R0.y], R0.x, {1, 0, 0, 0}, BUFFER;
MOV.F R1, R0;
MOV.U R0.x, R0;
END
# 8 instructions, 2 R-regs

Internal error: assembly compile error for compute shader at offset 619:

Generally speaking "internal error"s are bugs from within the compiler itself.

compiles fine for me, looks like it has been fixed with newer drivers (though can’t say exactly from which version on)

Seems bug is still present on OGL 4.4 beta drivers!

driver 326.41 beta gives me an error

Includes0(12) : error C3008: unknown layout specifier ‘local_size_y’
0(12) : error C3008: unknown layout specifier ‘local_size_x’

If I remove the layout line I get oscarbg’s error

Could you see if the bug is gone with the new OpenGL 4.4 beta 326.58 driver for Windows available here:

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