Name ARB_enhanced_layouts Name Strings GL_ARB_enhanced_layouts Contact John Kessenich (cepheus 'at' frii.com) Contributors Pat Brown, NVIDIA (pbrown 'at' nvidia.com) Christophe Riccio, AMD Notice Copyright (c) 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 June 3, 2013. Ratified by the Khronos Board of Promoters on July 19, 2013. Version Last Modified Date: January 10, 2019 Revision: 28 Number ARB Extension #146 Dependencies This extension is written against the OpenGL 4.3 (Compatibility Profile) Specification, dated February 14, 2013. This extension is written against the GLSL 4.30 Specification. OpenGL 3.1 and GLSL 1.40 or later are required. This extension interacts with OpenGL 3.3 and ARB_explicit_attrib_location. This extension interacts with OpenGL 4.0 and ARB_vertex_attrib_64bit. This extension interacts with OpenGL 4.0 and ARB_transform_feedback3. This extension interacts with OpenGL 4.1 and ARB_separate_shader_objects. This extension interacts with OpenGL 4.3 and ARB_shader_storage_buffer_object. This extension interacts with OpenGL 4.3 and ARB_program_interface_query. Overview This extension adds the following functionality to layout qualifiers, including broadening the API where this functionality is reflected. The following are added: 1) Use compile-time constant expressions. E.g., const int start = 6; layout(location = start + 2) int vec4 v; 2) Specify explicit byte offsets within a uniform or shader storage block. For example, if you want two vec4 variables "batman" and "robin" to appear at byte offsets 0 and 64 in your block, you can say: uniform Block { layout(offset = 0) vec4 batman; layout(offset = 64) vec4 robin; }; 3) Force alignment within a uniform or shader storage block. The previous example could also be expressed: uniform Block { vec4 batman; layout(align = 64) vec4 robin; }; This says the member 'robin' must start at the next address that is a multiple of 64. It allows constructing the same layout in C and in GLSL without inventing explicit offsets. Explicit offsets and aligned offsets can be combined: uniform Block { vec4 batman; layout(offset = 44, align = 8) vec4 robin; }; would make 'robin' be at the first 8-byte aligned address, starting at 44, which is 48. This is more useful when using the *align* at the block level, which will apply to all members. 4) Specify component numbers to more fully utilize the vec4-slot interfaces between shader outputs and shader inputs. For example, you could fit the following - an array of 32 vec3 - a single float into the space of 32 vec4 slots using the following code: // consume X/Y/Z components of 32 vectors layout(location = 0) in vec3 batman[32]; // consumes W component of first vector layout(location = 0, component = 3) in float robin; Further, an array of vec3 and an array of float can be stored interleaved, using the following. // consumes W component of 32 vectors layout(location = 0, component = 3) in float robin[32]; // consume X/Y/Z components of 32 vectors layout(location = 0) in vec3 batman[32]; 5) Specify transform/feedback buffers, locations, and widths. For example: layout(xfb_buffer = 0, xfb_offset = 0) out vec3 var1; layout(xfb_buffer = 0, xfb_offset = 24) out vec3 var2; layout(xfb_buffer = 1, xfb_offset = 0) out vec4 var3; The second line above says to write var2 out to byte offset 24 of transform/feedback buffer 0. (When doing this, output are only captured when xfb_offset is used.) To specify the total number of bytes per entry in a buffer: layout(xfb_buffer = 1, xfb_stride = 32) out; This is necessary if, say, var3 above, which uses bytes 0-11, does not fully fill the buffer, which in this case takes 32 bytes. Use of this feature effectively eliminates the need to use previously existing API commands to describe the transform feedback layout. 6) Allow locations on input and output blocks for SSO interface matching. For example: layout(location = 4) in block { vec4 batman; // gets location 4 vec4 robin; // gets location 5 layout(location = 7) vec4 joker; // gets location 7 vec4 riddler; // location 8 }; IP Status No known IP claims. New Procedures and Functions None. New Tokens Accepted in the array of GetProgramResourceiv: LOCATION_COMPONENT 0x934A TRANSFORM_FEEDBACK_BUFFER_INDEX 0x934B TRANSFORM_FEEDBACK_BUFFER_STRIDE 0x934C Accepted by the parameter of GetProgramInterfaceiv, GetProgramResourceIndex, GetProgramResourceName, and GetProgramResourceiv: TRANSFORM_FEEDBACK_BUFFER // reuse from core Modifications to the OpenGL 4.3 (Compatibility Profile) Specification Modify Section 7.3.1, Program Interfaces, p. 84 (insert after the TRANSFORM_FEEDBACK_VARYING bullet, p. 86) * TRANSFORM_FEEDBACK_BUFFER corresponds to the set of active buffer binding points to which output variables in the TRANSFORM_FEEDBACK_VARYING interface are written. (modify next-to-last paragraph, p. 87, to indicate that variables in the TRANSFORM_FEEDBACK_VARYING interface need not be sorted if specified via layout qualifiers) The order of the active resource list is implementation-dependent for all interfaces except for TRANSFORM_FEEDBACK_VARYING. If variables in the TRANSFORM_FEEDBACK_VARYING interface were specified using the TransformFeedbackVaryings command, the active resource list will be arranged in the variable order specified in the most recent call to TransformFeedbackVaryings before the last call to LinkProgram. If variables in the TRANSFORM_FEEDBACK_VARYING interface were specified using layout qualifiers in shader code, the order of the active resource list is implementation-dependent. (insert after the first paragraph, p. 88) For the TRANSFORM_FEEDBACK_BUFFER interface, the list of active buffer binding points is built by identifying each unique binding point to which one or more active output variables will be written in transform feedback mode. Active transform feedback buffers do not have an associated name string. (modify "Errors" section at the bottom of p. 89, for GetProgramInterfaceiv, handling the new TRANSFORM_FEEDBACK_BUFFER interface) An INVALID_OPERATION error is generated if pname is MAX_NAME_LENGTH and is ATOMIC_COUNTER_BUFFER or TRANSFORM_FEEDBACK_BUFFER, since active atomic counter and transform feedback buffer resources are not assigned name strings. An INVALID_OPERATION error is generated if pname is MAX_NUM_ACTIVE_VARIABLES and programInterface is not UNIFORM_BLOCK, SHADER_STORAGE_BLOCK, ATOMIC_COUNTER_BUFFER, or TRANSFORM_FEEDBACK_BUFFER. (modify the "Errors" section in the middle of p. 90, for GetProgramResourceIndex, handling the new TRANSFORM_FEEDBACK_BUFFER interface) An INVALID_ENUM error is generated if is ATOMIC_COUNTER_BUFFER or TRANSFORM_FEEDBACK_BUFFER, since active atomic counter and transform feedback buffer resources are not assigned name strings. (modify the "Errors" section in the middle of p. 90, for GetProgramResourceName, handling the new TRANSFORM_FEEDBACK_BUFFER interface) An INVALID_ENUM error is generated if is ATOMIC_COUNTER_BUFFER or TRANSFORM_FEEDBACK_BUFFER, since active atomic counter and transform feedback buffer resources are not assigned name strings. (modify existing entries in table 7.2, "GetProgramResourceiv properties and supported interfaces", pp. 92-93) Property Supported Interfaces ------------------- ---------------------------------------- NAME_LENGTH all but ATOMIC_COUNTER_BUFFER and TRANSFORM_FEEDBACK_BUFFER OFFSET UNIFORM, BUFFER_VARIABLE, TRANSFORM_FEEDBACK_VARYING BLOCK_INDEX, UNIFORM, BUFFER_VARIABLE ARRAY_STRIDE, MATRIX_STRIDE, IS_ROW_MAJOR BUFFER_BINDING UNIFORM_BLOCK, ATOMIC_COUNTER_BUFFER, NUM_ACTIVE_VARIABLES, SHADER_STORAGE_BLOCK, ACTIVE_VARIABLES TRANSFORM_FEEDBACK_BUFFER BUFFER_DATA_SIZE UNIFORM_BLOCK, ATOMIC_COUNTER_BUFFER, SHADER_STORAGE_BLOCK (add to table 7.2, "GetProgramResourceiv properties and supported interfaces", pp. 92-93) Property Supported Interfaces ------------------- ---------------------------------------- LOCATION_COMPONENT PROGRAM_INPUT, PROGRAM_OUTPUT TRANSFORM_FEEDBACK_ TRANSFORM_FEEDBACK_VARYING BUFFER_INDEX TRANSFORM_FEEDBACK_ TRANSFORM_FEEDBACK_BUFFER BUFFER_STRIDE (modify the third paragraph, p. 98) For the property OFFSET, a single integer identifying the offset of an active variable is written to . For variables in the UNIFORM and BUFFER_VARIABLE interfaces that are backed by a buffer object, the value written is the offset of that variable relative to the base of the buffer range holding its value. For variables in the TRANSFORM_FEEDBACK_VARYING interface, the value written is the offset in the transform feedback buffer storage assigned to each vertex captured in transform feedback mode where the value of the variable will be stored. Such offsets are specified via the /xfb_offset/ layout qualifier or assigned according to the variables position in the list of strings passed to TransformFeedbackVaryings. Offsets are expressed in basic machine units. For all variables not recorded in transform feedback mode, including the special names "gl_NextBuffer", "gl_SkipComponents1", "gl_SkipComponents2", "gl_SkipComponents3", and "gl_SkipComponents4", -1 is written to . (modify the next-to-last paragraph, p. 98) For the property BUFFER_BINDING, the index of the buffer binding point associated with the active uniform block, shader storage block, atomic counter buffer, or transform feedback buffer is written to . (modify the second and third paragraphs, p. 99) For the property NUM_ACTIVE_VARIABLES, the number of active variables associated with an active uniform block, shader storage block, atomic counter buffer, or transform feedback buffer is written to . For the property ACTIVE_VARIABLES, an array of active variable indices associated with an active uniform block, shader storage block, atomic counter buffer, or transform feedback buffer is written to . The number of values written to params for an active resource is given by the value of the property NUM_ACTIVE_VARIABLES for the resource. (insert after the first paragraph, p. 100) For the property LOCATION_COMPONENT, a single integer indicating the first component of the location assigned to an active input or output variable is written to . For input and output variables with a component specified by a qualifier, the specified component is written. For all other input and output variables, the value zero is written. (insert after the second paragraph, p. 100) For the property TRANSFORM_FEEDBACK_BUFFER_INDEX, a single integer identifying the index of the active transform feedback buffer associated with an active variable is written to . For variables corresponding to the special names "gl_NextBuffer", "gl_SkipComponents1", "gl_SkipComponents2", "gl_SkipComponents3", and "gl_SkipComponents4", -1 is written to . For the property TRANSFORM_FEEDBACK_BUFFER_STRIDE, a single integer identifying the stride, in basic machine units, between consecutive vertices written to the transform feedback buffer is written to . Modify Section 7.4.1, Shader Interface Matching, p. 105 (modify the last bullet of "An output variable is considered to match", adding the - the two variables are declared with the same location and component layout qualifiers and match in type and qualification (insert a new sentence to the beginning of the last paragraph, p. 105) For the purposes of interface matching, variables declared with a location layout qualifier but without a component layout qualifier are considered to have declared a component layout qualifier of zero. Variables or block members declared as structures... Modify Section 11.1.1, Vertex Attributes, p. 377 (replace the first two paragraphs, p. 378) When an attribute variable declared using one of the scalar or vector data types enumerated in table 11.1 is bound to a generic attribute index , its value(s) are taken from the components of generic attribute . The generic attribute components used depend on the type of the variable and value of the "component" layout qualifier (if any) specified in the variable declaration, as identified in table X.1. An attribute variable declared using a combination of data type and "component" layout qualifier not listed in this table is not supported and will result in shader compilation errors. "component" Data type layout qualifier Components used ---------------------- ---------------- --------------- scalar 0 or unspecified x scalar 1 y scalar 2 z scalar 3 w two-component vector 0 or unspecified (x,y) two-component vector 1 (y,z) two-component vector 2 (z,w) three-component vector 0 or unspecified (x,y,z) three-component vector 1 (y,z,w) four-component vector 0 or unspecified (x,y,z,w) Table X.1: Generic attribute components accessed by attribute variables When an attribute variable declared using a matrix type is bound to a generic attribute index , its values are taken from consecutive generic attributes beginning with generic attribute . Such matrices are treated as an array of column vectors with values taken from the generic attributes identified in table X.2. Individual column vectors are taken from generic attribute components according table X.1, using the vector type from Table X.2 and the "component" layout qualifier (if any) specified in the variable declaration. Data type Column vector type Generic attributes used --------------- -------------------- ------------------------ mat2 dmat2 two-component vector i, i+1 mat2x3 dmat2x3 three-component vector i, i+1 mat2x4 dmat2x4 four-component vector i, i+1 mat3x2 dmat3x2 two-component vector i, i+1, i+2 mat3 dmat3 three-component vector i, i+1, i+2 mat3x4 dmat3x4 four-component vector i, i+1, i+2 mat4x2 dmat4x2 two-component vector i, i+1, i+2, i+3 mat4x3 dmat4x3 three-component vector i, i+1, i+2, i+3 mat4 dmat4 four-component vector i, i+1, i+2, i+3 Table X.2: Generic attributes and vector types used by column vectors of matrix variables bound to generic attribute index . When an attribute variable declared using an array type is bound to generic attribute index , the active array elements are assigned to consecutive generic attributes beginning with generic attribute . The number of attributes and components assigned to each element are determined according to the data type of array elements and "component" layout qualifier (if any) specified in the declaration of the array, as described above. Modify Section 11.1.2.1, Output Variables (Vertex Shaders), p. 383 (insert before the third paragraph, p. 384) The set of variables to record can be specified in shader text using the "xfb_buffer", "xfb_offset", or "xfb_stride" layout qualifiers. When recording output variables of each vertex in transform feedback mode, a fixed amount of memory is reserved in the buffer bound to each transform feedback buffer binding point. Each output variable recorded is associated with a binding point, specified by the "xfb_buffer" layout qualifier. Each output variable is written to its associated transform feedback binding point at an offset specified by the "xfb_offset" layout qualifier, in basic machine units, relative to the base of the memory reserved for its vertex. The amount of memory reserved in each transform feedback binding point for a single vertex can be specified using the "xfb_stride" layout qualifier. If no "xfb_stride" qualifier is specified for a binding point, the stride is derived by identifying the variable associated with the binding point having the largest offset, and then adding the offset and the size of the variable, in basic machine units. If any variable associated with the binding point contains double-precision floating-point components, the derived stride is aligned to the next multiple of eight basic machine units. If a binding point has no "xfb_stride" qualifier and no associated output variables, its stride is zero. (modify third paragraph, p. 384) When no "xfb_buffer", "xfb_offset", or "xfb_stride" layout qualifiers are specified, the set of variables to record is specified with the command void TransformFeedbackVaryings(uint program, ... (replace last paragraph, p. 384) The variables in are assigned binding points and offsets sequentially, as though each were specified using the "xfb_buffer" and "xfb_offset" layout qualifiers. The strides associated with each binding point are derived by adding the offset and size of the last variable associated with that binding point. The first variable in is assigned a binding point and offset of zero. When is INTERLEAVED_ATTRIBS, each subsequent variable is assigned to the same binding point as the previous variable and an offset equal to the sum of the offset and size of of the previous variable. When is SEPARATE_ATTRIBS, each subsequent variable is assigned to the binding point following the binding point of the previous variable with an offset of zero. Several special identifiers are supported when is INTERLEAVED_ATTRIBS. These identifiers do not identify output variables captured in transform feedback mode, but can be used to modify the binding point and offsets assigned to subsequent variables. If a string in is "gl_NextBuffer", the next variable in will be assigned to the next binding point, with an offset of zero. If a string in is "gl_SkipComponents1", "gl_SkipComponents2", "gl_SkipComponents3", or "gl_SkipComponents4", the variable is treated as as specifying a one- to four-component floating-point output variable with undefined values. No data will be recorded for such strings, but the offset assigned to the next variable in and the stride of the assigned binding point will be affected. (modify first paragraph after the errors section, p. 385) The state set by TransformFeedbackVaryings or using transform feedback layout qualifiers has no effect on the execution of the program until program is subsequently linked. When LinkProgram is called, the program is linked so that the values of the specified outputs for the vertices of each primitive generated by the GL are written to one or more buffer objects. If the set of output variables to record in transform feedback mode is specified by TransformFeedbackVaryings, a program will fail to link if: (insert after the first set of bullets, p. 386) If the set of output variables to record in transform feedback mode is specified using layout qualifiers, a program will fail to link if: * any pair of variables associated with the same binding point overlap in memory (where the offset of the first variable is less than or equal to the offset of the second, but the sum of the offset and size of the first variable is greater than the offset of the second); * any binding point has a stride declared using the "xfb_stride" layout qualifier and the sum of the offset and size of any variable associated with that binding point exceeds the value of this stride; * any variable containing double-precision floating-point components * has an "xfb_offset" layout qualifier that is not a multiple of eight; or * is associated with a binding point with an "xfb_stride" layout qualifier that is not a multiple of eight; * the sum of the offset and size of any variable exceeds the maximum stride supported by the implementation (four times the value of MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS); or * the "xfb_stride" layout qualifier for any binding point exceeds the maximum stride supported by the implementation. (modify the two paragraphs following the bullets, p. 386) For transform feedback purposes, each component of outputs declared as double-precision floating-point scalars, vectors, or matrices are considered to consume eight basic machine units, and each component of any other type is considered to consume four basic machine units. To determine the set of output variables in a linked program object that will be captured in transform feedback mode and the binding points to which those variables are written, applications can query the properties and active resources of the TRANSFORM_FEEDBACK_VARYING and TRANSFORM_FEEDBACK_BUFFER interfaces. (insert before the fourth paragraph, starting with "Additionally, the command" on p. 386) If the shader used to record output variables for transform feedback varyings uses the "xfb_buffer", "xfb_offset", or "xfb_stride" layout qualifiers, the values specified by TransformFeedbackVaryings are ignored, and the set of variables captured for transform feedback is instead derived from the specified layout qualifiers. Modify Section 13.2.2, Transform Feedback Primitive Capture, p. 457 (split the first paragraph, p. 459, and replace the second half of the paragraph with the following language) ... attributes of the subsequent vertices. When capturing vertices, the stride associated with each transform feedback binding point indicates the number of basic machine units of storage reserved for each vertex in the bound buffer object. For every vertex captured, each output variable with an assigned transform feedback offset will be written to the storage reserved for the vertex at the associated binding point. When writing output variables that are arrays or structures, individual array elements or structure members are written in order. For vector types, individual components are written in order. For matrix types, outputs are written as an array of column vectors. If any component of an output with an assigned transform feedback offset was not written to by its shader, the value recorded for that component is undefined. The results of writing an output variable to a transform feedback buffer are undefined if any component of that variable would be written at an offset not aligned to the size of the component. When capturing a vertex, any portion of the reserved storage not associated with an output variable with an assigned transform feedback offset will be unmodified. (delete the last three paragraphs, p. 459, which describe INTERLEAVED_ATTRIBS and SEPARATE_ATTRIBS mode; this is already handled by the language defining TransformFeedbackAttribs in terms of offsets and strides) (modify the first paragraph, p. 460, removing the incorrect reference to "geometry program") When using a geometry shader that writes vertices to multiple ... (modify the third paragraph, p. 460) Any transform feedback binding point used for capturing vertices must have buffer objects bound when BeginTransformFeedback is called. A binding point requires a bound buffer object if and only if its associated stride in the program object used for transform feedback primitive capture is non-zero and the transform feedback buffer is associated with output variables, blocks or block members in the program object. Modify Section 15.2.3, Shader Outputs (Fragment Shader Variables), p. 514 (modify the fifth paragraph, p. 515, making an output variable binding refer to "components of a fragment color") The binding of a user-defined output variable to components of a fragment color number can be specified explicitly in shader text or using the command... (modify the third paragraph, p. 516) When a program is linked, each active user-defined fragment shader output variable will have a binding consisting of a fragment color number, a fragment color index, and a component index. Output variables declared with "location", "component", or "index" layout qualifiers will use the values specified in the shader text. Output variables without such layout qualifiers will use bindings specified by BindFragDataLocationIndexed or BindFragDataLocation, if any. Otherwise, the linker will automatically assign a fragment color number, using any color number not already assigned to another active fragment shader output variable. The fragment color index and component index of an output variable binding will default to zero unless values are explicitly specified by a layout qualifer or BindFragDataLocationIndexed. The properties of an active fragment shader output variable binding can be queried using the command GetProgramResourceiv with a of PROGRAM_OUTPUT and values of LOCATION, LOCATION_INDEX, and LOCATION_COMPONENT. When a fragment shader terminates, the value of each active user-defined output variable is written to components of the fragment color output to which it is bound. The set of fragment color components written is determined according to the variable's data type and component index binding, using the mappings in table X.1. For an output variable declared as an array bound to fragment color number , individual active array elements are written to consecutive fragment color numbers beginning with , with the components written determined from the array element's data type and the array variable's component index binding. Output binding assignments will cause LinkProgram to fail: (modify the third bullet immediately below the previous edit, p. 516, and add a new bullet immediately after it) * if two output variables are bound to the same output number and index with overlapping components selected; * if two output variables with different component types (signed integer, unsigned integer, or floating-point) are bound to the same output number, even if selected components do not overlap; or Additions to the OpenGL Shading Language Including the following line in a shader can be used to control the language features described in this extension: #extension GL_ARB_enhanced_layouts : where is as specified in section 3.3. New preprocessor #defines are added to the OpenGL Shading Language: #define GL_ARB_enhanced_layouts 1 Additions to Chapter 4 "Variables and Types" of the OpenGL Shading Language Section 4.4 "Layout Qualifiers" The existing last paragraph already says: "More than one layout qualifier may appear in a single declaration. If the same layout-qualifier-name occurs in multiple layout qualifiers for the same declaration, the last one overrides the former ones." Expand it to say: "More than one layout qualifier may appear in a single declaration. Additionally, the same layout-qualifier-name can occur multiple times within a layout qualifier or across multiple layout qualifiers in the same declaration. When the same layout-qualifier-name occurs multiple times, in a single declaration, the last occurrence overrides the former occurrence(s). Further, if such a layout-qualifier-name will effect subsequent declarations or other observable behavior, it is only the last occurrence that will have any effect, behaving as if the earlier occurrence(s) within the declaration are not present. This is also true for overriding layout-qualifier-names, where one overrides the other (e.g., row_major vs. column_major); only the last occurrence has any effect." Section 4.4.1 "Input Layout Qualifiers" Change "All shaders, except compute shaders, allow input layout location qualifiers on input variable declarations." To "All shaders, except compute shaders, allow *location* layout qualifiers on input variable declarations, input block declarations, and input block member declarations. Of these, variables and block members (but not blocks) additionally allow the *component* layout qualifier." Change "The layout qualifier identifier for inputs is "layout-qualifier-id location = integer-constant "Only one argument is accepted. For example," to "The layout qualifier identifiers for inputs are "layout-qualifier-id location = integral-constant-expression component = integral-constant-expression "where integral-constant-expression is defined in Section 4.3.3 Constant Expressions as /integral constant expression/" "For example," Add more examples: const int start = 6; layout(location = start + 2) int vec4 v; and change the first sentence describing them to "will establish that the shader input normal is assigned to vector location number 3 and v is assigned location number 8." About 18 other occurrences of "integer-constant" all need to be changed per above to "integral-constant-expression", throughout Sections 4.4.1.2 through 4.4.6.2. Change "If the declared input is a structure, its members will be assigned consecutive locations in the order of declaration, with the first member assigned the location specified for the structure." To "If the declared input is a structure or block, its members will be assigned consecutive locations in their order of declaration, with the first member assigned the location provided in the layout qualifier. For a structure. It is a compile-time error to use a location qualifier on a member of a structure. For a block, this process applies to the entire block, or until the first member is reached that has a location layout qualifier. When a block member is declared with a location qualifier, its location comes from that qualifier: The member's location qualifier overrides the block-level declaration. Subsequent members are again assigned consecutive locations, based on the newest location, until the next member declared with a *location* layout qualifier. The values used for locations do not have to be declared in increasing order. "It is a compile-time error to declare a block with some of its members having a location, but not all. Thus, if a block has no block-level *location* layout qualifier, it is required that either all or none of its members have a *location* layout qualifier." Change the next paragraph so it reads "The locations consumed by block and structure members are determined..." Change the subsequent examples to layout(location = 3) in struct S { vec3 a; // gets location 3 mat2 b; // gets locations 4 and 5 vec4 c[2]; // gets locations 6 and 7 layout (location = 8) vec2 A; // ERROR, can't use on struct member } s; layout(location = 4) in block { vec4 d; // gets location 4 vec4 e; // gets location 5 layout(location = 7) vec4 f; // gets location 7 vec4 g; // gets location 8 layout (location = 1) vec4 h; // gets location 1 vec4 i; // gets location 2 vec4 j; // gets location 3 vec4 k; // ERROR, location 4 already used }; Remove the paragraph "Location layout qualifiers may be used on input variables declared as structures, but not on individual members. Location layout qualifiers may not be used on input blocks or input block members. Compile-time errors result if these rules are not followed." Replace the paragraph (parts of it show up again at the end of this section) "A program will fail to link if any two non-vertex shader input variables or block members are assigned to the same location...." with part of it's last sentence (keep this here): "A program will fail to link if explicit location assignments leave the linker unable to find space for other variables without explicit assignments." Add, after the specification for 'location', the following: "The *component* qualifier allows the location to be more finely specified for scalars and vectors, down to the individual components within a location that are consumed. It is a compile-time error to use *component* without also specifying *location* (order does not matter). The components within a location are 0, 1, 2, and 3. A variable or block member starting at component N will consume components N, N+1, N+2, ... up through its size. For example: // a consumes components 2 and 3 of location 4 layout(location = 4, component = 2) vec2 a; // b consumes component 1 of location 4 layout(location = 4, component = 1) float b; // ERROR: c overflows components 2 and 3 layout(location = 3, component = 2) vec3 c; "If the variable is an array, each element of the array, in order, is assigned to consecutive locations, but all at the same specified component within each location. For example: // component 3 in 6 locations are consumed layout(location = 2, component = 3) float d[6]; "That is, location 2 component 3 will hold d[0], location 3 component 3 will hold d[1], ..., up through location 7 component 3 holding d[5]. "This allows packing of two arrays into the same set of locations: // e consumes beginning (components 0, 1 and 2) of each of 6 slots layout(location = 0, component = 0) vec3 e[6]; // f consumes last component of the same 6 slots layout(location = 0, component = 3) float f[6]; "If applying this to an array of arrays, all levels of arrayness are removed to get to the elements that are assigned per location to the specified component. These non-arrayed elements will fill the locations in the order specified for arrays of arrays in section 4.1.9 "Arrays". "It is a compile-time error to apply the *component* qualifier to a matrix, a structure, a block, or an array containing any of these. It is a link-time error to specify different components for the same variable within a program. "/Location aliasing/ is causing two variables or block members to have the same location number. /Component aliasing/ is assigning the same (or overlapping) component numbers for two location aliases. (Recall if component is not used, component's are assigned starting with 0.) With one exception, location aliasing is allowed only if it does not cause component aliasing; it is a compile-time or link-time error to cause component aliasing. Further, when location aliasing, the aliases sharing the location must have the same underlying numerical type (floating-point or integer) and the same auxiliary storage and interpolation qualification. The one exception where component aliasing is permitted is for two input variables (not block members) to a vertex shader, which are allowed to have component aliasing. This vertex-variable component aliasing is intended only to support vertex shaders where each execution path accesses at most one input per each aliased component. Implementations are permitted, but not required, to generate link-time errors if they detect that every path through the vertex shader executable accesses multiple inputs aliased to any single component." Section 4.4.2 "Output Qualifiers" Change "All shaders, except compute shaders, allow location output layout qualfiers on output variable declarations." To "As with input layout qualifiers, all shaders except compute shaders allow *location* layout qualifiers on output variable declarations, output block declarations, and output block member declarations. Of these, variables and block members (but not blocks) additionally allow the *component* layout qualifier." And add the layout-qualifier-id: component = integer-constant-expression Following that, add this new paragraph: "The usage and rules for using the *component* qualifier, and applying *location* qualifier to blocks and structures, are as described in section 4.4.1 "Input Layout Qualifiers". Additionally, for fragment shader outputs, if two variables are placed within the same location, they must have the same underlying type (floating-point or integer). No component aliasing of output variables or members is allowed." Remove the second (redundant) location = integer-constant Add a new section 4.4.2.1 "Transform Feedback Layout Qualifiers" "The vertex, tessellation, and geometry stages allow shaders to control transform feedback. When doing this, shaders will dictate which transform feedback buffers are in use, which output variables will be written to which buffers, and how each buffer is laid out. To accomplish this, shaders allow the following layout qualifier identifiers on output declarations: layout-qualifier-id xfb_buffer = integral-constant-expression xfb_offset = integral-constant-expression xfb_stride = integral-constant-expression "Any shader making any static use (after preprocessing) of any of these *xfb_* qualifiers will cause the shader to be in a transform feedback capturing mode and hence responsible for describing the transform feedback setup. This mode will capture any output selected by *xfb_offset*, directly or indirectly, to a transform feedback buffer. "The *xfb_buffer* qualifier specifies which transform feedback buffer will capture those outputs selected with *xfb_offset*. The *xfb_buffer* qualifier can be applied to the qualifier out, to output variables, to output blocks, and to output block members. Shaders in the transform feedback capturing mode have an initial global default of layout(xfb_buffer = 0) out; "This default can be changed by declaring a different buffer with xfb_buffer on the interface qualifier out. This is the only way the global default can be changed. When a variable or output block is declared without an xfb_buffer qualifier, it inherits the global default buffer. When a variable or output block is declared with an xfb_buffer qualifier, it has that declared buffer. All members of a block inherit the block's buffer. A member is allowed to declare an xfb_buffer, but it must match the buffer inherited from its block, or a compile-time error results. "The *xfb_buffer* qualifier follows the same conventions, behavior, defaults, and inheritance rules as the qualifier stream, and the examples for stream apply here as well. This includes a block's inheritance of the current global default buffer, a block member's inheritance of the block's buffer, and the requirement that any *xfb_buffer* declared on a block member must match the buffer inherited from the block. layout(xfb_buffer=2, xfb_offset=0) out block { // block's buffer is 2 layout(xfb_buffer = 2) vec4 v; // okay, matches the inherited 2 layout(xfb_buffer = 3) vec4 u; // ERROR, mismatched buffer vec4 w; // inherited }; layout (xfb_offset=16) out vec4 t; // initial default is buffer 0 layout (xfb_buffer=1) out; // new global default of 1 out block { // block has buffer 1 vec4 x; // x has buffer 1 (not captured) layout(xfb_buffer = 1) vec4 y; // okay (not captured) layout(xfb_buffer = 0) vec4 z; // ERROR, mismatched buffer }; layout(xfb_offset=0) out vec4 g; // g has buffer 1 layout(xfb_buffer=2) out vec4 h; // does not change global default layout(xfb_offset=16) out vec4 j; // j has buffer 1 "Note this means all members of a block that go to a transform feedback buffer will go to the same buffer. "It is a compile-time error to specify an *xfb_buffer* that is greater than the implementation-dependent constant gl_MaxTransformFeedbackBuffers. "The *xfb_offset* qualifier assigns a byte offset within a transform feedback buffer. Only variables, block members, or blocks can be qualified with *xfb_offset*. If a block is qualified with *xfb_offset*, all its members are assigned transform feedback buffer offsets. If a block is not qualified with *xfb_offset*, any members of that block not qualified with an *xfb_offset* will not be assigned transform feedback buffer offsets. Only variables and block members that are assigned offsets will be captured (thus, a proper subset of a block can be captured). Each time such a variable or block member is written in a shader, the written value is captured at the assigned offset. If such a block member or variable is not written during a shader invocation, the buffer contents at the assigned offset will be undefined. Even if there are no static writes to a variable or member that is assigned a transform feedback offset, the space is still allocated in the buffer and still affects the stride. "Variables and block members qualified with *xfb_offset* can be scalars, vectors, matrices, structures, and (sized) arrays of these. The offset must be a multiple of the size of the first component of the first qualified variable or block member, or a compile-time error results. Further, if applied to an aggregate containing a double, the offset must also be a multiple of 8, and the space taken in the buffer will be a multiple of 8. The given offset applies to the first component of the first member of the qualified entity. Then, within the qualified entity, subsequent components are each assigned, in order, to the next available offset aligned to a multiple of that component's size. Aggregate types are flattened down to the component level to get this sequence of components. It is a compile-time error to apply xfb_offset to the declaration of an unsized array. "The *xfb_stride* qualifier specifies how many bytes are consumed by each captured vertex. It applies to the transform feedback buffer for that declaration, whether it is inherited or explicitly declared. It can be applied to variables, blocks, block members, or just the qualifier out. If the buffer is capturing any double-typed outputs, the stride must be a multiple of 8, otherwise it must be a multiple of 4, or a compile-time or link-time error results. It is a compile-time or link-time error to have any *xfb_offset* that overflows *xfb_stride*, whether stated on declarations before or after the *xfb_stride*, or in different compilation units. While *xfb_stride* can be declared multiple times for the same buffer, it is a compile-time or link-time error to have different values specified for the stride for the same buffer. "For example: // buffer 1 has 32-byte stride layout (xfb_buffer = 1, xfb_stride = 32) out; // same as previous example; order within layout does not matter layout (xfb_stride = 32, xfb_buffer = 1) out; // everything in this block goes to buffer 0 layout (xfb_buffer = 0, xfb_stride = 32) out block1 { layout (xfb_offset = 0) vec4 a; // a goes to byte offset 0 of buffer 0 layout (xfb_offset = 16) vec4 b; // b goes to offset 16 of buffer 0 }; layout (xfb_buffer = 1, xfb_offset = 12) out block2 { vec4 v; // v will be written to byte offsets 12 through 27 of buffer 1 float u; // u will be written to offset 28 layout(xfb_offset = 40) vec4 w; vec4 x; // x will be written to offset 56, the next available offset }; layout (xfb_buffer = 2, xfb_stride = 32) out block3 { layout (xfb_offset = 12) vec3 c; layout (xfb_offset = 24) vec3 d; // ERROR, requires stride of 36 layout (xfb_offset = 0) vec3 g; // okay, increasing order not required }; "When no *xfb_stride* is specified for a buffer, the stride of a buffer will be the smallest needed to hold the variable placed at the highest offset, including any required padding. For example: // if there no other declarations for buffer 3, it has stride 32 layout (xfb_buffer = 3) out block4 { layout (xfb_offset = 0) vec4 e; layout (xfb_offset = 16) vec4 f; }; "The resulting stride (implicit or explicit) must be less than or equal to the implementation-dependent constant gl_MaxTransformFeedbackInterleavedComponents." Section 4.4.2.1 Tessellation Control Outputs Insert in front of the first sentence: "Other than for the transform feedback layout qualifiers, Section 4.4.5 "Uniform and Shader Storage Blocks" Add offset and align to the list, making it be layout-qualifier-id shared packed std140 std430 row_major column_major binding = integral-constant-expression offset = integral-constant-expression align = integral-constant-expression Modify the paragraph starting soon after as "Default layouts..." to read: "Default layouts for shared, packed, std140, std430, row_major, and column_major are established at global scope for uniform blocks as" At the end of the section, add descriptions of these: "The *offset* qualifier can only be used on block members of blocks declared with *std140* or *std430* layouts. The *offset* qualifier forces the qualified member to start at or after the specified integral-constant-expression, which will be its byte offset from the beginning of the buffer. It is a compile-time error to specify an *offset* that is smaller than the offset of the previous member in the block or that lies within the previous member of the block. Two blocks linked together in the same program with the same block name must have the exact same set of members qualified with *offset* and their integral-constant-expression values must be the same, or a link-time error results. The specified offset must be a multiple of the base alignment of the type of the block member it qualifies, or a compile-time error results. "The *align* qualifier can only be used on blocks or block members, and only for blocks declared with *std140* or *std430* layouts. The *align* qualifier makes the start of each block member have a minimum byte alignment. It does not affect the internal layout within each member, which will still follow the std140 or std430 rules. The specified alignment must be a power of 2, or a compile-time error results. "The /actual alignment/ of a member will be the greater of the specified *align* alignment and the standard (e.g., *std140*) base alignment for the member's type. The /actual offset/ of a member is computed as follows: If *offset* was declared, start with that offset, otherwise start with the next available offset. If the resulting offset is not a multiple of the /actual alignment/, increase it to the first offset that is a multiple of the /actual alignment/. This results in the /actual offset/ the member will have. "When *align* is applied to an array, it effects only the start of the array, not the array's internal stride. Both an *offset* and an *align* qualifier can be specified on a declaration. "The *align* qualifier, when used on a block, has the same effect as qualifying each member with the same *align* value as declared on the block, and gets the same compile-time results and errors as if this had been done. As described in general earlier, an individual member can specify its own *align*, which overrides the block-level *align*, but just for that member." Section 4.5.1 "4.5.1 Redeclaring Built-in Interpolation Variables in the Compatibility Profile" Modify the paragraph starting "Ideally, these are redeclared..." to read "Ideally, these are redeclared as part of the redeclaration of an interface block, as described in section 7.1.1 `Compatibility Profile Built-In Language Variables'. However, for the above purpose, they can be redeclared as individual variables at global scope, outside an interface block. Such redeclarations also allow adding the transform-feedback qualifiers xfb_buffer, xfb_stride, and xfb_offset to output variables. (Using xfb_buffer on a variable does not change the global default buffer.)... ." Section 7.1 "Built-In Language Variables" Near the end of this section, around 2nd to last paragraph, which is: "This establishes the output interface the shader will use with the subsequent pipeline stage. It must be a subset of the built-in members of gl_PerVertex." Add the following: "Such a redeclaration can also add the invariant qualifier, interpolation qualifiers, and the layout qualifiers xfb_offset, xfb_buffer, and xfb_stride. It can also add an array size for unsized arrays. For example: out layout(xfb_buffer = 1, xfb_stride = 16) gl_PerVertex { vec4 gl_Position; layout(xfb_offset = 0) float gl_ClipDistance[4]; }; "Other layout qualifiers, like location, cannot be added to such a redeclaration, unless specifically stated." Examples: layout(std140) uniform block { vec4 a; layout(offset = 20) vec3 b; // b takes offsets 20-31 layout(offset = 28) vec2 c; // ERROR, lies within previous member layout(offset = 36) vec2 d; // d takes offsets 36-43 layout(align = 16) float e; // e takes offsets 48-51 layout(align = 2) double f; // f takes offsets 56-63 layout(align = 6) double g; // ERROR, 6 is not a power of 2 layout(offset = 68) float h; // h takes offsets 64-71 layout(align = 16) dvec3 i; // i takes offsets 80-103 layout(offset = 105, align = 4) float i; // i takes offsets 108-111 };" Additions to Chapter 7.3 "Built-In Constants" of the OpenGL Shading Language Add const int gl_MaxTransformFeedbackBuffers = 4; const int gl_MaxTransformFeedbackInterleavedComponents = 64; Additions to Chapter 9 "Shading Language Grammar for Core Profile" of the OpenGL Shading Language Change IDENTIFIER EQUAL INTCONSTANT to IDENTIFIER EQUAL constant_expression Additions to the AGL/EGL/GLX/WGL Specifications None GLX Protocol None Dependencies on OpenGL 3.3 and ARB_explicit_attrib_location If neither OpenGL 3.3 nor ARB_explicit_attrib_location are supported, new "location" and "component" layout qualifier support for vertex shader inputs and fragment shader outputs is not supported. Dependencies on OpenGL 4.0 and ARB_vertex_attrib_64bit If neither OpenGL 4.0 nor ARB_vertex_attrib_64bit is supported, references to double-precision attribute variables should be removed. Dependencies on OpenGL 4.0 and ARB_transform_feedback3 If neither OpenGL 4.0 nor ARB_transform_feedback3 are supported, only a single binding point can be used for transform feedback using INTERLEAVED_ATTRIBS, including the new layout qualifier approach. It will be a compile-time error to use an "xfb_buffer" layout qualifier with a value other than zero and the value of the implementation-dependent GLSL constant gl_MaxTransformFeedbackBuffers will be 1. Dependencies on OpenGL 4.1 and ARB_separate_shader_objects If neither OpenGL 4.1 nor ARB_separate_shader_objects are supported, new "location" and "component" layout qualifier support for inputs and outputs other than vertex shader inputs and fragment shader outputs is not supported. Dependencies on OpenGL 4.3 and ARB_shader_storage_buffer_object If neither OpenGL 4.3 nor ARB_shader_storage_buffer_object is supported, references to shader storage blocks should be removed. Dependencies on OpenGL 4.3 and ARB_program_interface_query If neither OpenGL 4.3 nor ARB_program_interface_query is supported, edits to section 7.3.1 and the corresponding tokens should be removed. Add an edit to the spec language describing GetTransformFeedbackVarying to indicate that when layout qualifiers are used to specify transform feedback offsets, the set of active transform feedback variables enumerated by GetTransformFeedbackVarying and related APIs appears in arbitrary order. Errors No new API errors. New State Modify Table 23.53, Program Object Resource State (cont'd) Initial Get Value Type Get Command Value Description Sec. ----------------------- ---- ----------- ------- ------------------------ ----- LOCATION_COMPONENT Z+ GetProgram- - location component 7.3.1 Resourceiv assigned to active resource New Implementation Dependent State None. Conformance Tests TBD Issues 1) Do we need a sizeof() operator to aid in assigning layout locations? Would it need to be queried from the app as well? Aligning based on the size of previous member is what the system already does. Do we have a use case that needs custom packing following a structure, which cannot be handled by an *align* layout identifier? RESOLUTION: No. 2) Do we need to allow layout locations to be placed on blocks? Discussion: Yes, for SSO matching by location. But, do we still need them on members? A block could still be a well-defined block of memory, and if an interface is mixing/matching content of a block it seems they put the wrong things together in a block. RESOLUTION: Add for members for symmetry with UBOs and some utility as well. Order doesn't matter. 3) Do we need to support discovery of the current offset? E.g., layout(offset = currentOffset + 3) RESOLUTION: No. 4) Should we add a component-space for layout locations, which is no longer vec4 centric, but purely component centric? This is perhaps difficult as an add-on feature, but rather needs the specs as a whole to drop the vec4 nature of inputs/outputs. RESOLUTION: No. This is deferred until a future release that can make a larger change in this area, e.g., wholly drop the vec4 slot nature of inputs/outputs. 5) Instead of dynamic selection of outputs for transform/feedback, use locations. RESOLUTION: Use syntax in the shader layout blocks, not an entry point in the API. Either "layout(transformfeedback: var1, var2 var3) out;" or tag individual members. Applies to both inside and outside blocks. 6) Is it an error to specify an *offset* that is not naturally aligned? RESOLUTION: Yes, all offsets should be naturally aligned, but see issue 10: it is natural alignment of the type, not the component. 7) Is there an error at some point if an xfb_buffer is not valid? There are two cases here A) the buffer number is valid, B) the buffer number is out of range. RESOLVED A) No, there is no error, it is valid because the shader said so. RESOLVED B) This should be a compile-time or link-time error. 8) What API changes are needed to support component locations? There is currently no mention of stages in the specification language above, implying all stages' inputs and outputs can specify component locations. Probably, we either need to drop input components to the vertex stage and output components from the fragment stage, or consider API changes needed to support them. RESOLUTION: Behavior is well-defined for all stages. Need to broaden query functions to include component numbers. 9) How do we keep xfb buffers within implementation-dependent widths? Is this known at compile time? RESOLUTION: The actual stride of the buffer is determined by the stride in the shader, overriding any API settings. However, it is a link-time error to go over the limits of either MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS GLSL only needs to include the limits for interleaved components. 10) For uniform-like buffers only: might want offset of a vec3 to be vec4 aligned, not just component-sized aligned. Is there a portable rule? Or implementation-dependent rule? RESOLUTION: Alignments will be multiples of the base alignment of the member's type. 11) The location associated with a vertex shader input variable or fragment shader output variable can be specified in the shader using a location layout qualifier or in the OpenGL API using commands such as BindAttribLocation and BindFragDataLocation. Should we provide new variants of the OpenGL API commands (e.g., BindAttribLocationComponent) allowing applications to specify components with locations? RESOLVED: No. 12) Vertex shader input and fragment shader output variables declared without a location layout qualifier will have a location assigned by the compiler. What components will be assigned to such variables? RESOLVED: All variables declared without a 'location' layout qualifier will be assigned a 'component' value of zero. The first component of any such vertex input variable will be taken from the first component of the corresponding generic attribute. The first component of any such fragment output variable will be written to the first component of corresponding fragment color. If we allowed to compiler to automatically assign vertex input or fragment output variables to components other than zero, it could avoid link errors in cases where a shader requires more locations than the implementation supports. However, such a change would break existing applications that query the locations of their input or output variables, since they wouldn't be expecting component assignments other than zero. If we really wanted to support this, we'd probably need a directive in the shader indicating that the compiler can assign to arbitrary components. 13) How should we allow applications to query the components associated with shader input and output variables? RESOLVED: Extend the generic ARB_program_interface_query (OpenGL 4.3) active resource query API GetProgramResourceiv by providing a new property LOCATION_COMPONENT. This will query the component associated with a location assignment, in the same way that the existing LOCATION and LOCATION_INDEX properties query the location and location index numbers. 14) OpenGL 4.3 also includes the queries GetProgramResourceLocation and GetProgramResourceLocationIndex to directly query the location and location index of a named variable. Should we provide a similar query GetProgramResourceLocationComponent for location components? RESOLVED: No. ARB_program_interface_query provided the GetProgramResourceLocation entry point to serve as a generic version of pre-4.3 entry points such as GetUniformLocation, and to a lesser extent GetActiveAttrib and GetFragDataLocation. These entry points, particularly GetUniformLocation, are commonly used. We also provided GetProgramResourceLocationIndex to query the much less commonly-used location index, mostly for completeness. Both commands are simply short-cuts; it's possible for an application to perform such queries by calling GetProgramResourceIndex to map a variable name to an active resource index and then calling GetProgramResourceiv to query the location or location index. If we care about full orthogonality, we should add a new GetProgramResourceComponent command. If not, applications could still query component bindings with the sequence above. Since the only way to assign non-zero component indices to input or output variables is via explicit shader text, these queries seem less important. In earlier versions of OpenGL, the compiler always assigned the locations of uniforms, and it was always necessary to query their locations to perform an update. 15) OpenGL 4.3 also includes older APIs to query the locations of vertex shader inputs and fragment shader outputs (GetActiveAttrib, GetFragDataLocation, GetFragDataIndex). Should we provide similar queries for location components? RESOLVED: No. We added the generic ARB_program_interface_query feature to OpenGL 4.3 so we didn't have to keep adding new APIs and tokens for every combination of resource type and property. 16) For active vertex shader inputs and fragment shader outputs, what happens if two variables with different basic component types are bound to different components of the same generic attribute or fragment color output? RESOLVED: For fragment shader outputs, generate a link error. For vertex shader inputs, no link error occurs. However, the values of any vertex shader input not matching the attribute type programmed in the API (via VertexAttrib* or VertexAttrib*Pointer) will be undefined. In unextended OpenGL 4.3, we already require that the generic attribute associated with a vertex shader input variable be specified using the same component type as the variable. Additionally, we require that the framebuffer attachments receiving a fragment output color must have the same component type as the output variable. In either case, values are undefined to avoid the overhead of a mandatory draw-time error check based on frequently-changed vertex attribute values. In code like the following: layout(location=3) in float var1; layout(location=4) in int var2; the value of is undefined if generic attribute 3 isn't specified with floating-point values and the value of is undefined if generic attribute 4 isn't specified with integer values. But it's always possible for an application to specify correct attribute values for each type. Mismatches due to component layout qualifers have similar problems. In a vertex shader with the following declarations: layout(location=3, component=0) in float var1; layout(location=3, component=1) in int var2; the vertex shader would want to read the component of generic attribute 3 as a floating-point value and the component of that attribute as a signed integer. We provide no way to specify separate components of a single attribute with a different type, so one of the values must be undefined if the shader is considered legal. We chose to make this illegal for fragment shader outputs, since it can't possibly do the right thing without relying on undefined raw bit-cast behavior. We do allow this for vertex shader inputs, because we've supported "aliasing" behavior since OpenGL 2.0. This allows for an "uber-shader" with variables like: layout(location=3) in float var1; layout(location=3) in int var2; where sometimes it uses and sometimes . Since we don't treat the code above (with overlapping components) as an error, it would be strange to treat non-overlapping component assignments as an error. 17) How will applications be able to query the layout of transform feedback varyings if they are specified in the shader? RESOLVED: Add the ability to query offset and active buffer associations for each variable in the TRANSFORM_FEEDBACK_VARYING interface, which can now be specified by layout qualifier. Additionally, add a new interface TRANSFORM_FEEDBACK_BUFFER, which enumerates the set of active binding points used in transform feedback (similar to the ATOMIC_COUNTER_BUFFER interface for atomic counter uniforms). In unextended OpenGL 4.3, transform feedback varyings are specified by passing a list of name strings to TransformFeedbackVaryings() before linking, where those name strings include both real variables and special "marker" variables like "gl_SkipComponents1" and "gl_NextBuffer". The application can then query back the list of transform feedback varyings and their properties, including markers, using the TRANSFORM_FEEDBACK_VARYING interface with the GetProgramResourceName and GetProgramResourceiv APIs. Additionally, applications can use the legacy OpenGL 3.0 API GetTransformFeedbackVarying(). The varyings are enumerated in the order specified in TransformFeedbackVaryings(), and it's up to the application to figure out the offsets/buffers assigned to each. ("Figuring" this out is often unnecessary, since applications have already specified the variable list.) The special markers need to be enumerated as variables in this API to allow the applications applications can figure out the storage. When using the existing enumeration API with variables with transform feedback layout qualifiers, the active variables are enumerated in arbitrary order and offsets/bindings can be queried explicitly. No special markers like "gl_NextBuffer" are enumerated. One other option considered was specifying that the linker reverse-engineer a list of outputs for TransformFeedbackVaryings based on layout qualifiers and then operate as if that list were provided directly. For example, if you specified something like: layout(xfb_buffer=0, xfb_stride=48) out; layout(xfb_buffer=0, xfb_offset=4) out vec4 batman; layout(xfb_buffer=2, xfb_offset=0) out vec4 robin; layout(xfb_buffer=2, xfb_offset=16) out vec3 joker; this reverse-engineering would build the following list: gl_SkipComponents1 // first 4 bytes batman // next 16 bytes gl_SkipComponents4 // another 16 bytes, still in buffer 0 gl_SkipComponents3 // final 12 bytes, per xfb_stride gl_NextBuffer gl_NextBuffer robin // first 16 bytes in buffer 2 joker // last 12 bytes in buffer 2 Having an API to query offsets and buffers more directly seemed preferable. The new API is patterned after the ATOMIC_COUNTER_BUFFER interface, which also has variables associated with a collection of numbered binding points. Consider the code above and an implementation that sorts active binding points and variables by declaration order. The commands GetProgramInterface(program, TRANSFORM_FEEDBACK_BUFFER, ACTIVE_RESOURCES, &value); GetProgramInterface(program, TRANSFORM_FEEDBACK_VARYING, ACTIVE_RESOURCES, &value); return 2 (binding points 0 and 2) and 3 ("batman", "robin", and "joker"). GetProgramInterface(program, TRANSFORM_FEEDBACK_BUFFER, MAX_NUM_ACTIVE_VARIABLES, &value); returns 2 (the two variables "robin" and "joker" associated with binding point 2). GetProgramResourceiv for the two active binding points in the TRANSFORM_FEEDBACK_BUFFER interface would return: property index 0 (binding 0) index 1 (binding 2) -------------------- -------------------- -------------------- BUFFER_BINDING 0 2 NUM_ACTIVE_VARIABLES 1 2 ACTIVE_VARIABLES { 0 } { 1, 2 } TRANSFORM_FEEDBACK_ 48 28 BUFFER_STRIDE GetProgramResourceiv for the three active variables in the TRANSFORM_FEEDBACK_VARYING interface would return: (batman) (robin) (joker) property index 0 index 1 index 2 -------------------- ------------ ------------ ------------ NAME_LENGTH 7 6 6 TYPE FLOAT_VEC4 FLOAT_VEC4 FLOAT_VEC3 ARRAY_SIZE 0 0 0 OFFSET 4 0 16 TRANSFORM_FEEDBACK_ 0 1 1 BUFFER_INDEX 18) If you have a program where transform feedback layout qualifiers are specified both in the shader text and via TransformFeedbackVaryings, what happens? RESOLVED: To be consistent with other features where similar things can happen (e.g., BindAttribLocation), we should allow the declarations in the shader text to "win". When LinkProgram is called, transform feedback state specified via TransformFeedbackVaryings() is ignored if the shader used for transform feedback specifies an "xfb_offset" layout qualifier on any of its variables. 19) Do we need #extension support for this feature? RESOLVED: Yes. There is no reason we couldn't support some of the features (e.g, UBO offset) on OpenGL 3.X hardware. We will require OpenGL 3.1 / GLSL 1.40, since this is where layout qualifiers were first supported. For each extended feature, we will require the relevant core version or extension: * OpenGL 3.3 and ARB_explicit_attrib_location for location and component qualifiers on vertex shader inputs and fragment shader outputs. * OpenGL 4.1 and ARB_separate_shader_objects for location and component qualifiers all other shader inputs and outputs. * OpenGL 4.0 and ARB_transform_feedback3 on multiple output buffers in interleaved mode (i.e., "xfb_buffer" values other than zero). * OpenGL 4.3 and ARB_shader_storage_buffer_object for extended layout qualifiers on shader storage blocks. * OpenGL 4.3 and ARB_program_interface_query to query offsets assigned to transform feedback varyings. 20) For "varyings" (e.g., vertex shader outputs, fragment shader inputs), component selection via layout qualifiers allow you to store two different variables in a single vector "location". Those variables might have different data types or interpolation qualifiers? Is this a problem for any implemenations of this extension? RESOLVED: We will have a compile-time or link-time error for differing types or different interpolation qualifiers assigned to the same location. 21) Is the new ability to query offsets and active buffers for each variable in the TRANSFORM_FEEDBACK_VARYING interface supported for programs whose transform feedback outputs are specified via TransformFeedbackVaryings? RESOLVED: Yes. The implementation will build a list of offsets/bindings during linking. 22) We do need to precisely define what it means to have transform feedback layout declared in the shader text (e.g., the XFB layout qualifiers are declared anywhere), and how various corner cases work. Examples: A) What qualifiers can be used globally on "out", on block declarations, and individual variables? B) If a shader has an "xfb_stride" qualifier for a buffer, but doesn't declare "xfb_offset" for any variable associated with that buffer, what happens? C) If the shader has an "xfb_buffer" qualifier identifying a buffer, but doesn't declare "xfb_offset" on anything associated with it, what happens? D) If we have variables with "xfb_offset" associated with buffers 0 and 2, what happens with buffer 1? E) If the shader declares "xfb_offset" on some but not all block members, what happens with the ones without an offset? Are they not captured? F) If a shader variable is qualified with "xfb_offset" but is not statically referenced, what happens? RESOLVED: For issue (A), we allow "xfb_offset" on blocks, block members, and variables. When using "xfb_offset" on a block, all members are assigned consecutive offsets. For issue (B), the buffer has N bytes reserved for each vertex, but nothing will be written to it. For issue (C), variables not qualified with "xfb_offset" are not captured, which makes the associated "xfb_buffer" qualifier irrelevant. For issue (D), nothing is captured to buffer 1, and if no "xfb_stride" qualifier is specified for buffer 1, no storage will be reserved there. For issue (E), block members without an offset are not captured. For issue (F), all variables with an assigned offset will have storage reserved (possibly affecting the stride) whether or not they are statically referenced. Unreferenced variables, as well as referenced variables not written for a given shader invocation, will be treated as having undefined values. 23) This is related to issues 16 and 20. Its resolution was that we would have an error if two fragment shader outputs with different component types were assigned to different components of the same location. We wouldn't have an error for vertex shader inputs because of the aliasing allowed in the spec since 2.0. What should we do for "varyings", which don't interface with resources in the API (vertex shader inputs, fragment shader outputs). Would implementations have a problem with the following pair of vertex shader outputs/fragment shader inputs? // different types, different components, same vector layout(location=2,component=1) out float f; layout(location=2,component=2) out int g; Further, for the "mixed component types in a vector", do we need language related to the automatic assignment of variables without a location? For example, let's say we had fragment outputs like: layout(location=0,component=3) out int f; layout(location=0,component=0) out vec3 g; we'd have an error due to the component type mismatch. But what if we had this? layout(location=0,component=3) out int f; out vec3 g; // location assigned by compiler Should the compiler would be required to avoid location 0 in this case, even though it could "fit" into the first three components? RESOLVED: For fragment outputs, no mixing is allowed, while for varyings between stages, the compiler is free to assign locations as it sees fit. If the underlying hardware is vector-based and requires all components of a vector to have identical types/qualifiers, it may need to avoid certain locations. If there is no such limitation, the compiler is free to pack variables of different types into a single location. 24) Should we allow "xfb_stride" layout qualifiers on block declations? Strides must be associated with a binding point ("xfb_binding"), but there is not a 1:1 correspondence between blocks and binding points. UNRESOLVED: TBD 25) Should we allow "xfb_offset" on block declarations to specify that all block members are captured with increasing offset? If so, should we allow the "xfb_offset" qualifier on block members to override the offset for that member and subsequent ones? Also, if we allow it, what happens if you try to qualfy a block member with a different value for "xfb_buffer"? UNRESOLVED: TBD 26) How should we handle "xfb_offset" and "xfb_stride" layout qualifiers when the shader specifies that it wants to capture double-precision scalars, vectors, matrices, as well as arrays and structures containing these types? UNRESOLVED: In unextended OpenGL 4.3, we specify undefined behavior if we attempt to capture any double-precision component that doesn't have an offset aligned to a multiple of 8 bytes. This is discussed in issue (4) of the ARB_gpu_shader_fp64 extension, which notes that to align all doubles captured, three things must happen: (a) the offset of the base of a buffer object must be a multiple of eight bytes; (b) the amount of data captured per vertex must be a multiple of eight bytes; and (c) each double-precision variable captured must be aligned to a multiple of eight bytes relative to the beginning of a vertex. We could have enforced restrictions (b) and (c) in LinkProgram in ARB_gpu_shader_fp64, but chose not to because we couldn't conveniently enforce (a). Applications can always work around issues (b) and (c) by injecting padding via "gl_SkipComponents1" markers in their list of varyings. We also could have (but didn't) specified that the linker would insert such padding automatically. It might have been a good idea to have enforced (b) and (c) anyway to reduce the cases where undefined behavior occurs. Since this extension provides a new way to specify output layout, we can choose to specify a new behavior when using the new method, without changing the handling of the old method. We are choosing to specify a link error if "xfb_offset" or "xfb_stride" is specified but incorrectly aligned, and to specify that the linker injects padding if the offset/stride are derived automatically. Revision History Revision 1, 19-Dec-2012 (JohnK) - Create overview. Revision 2, 21-Jan-2013 (JohnK) - Pin down a specific proposal in the overview, and add first 5 issues. Revision 3, 23-Jan-2013 (JohnK) - Allow locations on input/output blocks/members - Add details about alignment rules, aliasing, number ranges, etc. - Resolve issues 1, 2, 3, and 5. Revision 4, 14-Feb-2013 (JohnK) - Update from ARB meeting - Resolve issue 4 - Incorporate resolution of issue 5 Revision 5, 13-Mar-2013 (JohnK) - Simplify overview - First draft specification language for features 1-5 (not 6). Revision 6, 28-Mar-2013 (JohnK) - Change xfb streams and components to buffers and offsets (aligned and non aliasing) - Uniform buffer-like offsets must be naturally aligned. - Updated issues 6-9 Revision 7, 28-Mar-2013 (JohnK) - xfb_width -> xfb_stride, order doesn't matter - resolve issues 2, 7, 8, and 9 - add issue 10 Revision 8, 18-Apr-2013 (pbrown) - Add API specification language to query components assigned to input/output variables. - Add spec language describing the effects of component assignments to vertex shader inputs and fragment shader outputs, which interface with other API resources (generic attributes, FBO attachments). - Add stub spec language describing how transform feedback layout qualifiers operate in the API; we have issues to resolve before attempting the final language. - Add issues 11-18. Revision 9, 18-Apr-2013 (pbrown) - Add more issues, including issue 19. Revision 10, 3-May-2013 (pbrown) - Add new program interface query support for transform feedback varyings (to query offsets and binding points for each variable) and transform feedback buffers (to query stride). - Add an example of the enumeration API in issue 17. - Start reworking the transform feedback section to use a collection of variables with offsets and strides instead of a list of consecutive variables. - Add errors if a fragment shader output location is shared between variables with differetn component types. - Add clarifications on the process of assigning locations to fragment shader outputs (avoiding locations used by any explicit assignments). - Close a number of previously unresolved issues. - Add issues 20 and 21, and fork issue 22 from issue 18. Revision 11, 6-May-2013 (JohnK) - Resolve bug 10132, which includes doing the following: - Expand on the rules for repeated layout qualifiers, ordering, effect - Don't allow /component/ on structs - Initial statef of "layout(xfb_buffer = 0) out;" - rules for applying xfb_offset to a block, array, or matrix - add gl_MaxTransformFeedbackInterleavedComponents - restrict *align* to blocks and block members - unresolve issue 7 - update issue 9 - add issue 23 Revision 12, 7-May-2013 (JohnK) - Resolve bug 10130, which means the following: - Resolve issue 10 - alignments from the align qualifier will be a multiple of the base alignment of the type - offset qualifier ids must be a multiple of the base alignment of the type - minor typo fixes Revision 13, 9-May-2013 (JohnK) - Allow location layout qualifiers on input/output blocks - This incorporates the resolution of issue 2 Revision 14, 9-May-2013 (JohnK) - Resolved issues 7, 19, 20, 21, and 23. Revision 15, 10-May-2013 (JohnK) - Address feedback from pbrown review cycle Revision 16, 13-May-2013 (JohnK) - Add #extension (issue 19) - Add gl_MaxTransformFeedbackInterleavedComponents = 64; - Incorporated issues 7, 20, and 23 - Update issue 22 - Break out xfb_ stuff into its own section - Flesh out output location/component qualifier specification - Lots of editorial changes, including moving to bold for layout qualifier names Revision 17, 16-May-2013 (JohnK) - Resolve and incorporate issue 22. Revision 18, 18-May-2013 (pbrown) - Add API specification language for transform feedback-related link errors to cover cases of variables overflowing the specified stride of their associated binding. - Rework the API specification language describing how primitives are captured in transform feedback mode to deal in offsets and strides instead of ordered lists of variables. Revision 10 had already re-defined TransformFeedbackVaryings as specifying offsets and strides. - Clarify that the OFFSET property of the TRANSFORM_FEEDBACK_VARYING returns the actual offset used for the variable, whether it was specified directly using a layout qualifier or indirectly using TransformFeedbackVaryings (issue 21). - Remove reference to MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS in issue 9; when using layout qualifiers, we always capture in INTERLEAVED_ATTRIBS mode. - Cleaned up issue 22, added resolutions for each of the sub-issues. - Add issues 24 and 25. - Minor cleanups for a few other issues. Revision 19, 18-May-2013 (pbrown) - Add dependencies for use of ARB_enhanced_layouts as an extension. Require OpenGL 3.1 / GLSL 1.40, since that's where layout qualifiers were first added. For various features involving layout qualifers, require the extension or core version where those layout qualifiers were first supported. - Fix a typo involving MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS. - Close issue 19. Revision 20, 21-May-2013 (JohnK) - Remove erroneous disembodied xfb_stride example Revision 21, 21-May-2013 (pdaniell) - Assign enum token values Revision 22, 28-May-2013 (JohnK) - Fix bugs 10249 and 10267: Expand on (stream's) rules of inheritance for xfb_buffer, allow xbf_offset to be on both a block its members, and xfb_stride can appear an anything. Other clarifications. - Fix bug 10266: xfb_stride must be a multiple of 8 if capturing doubles, and offsets are aligned to multiples of the component's size. - Fix bug 10247: Describe how actual offsets are computed based on offset and align. - Fix bug 10248: Either a whole block has location layout qualification or none of it does. - Other minor editorial changes. Revision 23, 28-May-2013 (pbrown) - Add API language specifying that automatically derived transform feedback strides (when xfb_stride is not used) will be padded out to a multiple of 8 when the buffer captures one or more doubles. - Add API language specifying a link error if the "xfb_offset" set for any variable containing doubles is not a multiple of 8, or if the "xfb_stride" set for any binding point with an associated variable containing doubles is not a multiple of 8. - Add issue 26. Revision 24, 30-May-2013 (pbrown) - Fixed a typo in the dependencies section for OpenGL 4.1 and ARB_separate_shader_objects. Revision 25, 31-May-2013 (JohnK) - Bug 10248: Redo aliasing language regarding location and component aliasing. - Bug 10318: More strongly state that align operates at the member level and not internally within members. - Bug 10321: More strongly state that xfb_offset applied to aggregates (arrays, structures, nesting,...) operates by flattening the aggregate down to a sequence of components. Revision 26, 3-July-2013 (JohnK) - Include mention of API changes in the overview, and fix the offset example. - Bug 10371: Be explicit that when the gl_PerVertex block is redeclared, the declaration can add on invariant, xfb_offset, xfb_buffer, and xfb_strideto its members, as well as array size for gl_ClipDistance. - Bug 10327: Editorial: Expanded the introduction to the transform-feedback section. Described inheritance for xfb_bufferwithout referring to stream. - A few minor editorial corrections. Revision 27, June 13, 2014 (Jon Leech) - Remove GetProgramResourceLocation* as commands accepting the TRANSFORM_FEEDBACK_BUFFER interface from the New Tokens section (Bug 10588). Revision 28, January 10, 2019 (Jon Leech) - Clarify that a transform feedback buffer only needs to be bound if the buffer is active (gitlab #38).