Layout Qualifier (GLSL)

Revision as of 23:15, 15 August 2013 by Alfonse (Talk | contribs) (Interface layouts: Interface components via enhanced_layouts.)

Jump to: navigation, search

A number of OpenGL Shading Language variables and definitions can have layout qualifiers associated with them. Layout qualifiers affect where the storage for a variable comes from, as well as other user-facing properties of a particular definition.

All layout qualifiers are defined with a common syntax:

layout(qualifier1​, qualifier2​ = value, ...) variable definition

The qualifier​ values are specific to a particular use of layouts. The qualifiers are order-independent, unless otherwise noted. Some qualifiers can have values assigned to them, as with qualifier2​ in the above example.

In the above, value must be an integer literal, unless you are using OpenGL 4.4/ARB_enhanced_layouts, in which case it may be an Integral Constant Expression (aka: a compile-time constant).

Layout qualifiers are sometimes used to define various options for different shader stages. These shader stage options apply to the input of the shader stage or the output. In these definitions, variable definition will just be in​ or out​.

In OpenGL 4.2/ARB_shading_language_420pack, a definition can have multiple layout()​ segments to qualify the definition, and and the same qualifier​ can appear multiple times for the same definition. When this happens, the last defined value for mutually-exclusive qualifiers or for numeric qualifiers prevails.

Interface layouts

Shader stage input and output variables define a shader stage's interface. Depending on the available feature set, these variables can have layout qualifiers that define what resources they use.

Vertex shader attribute index

Vertex shader inputs can specify the attribute index that the particular input uses. This is done with this syntax:

layout(location = attribute index) in vec3 position;

With this syntax, you can forgo the use of glBindAttribLocation entirely. If you try to combine the two and they conflict, the layout qualifier always wins.

Attributes that take up multiple attribute slots will be given a sequential block of that number of attributes in order starting with the given attribute. For example:

layout(location = 2) in vec3 values[4];

This will allocate the attribute indices 2, 3, 4, and 5.

Fragment shader buffer output

Fragment shader outputs can specify the buffer index that a particular output writes to. This uses the same syntax as vertex shader attributes:

layout(location = output index) out vec4 outColor;

As with vertex shader inputs, this allows the user to forgo the use of glBindFragDataLocation. Similarly, the values in the shader override the values provided by this function.

For dual source blending, the syntax includes a second qualifier:

layout(location = output index, index = dual output index) out vec4 outColor;

Again, this allows one to forgo the use of glBindFragDataLocationIndexed.

Program separation linkage

Program Separation
Core in version 4.5
Core since version 4.1
Core ARB extension ARB_separate_shader_objects

When dynamically using separate programs, the correspondence between the outputs of one program and the inputs of the next is important. This correspondence typically happens the same way as when doing dynamic linkage: inputs and outputs must match by name, type, and qualifiers exactly (with a few exceptions).

However, it is possible to tag variables with an index, such that they correspond by the index instead of by name. This changes the interface matching process a bit, allowing outputs that aren't consumed by the next stage and so forth.

This index is provided by location​ qualifier. This applies to loose input/output variables. Input and output#Interface block variables need additional functionality to use these.

For example, given a vertex shader that provides these outputs:

layout(location = 0) out vec4 color;
layout(location = 1) out vec2 texCoord;
layout(location = 2) out vec3 normal;

This allows the consuming shader to use different names and even types:

layout(location = 0) in vec4 diffuseAlbedo;
layout(location = 1) in vec2 texCoord
layout(location = 2) in vec3 cameraSpaceNormal;

This still results in an interface match.

Note: The ARB_separate_shader_objects extension was released in a form where this kind of layout location linking outside of separate shaders did not work. That is, if you specified location indices, they were effectively ignored unless you were linking a separate program. The spec was changed to fix this, so that linkage would be the same whether separate or together; if location indices are specified, they are always used. However, AMD implemented the old behavior for a time, and it is not clear that their implementation was updated to fix this.

