Name ARB_arrays_of_arrays Name Strings GL_ARB_arrays_of_arrays Contact John Kessenich (cepheus 'at' frii.com) Contributors XXX Notice Copyright (c) 2012-2013 The Khronos Group Inc. Copyright terms at http://www.khronos.org/registry/speccopyright.html Specification Update Policy Khronos-approved extension specifications are updated in response to issues and bugs prioritized by the Khronos OpenGL Working Group. For extensions which have been promoted to a core Specification, fixes will first appear in the latest version of that core Specification, and will eventually be backported to the extension document. This policy is described in more detail at https://www.khronos.org/registry/OpenGL/docs/update_policy.php Status Complete. Approved by the ARB on 2012/06/12. Version Last Modified Date: 2012/07/01 Revision: 7 Number ARB Extension #120 Dependencies GLSL 1.2 is required. OpenGL ?? (Core Profile) specification is required. (See issues.) Overview Multi-dimensional arrays are a frequently requested feature. This extension removes the restriciton that arrays cannot be formed into arrays, allowing arrays of arrays to be declared. Technically, removing this restriction is all that is necessary to enable this feature, but it is worthwhile showing what the result of doing that looks like. The following will be true of arrays of arrays - They will first class objects. (They know their size, can be passed by copy-in semantics to functions, etc.) - They will only be one-dimensional arrays of other first class objects. (arrays are already first class objects). - The syntax vec4 a[3][2]; Declares a one-dimensional array of size 3 of one-dimensional arrays of size 2 of vec4s. Also, these syntaxes do the same thing: vec4[2] a[3]; vec4[3][2] a; or, looking at more dimensions, these are all the same int a[1][2][3][4][5][6]; int[1][2][3][4][5][6] a; int[4][5][6] a[1][2][3]; note this latter is equivalent to C, in meaning the same thing, if done as typedef int int456[4][5][6]; int456 a[1][2][3]; that is, this GLSL proposal matches C behavior in this way. The type needed for both constructors and nameless parameters is: int[1][2][3][4][5][6] - This type could be declared as a formal parameter in a function prototype as void foo(vec4[3][2]); - Accessing is done as a[x][y] // x selects which array of size 2 is desired // y selects which vec4 is desired a[x] // this results in a one-dimensional array, with all rights and // priviledges implied - The .length() operator works as normal: a.length() // this is 3 a[x].length() // this is 2 - The constructor for the above is vec4[3][2](vec4[2](vec4(0.0), vec4(1.0)), vec4[2](vec4(0.0), vec4(1.0)), vec4[2](vec4(0.0), vec4(1.0))) - Initializers for the above are vec4 a[3][2] = vec4[3][2](vec4[2](vec4(0.0), vec4(1.0)), vec4[2](vec4(0.0), vec4(1.0)), vec4[2](vec4(0.0), vec4(1.0))); // or vec4 a[3][2] = {vec4[2](vec4(0.0), vec4(1.0)), vec4[2](vec4(0.0), vec4(1.0)), vec4[2](vec4(0.0), vec4(1.0))) }; // or vec4 a[3][2] = {{ vec4(0.0), vec4(1.0) }, { vec4(0.0), vec4(1.0) }, { vec4(0.0), vec4(1.0) } }; // requires matching nesting of // {} with object's hierarchy Note that all the above is naturally already specified in the core specification. New Procedures and Functions New Tokens Additions to Chapter 2 of the OpenGL 4.2 (Core Profile) Specification (OpenGL Operation) Additions to Chapter 3 of the OpenGL 4.2 (Core Profile) Specification (Rasterization) None. Additions to Chapter 4 of the OpenGL 4.2 (Core Profile) Specification (Per-Fragment Operations and the Framebuffer) None. Additions to Chapter 5 of the OpenGL 4.2 (Core Profile) Specification (Special Functions) Additions to Chapter 6 of the OpenGL 4.2 (Core Profile) Specification (State and State Requests) None. Additions to Chapter 4 of the OpenGL Shading Language Specification, Version 4.20 (Variables and Types) Section 4.1.9 Arrays Rewrite the sentences "Only one-dimensional arrays may be declared. All basic types and structures can be formed into arrays." as "Arrays only have a single dimension (a single number within "[ ]", however, arrays of arrays can be declared. All types (basic types, structures, arrays) can be formed into an array." "When in transparent memory (like in a uniform block), the layout is that the 'inner' (right-most in declaration) dimensions iterate faster than the out dimensions. That is, for the above, the order in memory would be: low address...a[0][0] a[0][1] a[1][0] a[1][1] a[2][0] a[2][1]...high address" Expand the examples in this section by incorporating the declaration and use content from the overview section above. Add vec4 a[3][2]; a.length() // this is 3 a[x].length() // this is 2 When the *length* method will return a compile-time constant, the expression in brackets (x above) will be evaluated and subject to the rules required for array indexes, but the array will not be deferenced. Thus, behavior is well defined even if the run-time value of the expression is out of bounds. Remove the illegal examples of arrays of arrays. Add the following: "For unsized arrays, only the outermost dimension can be lacking a size. A type that includes an unknown array size cannot be formed into an array until it gets an explicit size." Section 4.1.11 Initializers Expand the examples in this section by incorporating the initializer content from the overview section above. Section 4.3.4 Input Variables For this paragraph, keep this introductory text the same "Some inputs and outputs are arrayed, meaning that for an interface between two shader stages either the input or output declaration requires an extra level of array indexing for the declarations to match. but rewrite the remainder "For example, with the interface between a vertex shader and a geometry shader, vertex shader output variables and geometry shader input variables of the same name must match in type and qualification, except that the vertex shader name cannot be declared as an array while the geometry shader name must be declared as an array, to allow for vertex indexing. It is a link error if a non-arrayed input is not declared with the same type, qualification, and array dimensionality as the matching output. It is an error if an arrayed input is not declared as an array of the same type and qualification as the corresponding (non-array) output. Symmetrically, it is an error if an arrayed output is not declared as an array of the same type and qualification as the corresponding (non-array) input." instead as "For example, with the interface between a vertex shader and a geometry shader, vertex shader output variables and geometry shader input variables of the same name must match in type and storage qualification, except that the geometry shader will have one more array dimension than the vertex shader, to allow for vertex indexing. If such an arrayed interface variable is not declared with the necessary additional input or output array dimension, a link-time error will result." "For non-arrayed interfaces (meaning array dimensionally stays the same between stages), it is a link-time error if the input variable is not declared with the same type, including array dimensionality, as the matching output variable." Remove the following paragraph "If the output corresponding to an arrayed input is itself an array, it must appear in an output block (see interface blocks below) in the outputting shader and in an input block in the inputting shader with a block instance name declared as an array. This is required because two-dimensional arrays are not supported." Section 4.3.6 Output Variables Remove the following paragraph "As described under the section 4.3.4 'Input Variables' above, if a per-vertex output of the tessellation control shader is itself an array with multiple values per vertex, it must appear in an output block (see interface blocks below) in the tessellation control shader with a block instance name declared as an array." Additions to Chapter 5 of the OpenGL Shading Language Specification, Version 4.20 (Built-in Variables) Section 5.4 Array Constructors Expand the constructor examples with the constructor examples from the overview section of this specification. Section 5.7 Structure and Array Operations Expand the examples with the .length() and [] examples from the overview section of this specification. Changes to the grammar There are 7 pairs of rules that allowed either an empty array declaration or one with a size. For example: init_declarator_list: init_declarator_list COMMA IDENTIFIER LEFT_BRACKET RIGHT_BRACKET init_declarator_list COMMA IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET plus 1 rule for parameter array declarations: parameter_declarator: type_specifier IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET These 15 total (2*7 + 1) declaration rules are all replaced with 8 uses of a new rule array_specifier: array_specifier: LEFT_BRACKET RIGHT_BRACKET LEFT_BRACKET constant_expression RIGHT_BRACKET array_specifier LEFT_BRACKET RIGHT_BRACKET array_specifier LEFT_BRACKET constant_expression RIGHT_BRACKET For example, the pair given in the example above becomes: init_declarator_list: init_declarator_list COMMA IDENTIFIER array_specifier The LEFT_BRACKET now appears in exactly 5 rules now; the 1 for postfix expressions (remains unchanged) and the 4 for array_specifier. New State None. New Implementation Dependent State None. Issues 1. Do we want to support the following form as well? vec4[3][2] a; Probably, to match the constructor and formal parameter declaration. These require that vec4[3][2] // a valid type is a type in its own right, and the general syntax to declare something is GLSL already has required the following since 1.2: vec4[3] a; RESOLUTION: Yes, allow this syntax. 2. What does the enumeration API look like? Don't want to enumerate down to 10,000 little individual elements, want something more hierarchical instead. This will significantly effect this extension if this extension turns into defining a new discovery API. Nested issue: What about optimizers eliminating holes in a data structure? RESOLUTION: Belongs in another extension. 3. How are large buffer/memory arrays declared? E.g., buffer vec4 a[][2]; RESOLUTION: Belongs in another extension. Probably will be buffer BufferBlock { vec4 a[][2]; }; 4. Can large memory arrays be passed by reference to a function? Want to pick up pointer-like feature without full introduction of pointers. RESOLUTION: Belongs in another extension. 5. How does this extension interact with ??, which is adding the large memory/buffer style arrays. RESOLUTION: Belongs in another extension. 6. Can vertex inputs be arrays of arrays? RESOLUTION: Yes. 7. Can fragment outputs be arrays of arrays? RESOLUTION: Yes. 8. Can vertex outputs be arrays of arrays? Note that some stage inputs can now be arrays of arrays, due to adding a new array level to a previous stage's output type. RESOLUTION: Yes. 9. Can uniforms be arrays of arrays? RESOLUTION: Yes. 10. Can interface blocks (e.g. uniform blocks) be arrays of arrays? RESOLUTION: Yes. 11. Can subroutine variables be arrays of arrays? Recommended: Yes. RESOLUTION: 12. Do we want to eliminate the syntax? vec4[2] a[3]; // same as vec4 a[3][2]; It might seem the 3 and 2 should be reversed. However, thinking through how precedence, the grammar, etc. all work, this is actually very well defined and correct and consistent with C/C++. RESOLUTION: Yes, allow these syntaxes. Revision History Rev. Date Author Changes ---- -------- -------- ----------------------------------------- 7 1-Jul-2012 JohnK Added grammar changes. 6 10-May-2012 JohnK Editorial fixes before merging into core spec. 5 16-Mar-2012 JohnK Update with resolutions from language meeting (Generally, allow arrays of arrays for most I/O, and allow the syntaxes that naturally fall out.) 4 24-Feb-2012 JohnK Minor clarifications within issues. 3 3-Feb-2012 JohnK Fix reversed 2/3, add new example, resolve issues 2-5 2 1-Feb-2012 JohnK Flesh out with specification language 1 1-Feb-2012 JohnK Initial revision