Possible bug: GL_ARRAY_SIZE of a shader storage block member is always zero

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;
}