Hi,
I have a shader that defines the following block:
layout(std140) readonly buffer b_buff {
mat4 u_mvp[8U];
};
When calling glGetProgramResourceiv to retrieve the array size (GL_ARRAY_SIZE) of the u_mvp variable, the driver returns 0.
If I replace the shader storage block with a uniform block it returns 8 as expected:
layout(std140) uniform b_buff {
mat4 u_mvp[8U];
};
I couldn’t find something in the spec that differentiates the behavior of uniform blocks and shader storage blocks when it comes to reporting array sizes. But I am not quite sure.
OS: Linux 3.11.0-20-generic x86_64 (= Ubuntu 13.10 64bit)
Driver version: 331.20
GPU: GeForce GTX 560 Ti
Also the full source of my test to save you some time:
static int
create_program(const char *source, const GLenum type, GLuint *program)
{
GLuint prog;
GLint status;
prog = glCreateShaderProgramv(type, 1, &source);
glGetProgramiv(prog, GL_LINK_STATUS, &status);
if (status == GL_FALSE) {
GLint len = 0;
GLint written = 0;
char *txt;
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &len);
txt = malloc(len + 1);
glGetProgramInfoLog(prog, len, &written, txt);
error(txt);
free(txt);
return 1;
}
*program = prog;
return 0;
}
static int
test_shader_arrays()
{
static const char *vert_source =
"#version 440 core\n"
"layout(location = 0) in vec3 position;\n"
"layout(std140) readonly buffer b_buff {\n"
"\tmat4 u_mvp[8U];\n"
"};\n"
"out gl_PerVertex {\n"
"vec4 gl_Position;\n"
"};\n"
"void main()\n"
"{\n"
"\tgl_Position = u_mvp[gl_InstanceID] * "
"vec4(position * 0.9, 1.0);\n"
"}\n";
GLuint prog;
GLint count;
#if 1
static const GLenum interface = GL_BUFFER_VARIABLE;
#else
static const GLenum interface = GL_UNIFORM;
#endif
unsigned i;
if (create_program(vert_source, GL_VERTEX_SHADER, &prog)) {
error("create_program() failed");
return 1;
}
glGetProgramInterfaceiv(prog, interface, GL_ACTIVE_RESOURCES, &count);
for (i = 0; i < count; i++) {
char name[256];
GLsizei len;
GLenum props[] = {GL_ARRAY_SIZE};
GLenum out[1];
glGetProgramResourceName(prog, interface, i, sizeof(name),
&len, name);
name[len] = '
static int
create_program(const char *source, const GLenum type, GLuint *program)
{
GLuint prog;
GLint status;
prog = glCreateShaderProgramv(type, 1, &source);
glGetProgramiv(prog, GL_LINK_STATUS, &status);
if (status == GL_FALSE) {
GLint len = 0;
GLint written = 0;
char *txt;
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &len);
txt = malloc(len + 1);
glGetProgramInfoLog(prog, len, &written, txt);
error(txt);
free(txt);
return 1;
}
*program = prog;
return 0;
}
static int
test_shader_arrays()
{
static const char *vert_source =
“#version 440 core\n”
“layout(location = 0) in vec3 position;\n”
“layout(std140) readonly buffer b_buff {\n”
“\tmat4 u_mvp[8U];\n”
“};\n”
“out gl_PerVertex {\n”
“vec4 gl_Position;\n”
“};\n”
“void main()\n”
“{\n”
"\tgl_Position = u_mvp[gl_InstanceID] * "
“vec4(position * 0.9, 1.0);\n”
“}\n”;
GLuint prog;
GLint count;
#if 1
static const GLenum interface = GL_BUFFER_VARIABLE;
#else
static const GLenum interface = GL_UNIFORM;
#endif
unsigned i;
if (create_program(vert_source, GL_VERTEX_SHADER, &prog)) {
error("create_program() failed");
return 1;
}
glGetProgramInterfaceiv(prog, interface, GL_ACTIVE_RESOURCES, &count);
for (i = 0; i < count; i++) {
char name[256];
GLsizei len;
GLenum props[] = {GL_ARRAY_SIZE};
GLenum out[1];
glGetProgramResourceName(prog, interface, i, sizeof(name),
&len, name);
name[len] = '\0';
glGetProgramResourceiv(prog, interface, i,
1, props,
1, NULL, out);
printf("name: %s array_size: %d\n", name, out[0]);
}
return 0;
}
';
glGetProgramResourceiv(prog, interface, i,
1, props,
1, NULL, out);
printf("name: %s array_size: %d\n", name, out[0]);
}
return 0;
}