Location sizes: Interfaces between programs can be of various types, even user-defined structs and arrays. Some such types consume multiple locations. When a type that consumes multiple locations is used, they will consume locations sequentially. It is a compile/link-time error to have ranges of variables overlap their locations (unless they have different components specifiers and don't overlap their component usage).

Scalars and vector types that are not doubles all take up one location. The double​ and dvec2​ types also take one location, while dvec3​ and dvec4​ take up 2 locations. Structs take up locations based on their member types, in-order. Arrays also take up locations based on their array sizes.

Here are some examples:

struct OutData
  vec3 data1;
  dvec4 data2;
  float val[3];

layout(location = 0) out vec3 vals[4];    //Consumes 4 locations
layout(location = 4) out OutData myOut;   //Consumes 6 locations. dvec4 uses 2, and `val[3]` uses 3 total
layout(location = 10) out vec2 texCoord;  //Consumes 1 location

The number of available locations is implementation-defined, and it cannot be queried. However, it will be at least one-fourth of GL_MAX_VARYING_COMPONENTS.

Block member locations

Block member locations
Core in version 4.5
Core since version 4.4

With this feature, The location​ qualifier can be used on input/output interface block definitions and members.

Note: This feature does not exist to allow separate linking to work differently for interface blocks. So even if an interface block uses location qualifiers, the linking will still require an exact match between the blocks. This feature is here to support component specifications and location aliasing, which requires specifying an explicit location.

The block as a whole can have a location​ qualifier. This will allocate a sequential sets of locations, giving the first member the given location and incrementing from there. The size of the individual members is computed the same way as above.

A particular member of a block can have a location​ qualifier. However, this only works if the block itself is qualified or if all members of the block have a qualifier.

If the block has a qualifier, then a member's qualifier overrides the block computed qualifier. It also resets the block's computed qualifier, so that subsequent unqualified members will be computed relative to the most recent explicit qualifier. Here is an example:

layout(location = 0) out Block
  vec2 first;                        //Location 0.
  dvec4 second[3];                   //Location 1.
  vec4 third;                        //Location 7; dvec4 takes 2 each, and the prior one has 3 array members.
  layout(location = 10) vec2 fourth; //Location 10.
  dvec4 fifth;                       //Location 11. Starts from the most recent explicit location.
  layout(location = 8) dvec3 sixth;  //Location 8.
  vec3 seventh;                      //Location 10, overlaps with `fourth`, so causes an error.

Interface components

Interface components
Core in version 4.5
Core since version 4.4

There are limits on the locations of input and output variables. These limits are based on an implicit assumption in the API that the resources being passed around are done so as groups of 4-element vectors of data. This is why a mat2​ takes up 2 locations, while a vec4​ only takes up 1, even though they both are 4 floats in size. The mat2​ is considered to be passed as two vec4​s; the last two components of each vector simply go unused.

It is possible to reclaim some of this unused space. To do this, you declare two (or more) variables that use the same location, but use different components within that location.

This is done using the component​ layout qualifier. You must use a location​ qualifier when using component​, even if the variable would have an implicitly assigned location from an interface block declaration. If a variable does not have an explicit component​ qualifier, it is as through it were set to 0.

The component specifies the starting component that the variable will use. It is illegal to set the component on a variable who's type would cause it to exceed the boundaries of a 4-element vector. So if you have a vec3​, the component​ can only be 0 or 1.

If you set two interface variables to the same location, the variables must use components such that the used space in that location does not overlap. So you can't pack a vec3​ in the same location with a vec2​, but you can pack two floats​ with a {{code|vec2}.

Arrays (and arrays of arrays) can also have components assigned. This will assign the component to each location that the array covers. So it is possible to do the following:

layout(location = 0) out vec2 arr1[5];
layout(location = 0, component = 2) out vec2 arr2[4]; //Different sizes are fine.
layout(location = 4, component = 2) out float val; //A non-array steaks a component from arr1[4].

Two (or more) variables that share the same location must satisfy the following conditions:

  • Share the same base data type. So you can have alias locations for floating-point types, or integer types (signed and unsigned does not matter for this), but you cannot have a float alias with an integer.
  • Use the same interpolation qualifiers.

The component​ qualifier may not be used for:

  • Variables of matrix types
  • Variables of structs
  • Interface blocks (they can be on members of a block, but not on the block itself)
  • Arrays of the above
Note: Previously, it was stated that it is illegal for two interface variables to use the same location and overlap their components. That is not entirely true. It is legal to do so for vertex shader inputs and fragment shader outputs. But only so long as any particular vertex shader invocation cannot read from both of the inputs, and any particular fragment shader invocation does not write to both outputs. You are advised to forget that this is possible; there's not much point to it.

Binding points

Binding points
Core in version 4.5
Core since version 4.2
Core ARB extension ARB_shading_language_420pack

Uniform and shader storage blocks, and all opaque types have a value which represents the location in the GL context where an object that is to be read/modified is stored. These binding points, like input attribute indices and output data locations can be bound in the shader when using GLSL 4.20 or the GL_ARB_shading_language_420pack extension. This is done by using the "binding" syntax:

layout(binding = 3) uniform sampler2D mainTexture;
layout(binding = 1, std140) uniform MainBlock
  vec3 data;

The first line is the equivalent of getting the uniform location for "mainTexture" and setting its uniform value to "3". Similarly, the second line is the equivalent of getting the "MainBlock" block location and setting its block index to "1". This only sets the initial value; source code can modify it later.

Image formats

Forced early fragment tests
Core in version 4.5
Core since version 4.2
Core ARB extension ARB_shader_image_load_store

Image uniform variables have qualifiers that define the format that all reading operations will convert the data into and all writing operations will convert the data from. They are grouped into 3 categories: floating-point, signed-integer, and unsigned-integer formats. These are the possible values:

  • Floating-point layout image formats:
    • rgba32f
    • rgba16f
    • rg32f
    • rg16f
    • r11f_g11f_b10f
    • r32f
    • r16f
    • rgba16
    • rgb10_a2
    • rgba8
    • rg16
    • rg8
    • r16
    • r8
    • rgba16_snorm
    • rgba8_snorm
    • rg16_snorm
    • rg8_snorm
    • r16_snorm
    • r8_snorm
  • Signed integer layout image formats:
    • rgba32i
    • rgba16i
    • rgba8i
    • rg32i
    • rg16i
    • rg8i
    • r32i
    • r16i
    • r8i
  • Unsigned integer layout image formats:
    • rgba32ui
    • rgba16ui
    • rgb10_a2ui
    • rgba8ui
    • rg32ui
    • rg16ui
    • rg8ui
    • r32ui
    • r16ui
    • r8ui

Atomic counter storage

Atomic Counters
Core in version 4.5
Core since version 4.2
Core ARB extension ARB_shader_atomic_counters

Atomic Counter variables have special layout settings that define where within a buffer object a particular variable comes from. These are required; there are no alternate methods to set these fields.

V · E

Atomic counter layout parameters

Interface block memory layout

Variables declared in interface blocks that get their storage from buffers (uniform blocks or shader storage blocks) have a number of layout qualifiers to define the packing and ordering of the variables defined in the block.

Explicit uniform location

Explicit Uniform Location
Core in version 4.5
Core since version 4.3
Core ARB extension ARB_explicit_uniform_location
V · E

Uniforms defined outside of Interface Blocks have a location. This location can be directly assigned in the shader, using this syntax:

layout(location = 2) uniform mat4 modelToWorldMatrix;

Calling glGetUniformLocation(prog, "modelToWorldMatrix") is guaranteed to return 2. It is illegal to assign the same uniform location to two uniforms in the same shader or the same program. Even if those two uniforms have the same name and type, and are defined in different shader stages, it is not legal to explicitly assign them the same uniform location; a linker error will occur.

All non-array/struct types will be assigned a single location. Arrays and structs will be assigned sequentially increasing locations, starting with the given location. Given this:

layout(location = 2) uniform mat4 some_mats[10];

some_mats​ will be assigned all of the uniform locations on the half-open range [2, 12). This will apply for nested types. Consider the following:

struct Thingy
  vec4 an_array[3];
  int foo;
layout(location = 2) uniform Thingy some_thingies[6];

Each Thingy​ takes up 4 uniform locations; the first three going to an_array​ and the fourth going to foo​. Thus, some_thingies​ takes up 24 uniform locations.

Uploading arrays of uniforms with one of the glUniform*v functions will work. For example, uniform location 2 represents the array `some_thingies[0].an_array`. As such, you can upload an array of vec4​s to this array with glUniform4fv(2, 3, ...);.

No two uniform declarations in a program can be explicitly assigned the same location. This means that explicit uniform location ranges cannot overlap. So this is illegal:

layout(location = 2) uniform mat4 some_mats[10];
layout(location = 6) uniform vec4 some_vecs[4];
Warning: This rule also means that two uniforms in different Shader stages that are linked together cannot share the same explicit uniform location. Even if their declarations are identical, it is a linker error to link two such shaders into the same program. So it is not possible for an explicitly-assigned uniform location to refer to a uniform in both the vertex and fragment shaders, for example.

The maximum number of available locations within a single program is GL_MAX_UNIFORM_LOCATIONS, which will be at least 1024 locations. You may not use a uniform location outside of the range [0, GL_MAX_UNIFORM_LOCATIONS), nor may the sequential assignment of uniform locations due to array/struct aggregation go outside of this range.

Shader stage options

Many shader stages have options that control how some aspect of how they function. These are defined within the shader using layout qualifiers.

Tessellation control output vertex count

Tessellation Control Shader
Core in version 4.5
Core since version 4.0
Core ARB extension ARB_tessellation_shader

Tessellation Control Shaders (TCS) output patches with a particular vertex count. This is defined by a layout qualifier:

layout(vertices = vertex_count​) out;

The TCS will be invoked once for each vertex output.

Tessellation evaluation options

The Tessellation Evaluation Shader (requires GL 4.0 or ARB_tessellation_shader) has a large number of special layout qualifiers that control its behavior.

Geometry shader primitives

Geometry Shaders take a particular primitive type as input and return a particular primitive type as outputs. Also, geometry shaders have a defined maximum number of vertices that they can output. These specifications cannot be used on a variable definition; it can only be used on the qualifiers in​ and out​ as a whole.

 layout(primitive type​) in;
 layout(primitive type​, max_vertices = integer value) out;

For inputs, the primitive type​ can be any of the following:

  • points
  • lines
  • lines_adjacency
  • triangles
  • triangles_adjacency

For outputs, the primitive type​ can be any of the following:

  • points
  • line_strip
  • triangle_strip

The value of max_vertices​ defines the maximum number of vertices the geometry shader can every output in a single invocation.

Fragment shader coordinate origin

The gl_FragCoord​ built-in variable represents the location of the fragment in window-space. There are two layout qualifiers that can affect this. These are specified by redeclaring the predefined variable.

The qualifier origin_upper_left​ specifies that gl_FragCoord​ will have the origin (0, 0) in the upper-left of the screen. The standard OpenGL convention is to have it in the lower-left. This does not change the Z or W of the gl_FragCoord​ value.

The qualifier pixel_center_integer​ specifies that the X and Y of gl_FragCoord​ will be shifted by a half-pixel, so that the center of each pixel is an integer value. The standard OpenGL convention puts the integer values at the corner of the pixel.

These are used as follows:

layout(origin_upper_left) in vec4 gl_FragCoord;

Early fragment tests

Forced early fragment tests
Core in version 4.5
Core since version 4.2
Core ARB extension ARB_shader_image_load_store

By the OpenGL specification, the depth and stencil tests are performed after the fragment shader's execution (implementations can and will do it before the fragment shader, but only if it won't affect the apparent output). However, with a fragment shader's ability to write to arbitrary images and buffers in OpenGL 4.2+, it is useful to be able to enforce early tests. This can be done in GL 4.2 (or with ARB_shader_image_load_store):

layout(early_fragment_tests) in;

Any writes to gl_FragDepth​ in a shader that defines this will be ignored.