How does Uniform block indexing work for arrays of arrays?

How does indexing work in calls like glGetActiveUniformBlockiv when the uniform block is an array of arrays?

e.g

uniform UB {
vec4 a;
} test[2][3];

I assume it would work something like this where uniformBlockIndex would be:
0 == test[0][0]
1 == test[0][1]
2 == test[0][2]
3 == test[1][0]
4 == test[1][1]
5 == test[1][2]

Is this correct?

If this is documented somewhere I would be grateful is someone could point me too it. I’ve searched but can’t find anything.

According to §4.3.9 of the GLSL 4.5 specification, the instance name can only have a single subscript:

interface-block :
layout-qualifier[sub]opt[/sub] interface-qualifier block-name { member-list } instance-name[sub]opt[/sub] ;

instance-name :
identifier
identifier
identifier [ integral-constant-expression ]

Right that’s what the glsl spec says. But the ARB_arrays_of_arrays spec says:

  1. Can interface blocks (e.g. uniform blocks) be arrays of arrays?
RESOLUTION: Yes.

A reply to a bug report about this said arrays of array were supported and the “expository grammar doesn’t show all possibilities”.

So any idea how you are meant to interact with it?

According to §4.3.9 of the GLSL 4.5 specification, the instance name can only have a single subscript:

Perhaps you should update your specification. Mine, and the copy online, clearly says:


identifier [ integral-constant-expression ] // Note: Arrays of arrays are also allowed

Granted, that text was a recent addition based on Khronos bug 13004.

As to your question, I’m not entirely certain I understand what you’re asking. Allow me to clarify.

Uniform blocks have two numbers associated with them. There is the block index, and there is the buffer binding point. The indices of each uniform block are arbitrarily assigned by the implementation. This is true even for arrays of blocks; each individual array element will have its own index, and the only way to know which index goes to which array element of the block is to query it.

So if you want to iterate through all of the elements of an array (or array of arrays) for a uniform block, you would need to construct appropriate strings with appropriate indices, then pass each one individually to glGetUniformBlockIndex​ to get their block indices.

There is no way to take the base-name for an arrayed uniform block and find out how many array elements it has.

A bigger question is with buffer binding points. While the block indices are aribtrarily assigned during compilation, buffer binding points are not. And while each individual array element has its own completely separate buffer binding point, the question you may be asking is what happens if you assign the buffer binding point in the shader:


layout(binding = 2) uniform UB
{
  vec4 a;
} test[2][3];

The specification states that UB will be a multidimensional uniform block array. Therefore, each element will have its own block index (again, arbitrarily assigned, so you can’t assume that the block index for UB[0][0] is right before UB[0][1]). But the binding indices will be assigned sequentially, starting at 2, ending at 7.

Of course, what’s not specified by the standard is the order of this sequential assignment, relative to having multiple dimensions. Now, the specification does say, when referring to the order of multidimensional arrays in memory (such as in a UBO, or when querying size and layout from a uniform variable), that locations are assigned with the right-most index incrementing first.

It does not specifically say that this is true for interface blocks, however. All it says is, “If the binding identifier is used with a uniform or shader storage block instanced as an array, the first element of the array takes the specified block binding and each subsequent element takes the next consecutive uniform block binding point.” It’s not clear what “subsequent” means in this context.

In short: the spec is unclear. So it’d probably be best to avoid multidimensional arrays of interface blocks.

[QUOTE=Alfonse Reinheart;1264989]Perhaps you should update your specification. Mine, and the copy online, clearly says:


identifier [ integral-constant-expression ] // Note: Arrays of arrays are also allowed

[/QUOTE]

Right; I was looking at revision 3. I had assumed that document revisions were just for typos and the like, and that actual changes to the language would constitute a new language version.

Technically, it is a typo. It was already a part of the formal grammar at the end (array_specifier is a list of possible specifiers, and interface blocks use array_specifier); it’s just that the text inline didn’t make note of the grammatical possibility.