blob: 5290f63a49deab76baec7ba84701311f9e525efe [file] [log] [blame]
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 <props> array of GetProgramResourceiv:
LOCATION_COMPONENT 0x934A
TRANSFORM_FEEDBACK_BUFFER_INDEX 0x934B
TRANSFORM_FEEDBACK_BUFFER_STRIDE 0x934C
Accepted by the <programInterface> 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
<programInterface> 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 <programInterface> 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 <programInterface> 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 <params>. 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 <params>.
(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 <params>.
(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 <params>.
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 <params>. 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 <params>. For input and output variables with a component
specified by a <layout> 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 <params>. For variables
corresponding to the special names "gl_NextBuffer", "gl_SkipComponents1",
"gl_SkipComponents2", "gl_SkipComponents3", and "gl_SkipComponents4", -1
is written to <params>.
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 <params>.
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 <i>,
its value(s) are taken from the components of generic attribute <i>. 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 <i>, its values are taken from consecutive generic
attributes beginning with generic attribute <i>. 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 <i>.
When an attribute variable declared using an array type is bound to
generic attribute index <i>, the active array elements are assigned to
consecutive generic attributes beginning with generic attribute <i>. 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 <varyings> 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 <varyings> is
assigned a binding point and offset of zero. When <bufferMode> 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 <bufferMode> 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 <bufferMode> 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
<varyings> is "gl_NextBuffer", the next variable in <varyings> will be
assigned to the next binding point, with an offset of zero. If a string
in <varyings> 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 <varyings> 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 <programInterface> of PROGRAM_OUTPUT and
<props> 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 <i>, individual active array
elements are written to consecutive fragment color numbers beginning with
<i>, 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 : <behavior>
where <behavior> 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.)...
<rest of paragraph>."
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 <var1> is undefined if generic attribute 3 isn't
specified with floating-point values and the value of <var2> 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 <x> component of generic
attribute 3 as a floating-point value and the <y> 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 <var1> and sometimes <var2>. 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).