Difference between revisions of "Type Qualifier (GLSL)"

From OpenGL.org
Jump to: navigation, search
(Interpolation qualifiers)
(Constant qualifier: Versions behave differently.)
 
(57 intermediate revisions by 4 users not shown)
Line 1: Line 1:
The [[OpenGL Shading Language]] defines a number of '''type qualifiers''', which are applied to global and locally defined variables. These qualifiers change particular aspects of the variable. They come in a number of different categories.
+
{{shader float}}
 +
 
 +
A '''type qualifier''' is used in the [[OpenGL Shading Language]] (GLSL) to modify the storage or behavior of global and locally defined variables. These qualifiers change particular aspects of the variable, such as where they get their data from and so forth. They come in a number of different categories.
  
 
== Storage qualifiers ==
 
== Storage qualifiers ==
 +
 +
Storage qualifiers define where a variable's storage comes from.
  
 
=== Default ===
 
=== Default ===
Line 7: Line 11:
 
If no storage qualifier is specified when declaring a global variable, then the variable is just a normal global variable. All global variables have a scope of the particular shader stage. So if you have two vertex shader objects that define {{code|int someValue;}}, when you link them into a program, they will both be referring to the same value.
 
If no storage qualifier is specified when declaring a global variable, then the variable is just a normal global variable. All global variables have a scope of the particular shader stage. So if you have two vertex shader objects that define {{code|int someValue;}}, when you link them into a program, they will both be referring to the same value.
  
If no storage qualifier is specified for a local variable, then the variable is a local variable that can be modified.
+
Each separate invocation of the same shader stage will refer to different versions of the same global variable. So invocations cannot communicate between each other through default-qualified global variables; that would require the [[#shared|shared qualifier]].
 +
 
 +
If no storage qualifier is specified for a local variable, then the variable is a local variable that can be modified. Local variables are scoped as with C/C++: the local scope in which they are declared.
  
 
=== Constant qualifier ===
 
=== Constant qualifier ===
  
Global or local variables can be declared with the {{code|const}} qualifier. This means that the variable's value cannot be changed after it is initialized. This also means that the variable declaration must initialize the variable.  
+
Global and local variables, as well as [[Function Parameter (GLSL)|input function parameters]], can be declared with the {{code|const}} qualifier. This means that the variable's value cannot be changed after it is initialized. This also means that the variable declaration must initialize the variable.
  
The initializer for a const variable must be a constant expression. Constant expressions are expressions that only contain:
+
GLSL versions before 4.20 required that {{code|const}} qualified variables (but not parameters) be initialized only with [[Constant Expression]]s. Therefore, {{code|const}} variables were always constant expressions. 4.20 permits such variables to be initialized with non-constant expressions, but the variable in that case will not be a constant expression.
 
+
* Literal values (3, 2.4, etc)
+
* A previously defined global or local variable that is qualified as const.
+
* A type constructor that is given only constant expressions as arguments.
+
* A operator whose arguments are constant expressions (5+4).
+
* A built-in function call whose arguments are all constant expressions. Notably exempt from this are the [[GLSL Sampler|texture functions]], because uniform variables are ''not'' compile-time constant. All of the texture functions take a sampler uniform as a parameter, and therefore they are not compile-time constants.
+
  
 
=== Shader stage inputs and outputs ===
 
=== Shader stage inputs and outputs ===
Line 25: Line 25:
 
Global variables declared with the {{code|in}} qualifier are shader stage input variables. These variables are given values by the previous stage (possibly via interpolation of values output from multiple shader executions). These variables are not constant (in the sense of {{code|const}}), but they cannot be changed by user code.
 
Global variables declared with the {{code|in}} qualifier are shader stage input variables. These variables are given values by the previous stage (possibly via interpolation of values output from multiple shader executions). These variables are not constant (in the sense of {{code|const}}), but they cannot be changed by user code.
  
Global variables declared with the {{code|out}} qualifier are shader stage output variables. These values are passed to the next stage of the pipeline (possibly via interpolation of values output from multiple shader executions). The shader must set all output variables at some point in its execution (unless the fragment shader executes the {{code|discard}} statement), except for those outputs that are not read by the next shader.
+
Global variables declared with the {{code|out}} qualifier are shader stage output variables. These values are passed to the next stage of the pipeline (possibly via interpolation of values output from multiple shader executions). The shader must set all output variables at some point in its execution; there are only two exceptions to this:
  
Neither qualifier can be used on local variables.
+
# The shader is a [[Fragment Shader]] which executes the {{code|discard}} statement.
 +
# The output variables which are not written are not read by the next shader stage.
  
These variables can be of any non-sampler basic type. They cannot be of struct types, but they can be arrays. There are usually very strict limits on the number of inputs and outputs available to a shader stage.
+
These qualifiers can not be used on local variables. And on [[Function Parameter]]s, they take on an entirely different meaning.
  
These variables are how the shader communicates to the earlier and later parts of the pipeline. Each variable name and type will match with an equivalent variable name and type on the next or previous shader stage. So, for each vertex shader output, the fragment shader will have a matching input with the same name and type. Using the same name with a different type is a linker error.
+
Variables qualified with these can be of any non-[[Opaque Type|opaque]] basic type (though some stages have more restrictive limitations on types. See below). They cannot be of struct types, but they can be [[GLSL Array|arrays]]. Input/output variables can be aggregated into [[Interface Block (GLSL)|interface blocks]]. There are usually very strict limits on the number of user-defined input and output values available to each shader stage.
  
Also, it is allowed to have output variables that are not read by the next stage. It is not allowed to have input variables not written by the previous stage.
+
The input and output-qualified variables define an interface between this shader and the previous/next part of the pipeline. The interfaces between two shader stages [[Interface Matching|must match, though not necessarily exactly]].
  
 
There are some special cases with input and output variables for different stages.
 
There are some special cases with input and output variables for different stages.
  
 
==== Vertex shader inputs ====
 
==== Vertex shader inputs ====
 +
{{main|Vertex Shader#Inputs}}
  
Inputs for vertex shaders are attributes. They are passed from [[Vertex Specification|vertex arrays]] to the vertex shader.
+
User-defined inputs for vertex shaders are called vertex attributes. They are passed via [[Vertex Specification|vertex arrays]] to the vertex shader, usually from data stored in [[Buffer Object]]s.
  
Array inputs can be defined. Each array value takes up one attribute index, sequentially from the first. So this input: {{code|in float values[5]}} will take up 5 attributes.
+
Vertex shader inputs have attribute location indices that are used in vertex specification to identify a particular input. Most inputs take up only one attribute location index, but certain types (matrices, array inputs, and some double-precision types) can take up more than one index.
  
Matrix inputs take up one attribute index for each row.
+
==== Tessellation control shader outputs ====
 +
{{main|Tessellation Control Shader#Outputs}}
  
In OpenGL 4.0, double-precision variables take up more attribute indices. {{code|double}} and {{code|dvec2}} take up one attribute index, while {{code|dvec3}} and {{code|dvec4}} require two, in sequential indices.
+
Tessellation Control Shader outputs can be either per-vertex or per-patch. Per-vertex outputs are aggregated into arrays, where the length of the arrays is the number of output vertices in the patch. Per-patch outputs (declared with the {{code|patch}} keyword) are not arrays (you can declare arrays of them, but they won't be indexed per-vertex).
 +
 
 +
TCS's can read from any per-vertex or per-patch output, so each TCS invocation can read data written by other TCS invocations (assuming you [[TCS Synchronization|take steps to ensure that the other invocations have written to them]]). But each TCS invocation can only write to per-vertex outputs that are for their particular vertex. This means that the only expression in the subscript that can be when writing to a per-vertex output is {{code|gl_InvocationID}}.
 +
 
 +
==== Tessellation evaluation shader inputs ====
 +
{{main|Tessellation Evaluation Shader#Inputs}}
 +
 
 +
Tessellation Evaluation Shader inputs are like TCS outputs: either per-vertex or per-patch (declared with the {{code|patch}} keyword. Any TES invocation can read any per-vertex or per-patch input.
  
 
==== Geometry shader inputs ====
 
==== Geometry shader inputs ====
 +
{{main|Geometry Shader#Inputs}}
 +
 +
Geometry Shader inputs are aggregated into arrays, one per vertex in the primitive. The length of the array depends on the [[Geometry Shader Primitive Specification|input primitive type]] used by the GS. Each array index represents a single vertex in the input primitive.
  
 
==== Fragment shader outputs ====
 
==== Fragment shader outputs ====
 +
{{main|Fragment Shader#Outputs}}
  
Fragment shader outputs cannot be matrices or booleans; they must be floating-point or integer vectors or scalars.
+
Fragment shader outputs cannot be matrices or boolean types. They must be vectors or scalars of single-precision floating-point or integer types. They may also be arrays of these types. Like vertex shader inputs, fragment shader outputs are assigned indices, either explicitly by the user or implicitly by the system.
  
Each fragment shader output corresponds to a draw buffer, set with the {{apifunc|glDrawBuffers}} command. The association between output values and draw buffers is made with {{apifunc|glBindFragDataLocation}} or with explicit binding via {{code|layout(location {{=}} #)}} in the shader before linking the program. Any unassigned outputs will be assigned values by the linker arbitrarily.
+
Each fragment shader output's index corresponds to a draw buffer, as defined by the [[Framebuffer Draw Buffer|current draw framebuffer's draw-buffer setting]], set with the {{apifunc|glDrawBuffers}} command. The indices in the array passed to this function correspond to an output variable's assigned index. The value in the array at that index refers to a specific image in the current drawing framebuffer.
 +
 
 +
Output variables from the fragment shader do not have to be written. However, unwritten outputs will have undefined values. This is OK if the current [[Framebuffer Draw Buffer]] setting would discard that value (by using {{enum|GL_NONE}}).
  
 
==== Interpolation qualifiers ====
 
==== Interpolation qualifiers ====
  
Fragment shader inputs can have interpolation qualifiers. Interpolation qualifiers can also be used on the outputs from the final shader stage before the rasterizer. This traditionally has been the vertex shader, but it could be the geometry shader or the tessellation evaluation shader.
+
Certain inputs and outputs can use interpolation qualifiers. These are for any values which could be interpolated as a result of rasterization. These include:
 +
 
 +
* Vertex shader outputs
 +
* Tessellation control shader inputs (to match with outputs from the VS)
 +
* Tessellation evaluation shader outputs
 +
* Geometry shader inputs (to match with outputs from the TES/VS) and outputs
 +
* Fragment shader inputs
  
The interpolation qualifiers for corresponding values must match; failure to do so is a linker error.
+
Interpolation qualifiers control how interpolation of values happens across a triangle or other primitive. There are three basic interpolation qualifiers.
  
Interpolation qualifiers control how interpolation happens across a triangle or other primitive. There are three basic interpolation qualifiers.
+
; {{code|flat}}
 +
: The value will not be interpolated. The value given to the fragment shader is the value from the [[Provoking Vertex]] for that primitive.
 +
; {{code|noperspective}}
 +
: The value will be linearly interpolated in window-space. This is usually not what you want, but it can have its uses.
 +
; {{code|smooth}}
 +
: The value will be interpolated in a perspective-correct fashion. This is the default if no qualifier is present.
  
{{code|flat}} means that there is no interpolation. The value given to the fragment shader is based on the [[Provoking Vertex]] conventions.
+
The {{code|centroid}} and {{code|sample}} (the latter requires {{require|4.0|gpu_shader5}}) qualifiers affect interpolation, but they are somewhat special, grammatically speaking. Before {{require|4.2||shading_language_420pack}}, these were considered part of the {{code|in/out}} storage qualifier. So their use must always be together: {{code|centroid in}} or {{code|sample out}}; no qualifiers can come between them. In 4.2 and above, they are considered axillary qualifiers, so they can be separated from the {{code|in/out}} storage qualifier.
  
{{code|noperspective}} means that there will be linear interpolation in window-space. This is usually not what you want, but it can have its uses.
+
They may not technically be interpolation qualifiers, but they do control aspects of interpolation. They only have an effect when [[Multisampling]] is being used.
  
{{code|smooth}}, the default, means to do perspective-correct interpolation.
+
During multisampling, if {{code|centroid}} is not present, then the written value can be interpolated to to an arbitrary position within the pixel. This may be the pixel's center, one of the sample locations within the pixel, or an arbitrary location. Most importantly of all, this sample may lie ''outside'' of the actual primitive being rendered, since a primitive can cover only part of a pixel's area. If the implementation computes the sample based on the center of the pixel, and the primitive doesn't actually cover the pixel's center (remember: in multisampling, this can still produce a non-zero number of samples), then the interpolated value will be outside of the primitive's borders.
  
The {{code|centroid}} qualifier only matters when multisampling. If this qualifier is not present, then the value is interpolated to the pixel's center, anywhere in the pixel, or to one of the pixel's samples. This sample may lie ''outside'' of the actual primitive being rendered, since a primitive can cover only part of a pixel's area. The <code>centroid</code> qualifier is used to prevent this; the interpolation point must fall within both the pixel's area and the primitive's area.
+
The {{code|centroid}} qualifier is used to prevent this; the interpolation point must fall within both the pixel's area and the primitive's area. This is useful for parameters or computations that would have undefined values if they fell outside of the primitive's area. A square root is only defined for positive numbers, so if you are taking the square root of an interpolated value, you may need to use {{code|centroid}} interpolation.
  
This is useful for parameters or computations that would have undefined values if they fell outside of the primitive's area. A square root is only defined for positive numbers, so if you are taking the square root of an interpolated value, you may need to use <code>centroid</code> interpolation.
+
You should only use {{code|centroid}} if there is a real problem like this. In many cases interpolating without centroid doesn't pose a problem.
 +
 
 +
The {{code|sample}} qualifier forces OpenGL to interpolate this qualifier to the location of the particular sample for each generated fragment. This is only really useful with per-sample shading.
  
 
=== Uniforms ===
 
=== Uniforms ===
 
{{main|GLSL Uniform}}
 
{{main|GLSL Uniform}}
  
Global variables and [[Interface Block]]s can be declared with the <code>uniform</code> qualifier. This means that the value does not change between multiple executions of a shader during the rendering of a primitive (ie: during a glDraw* call). These values are set by the user from the OpenGL API.
+
Global variables and [[Interface Block]]s can be declared with the {{code|uniform}} qualifier. This means that the value does not change between multiple executions of a shader during the rendering of a primitive (ie: during a glDraw* call). These values are set by the user from the OpenGL API.
 +
 
 +
They are constant, but not ''compile-time'' constant (so not {{code|const}}).
  
 
=== Buffer ===
 
=== Buffer ===
 
{{main|Shader Storage Buffer Object}}
 
{{main|Shader Storage Buffer Object}}
  
In OpenGL 4.3 (or with the ARB_shader_storage_buffer_object extension), [[GLSL Interface Block|interface blocks]] can be qualified with the {{code|buffer}} qualifier. This means that the storage for the block comes from a buffer object, similarly to [[Uniform Buffer Object]]s and uniform blocks. Unlike UBOs, storage blocks can be written to. They can also have an unbounded size.
+
In {{require|4.3|shader_storage_buffer_object}}, individual global variables (as well as [[Interface Block (GLSL)|interface blocks]]) can be qualified with the {{code|buffer}} qualifier. This means that the storage for the variable/block comes from a buffer object, similarly to [[Uniform Buffer Object]]s and uniform blocks. Unlike UBOs, storage blocks can be written to. They can also have an array with an unbounded size, who's size is determined by the size of the SSBO bound at render time.
  
 
=== Interface blocks ===
 
=== Interface blocks ===
 
{{main|GLSL Interface Blocks}}
 
{{main|GLSL Interface Blocks}}
  
Inputs, outputs, uniforms, and storage buffer variables for various stages can grouped into interface blocks.
+
Inputs, outputs, uniforms, and buffer variables for various stages can grouped into interface blocks.
  
 +
=== Shared ===
 +
{{main|Compute Shader#Shared variables}}
 +
 +
Variables declared with the {{code|shared}} qualifier are shared among several shader invocations. Such variables can only be used in [[Compute Shader]]s. Shared variables are shared among all invocations in a work group.
  
 
== Layout qualifiers ==
 
== Layout qualifiers ==
 +
{{main|Layout Qualifier (GLSL)}}
  
Uniforms, buffer, inputs, and outputs can also have layout qualifiers. Different stages have their own layout qualifiers, and the different types can have their own as well.
+
There are a large number of layout qualifiers which can be applied to a variety of defined constructs, from [[Interface Block (GLSL)|interface blocks]] to shader stage inputs and outputs. These affect the storage location of their data and many other properties about where the variable's data comes from or other user-facing interfaces about the data.
  
All layout qualifiers are defined with a common syntax:
+
== Precision qualifiers ==
  
layout({{param|qualifier1}}, {{param|qualifier2}} = ''value'', ...) ''variable definition''
+
{{note|Precision qualifiers in GLSL are supported for compatibility with [[OpenGL ES]] 2.0. They use the same syntax as ES 2.0's qualifiers, but they have no functional effects. Do not use them unless you want your shaders to be ES 2.0 compatible.}}
  
 +
There are three precision qualifiers: {{code|highp}}, {{code|mediump}}, and {{code|lowp}}. They have no semantic meaning or functional effect. They can apply to any floating-point type (vector or matrix), or any integer type.
  
The {{param|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 {{param|qualifier2}} in the above example. These values must be literals.
+
=== Precision statements ===
  
Some layout qualifiers can apply to all inputs or outputs. In which case, the ''variable definition'' can just be {{code|in}} or {{code|out}}.
+
All variables of a certain type can be declared to have a precision by using the {{code|precision}} statement. It's syntax is as follows:
  
=== Vertex shader attribute index ===
+
precision {{param|precision-qualifier}} {{param|type}};
  
Vertex shader inputs can specify the attribute index that the particular input uses. This is done with this syntax:
+
In this case, {{param|type}} can only be {{code|float}} or {{code|int}}. This will affect all collections of that basic type. So {{code|float}} will affect all floating-point scalars, vectors, and matrices. The {{code|int}} type will affect all signed and unsigned integer scalars and vectors.
  
layout(location = ''attribute index'') in vec3 position;
+
== Memory qualifiers ==
 +
{{infobox feature
 +
| name = Image Load/Store
 +
| core = 4.2
 +
| core_extension = {{extref|shader_image_load_store}}
 +
}}
  
With this syntax, you can forgo the use of {{apifunc|glBindAttribLocation}} entirely. If you try to combine the two and they conflict, the layout qualifier always wins.
+
{{code|image}} variables, {{code|buffer}} variables, and shader storage blocks (and their contents) can have a number of memory qualifiers applied to them. These affect how they can be used and how values read from/written to them will be seen in other shader invocations. Multiple qualifiers can be used on the same variable.
  
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:
+
{{memory qualifiers}}
  
<source lang="cpp">
+
These qualifiers can be used on parameters of image types. If you pass an image to a function, the function parameter's qualifier list much match that of the image declaration. The parameter could have ''more'' qualifiers, but it cannot have fewer.
layout(location = 2) in vec3 values[4];
+
</source>
+
  
This will allocate the attribute indices 2, 3, 4, and 5.
+
== Invariance qualifiers ==
 +
{{main|Invariance#Shader}}
  
=== Geometry shader primitives ===
+
There is a way to qualify certain output variables as being invariant. This allows different programs to compute the exact same answer, assuming certain conditions are met.
  
[[Geometry Shader]]s 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 {{code|in}} and {{code|out}} as a whole.
+
The {{code|invariant}} qualifier can be applied to an existing declaration, as in this case:
  
  layout({{param|primitive type}}) in;
+
<source lang="glsl">
  layout({{param|primitive type}}, max_vertices = ''integer value'') out;
+
invariant gl_Position; //Not redeclared; just uses invariant.
 
+
out vec3 Color;
For inputs, the {{param|primitive type}} can be any of the following:
+
invariant Color; //Again makes existing declaration invariant.
 
+
* points
+
* lines
+
* lines_adjacency
+
* triangles
+
* triangles_adjacency
+
 
+
For outputs, the {{param|primitive type}} can be any of the following:
+
 
+
* points
+
* line_strip
+
* triangle_strip
+
 
+
The value of {{param|max_vertices}} defines the maximum number of vertices the geometry shader can every output in a single invocation.
+
 
+
=== Fragment shader coordinate origin ===
+
 
+
The {{code|gl_FragCoord}} [[GLSL Predefined Variables|predefined variable]] represents the location of the fragment in window-space. There are two layout qualifiers that can affect this. These are specified by [[GLSL_Type_Qualifiers#Built-in_redeclaration|redeclaring]] the predefined variable.
+
 
+
The qualifier {{code|origin_upper_left}} specifies that {{code|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 {{code|gl_FragCoord}} value.
+
 
+
The qualifier {{code|pixel_center_integer}} specifies that the X and Y of {{code|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:
+
 
+
<source lang="cpp">
+
layout(origin_upper_left) in vec4 gl_FragCoord;
+
 
</source>
 
</source>
  
=== Early fragment tests ===
+
Or you can use it at the declaration site.
 
+
By the OpenGL specification, the depth and stencil tests are performed after the fragment shader's execution ([[Early Depth Test|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):
+
  
 
<source lang="glsl">
 
<source lang="glsl">
layout(early_fragment_tests) in;
+
invariant out vec3 Color;
 
</source>
 
</source>
  
Any writes to {{code|gl_FragDepth}} in a shader that defines this will be ''ignored''.
+
Only input and output variables can be declared {{code|invariant}}. However, for input variables, it has no meaning; it is only allowed for symmetry. Note that the {{code|variant}} qualifier ''does not'' participate in interface matching, so you do not have to use it at all on input variables from stages that declared that output as {{code|invariant}}.
  
=== Fragment shader buffer output ===
+
== Precise qualifiers ==
 
+
{{todo}}
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 {{apifunc|glBindFragDataLocation}}. Similarly, the values in the shader override the values provided by this function.
+
 
+
For [[Blending#Dual_Source_Blending|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 {{apifunc|glBindFragDataLocationIndexed}}.
+
 
+
=== Program separation linkage ===
+
 
+
When using OpenGL 4.1 or an implementation that provides support for ARB_separate_shader_objects, all input and output variables can have layout {{code|location}} qualifiers. The meaning is unchanged for vertex shader inputs and fragment shader outputs. But for communication between shader stages, the meaning is changed.
+
 
+
Normally, when linking shaders into a program, the output variables from one stage are matched with the input variables from another stage. However, when linking '''programs''' together dynamically in a program pipeline object, an alternative method of linking is allowed. The name linking is allowed, but so is linking by location.
+
 
+
For example, given a vertex shader that provides these outputs:
+
 
+
<source lang="cpp">
+
layout(location = 0) out vec4 color;
+
layout(location = 1) out vec2 texCoord;
+
layout(location = 2) out vec3 normal;
+
</source>
+
 
+
Normally, the fragment shader would have to use exactly those names. This is not required when using separate programs. If an output has a location specified, the next stage can provide that location with a different name. So a matching fragment shader could look like this:
+
 
+
<source lang="cpp">
+
layout(location = 0) in vec4 diffuseAlbedo;
+
layout(location = 1) in vec2 texCoord
+
layout(location = 2) in vec3 cameraSpaceNormal;
+
</source>
+
 
+
{{note|'''This only works when connecting programs with a program pipeline object'''. This does not change how linking ''within'' a program object works. It only works when using separate programs and with implicit linking between separate programs. NVIDIA's implementation ignores the specification here to provide the behavior you might expect, while ATI's implementation sticks to the specification. Do not use layout locations on interface variables unless you are separating programs.}}}
+
 
+
=== Interface block memory layout ===
+
{{main|GLSL_Interface_Block#Memory_layout}}
+
 
+
Variables declared in interface blocks that get their storage from buffers ([[Uniform Buffer Object|uniform blocks]] or [[Shader Storage Buffer Object|shader storage blocks]]) have a number of layout qualifiers to define the packing and ordering of the variables defined in the block.
+
 
+
=== Binding points ===
+
 
+
Samplers, uniform bloc, shader storage blocks, and image 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:
+
 
+
<source lang="cpp">
+
layout(binding = 3) uniform sampler2D mainTexture;
+
layout(binding = 1, std140) uniform MainBlock
+
{
+
  vec3 data;
+
};
+
</source>
+
 
+
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.
+
 
+
== Precision qualifiers ==
+
 
+
{{note|Precision qualifiers in GLSL are supported for compatibility with [[OpenGL ES]] 2.0. They use the same syntax as ES 2.0's qualifiers, but they have no functional effects. Do not use them unless you want your shaders to be ES 2.0 compatible.}}
+
 
+
There are three precision qualifiers: {{code|highp}}, {{code|mediump}}, and {{code|lowp}}. They have no semantic meaning or functional effect. They can apply to any floating-point type (vector or matrix), or any integer type.
+
 
+
== Precision statements ==
+
 
+
All variables of a certain type can be declared to have a precision by using the <code>precision</code> statement. It's syntax is as follows:
+
 
+
<code>
+
precision ''precision-qualifier'' ''type'';
+
</code>
+
 
+
In this case, ''type'' can only be {{code|float}} or {{code|int}}. This will affect all collections of that basic type. So {{code|float}} will affect all floating-point scalars, vectors, and matrices. The {{code|int}} type will affect all signed and unsigned integer scalars and vectors.
+
 
+
== Invariance qualifiers ==
+
{{main|Invariance}}
+
 
+
There is a way to qualify certain output variables as being invariant. This allows different programs to compute the exact same answer, assuming certain conditions are met.
+
 
+
The {{code|invariant}} qualifier must be the first qualifier in a definition. The {{code|gl_Position}} predefined variable can be redeclared to be invariant with this:
+
 
+
<code>
+
invariant gl_Position;
+
</code>
+
  
 
== Qualifier order ==
 
== Qualifier order ==
  
Qualifiers always come in a particular order. For non-parameter values, the order is always this:
+
Unless you are in {{require|4.2|shading_language_420pack}}, qualifiers always come in a particular order. For non-parameter values, the order is always this:
  
<code>
+
''invariant-qualifier'' ''interpolation-qualifier'' ''layout-qualifier'' ''other-storage-qualifier'' ''precision-qualifier''
''invariant-qualifier'' ''interpolation-qualifier'' ''layout-qualifier'' ''other-storage-qualifier'' ''precision-qualifier''
+
</code>
+
  
 
The {{code|centroid}} qualifier, if present, must immediately precede {{code|in}} or {{code|out}}. For the purpose of ordering, it is considered part of the {{code|in}} or {{code|out}} storage qualifier, not part of the interpolation qualifier.
 
The {{code|centroid}} qualifier, if present, must immediately precede {{code|in}} or {{code|out}}. For the purpose of ordering, it is considered part of the {{code|in}} or {{code|out}} storage qualifier, not part of the interpolation qualifier.
 +
 +
{{require|4.2|shading_language_420pack}} removes the ordering restriction in most cases. {{code|centroid}} still has to immediate precede {{code|in}} or {{code|out}}. It also allows multiple layout qualifiers, but you can still only use one qualifier from most other groups (there can be multiple memory qualifiers). Also, all qualifiers must still come before the [[Data Type (GLSL)|type specifier]]. The groups of qualifiers match the main headings above: storage, layout, precision, etc.
  
 
== Built-in redeclaration ==
 
== Built-in redeclaration ==
  
The GLSL defines a number of [[GLSL_Predefined_Variables|predefined variables]] at the various shader stages. These variables are defined with a particular set of qualifiers, as stated in the above article. If you wish to use them with a different qualifier, you can redeclare them. You must use the same type, however. And some variables cannot be redeclared with a new qualifier; gl_Position in the vertex shader for example cannot use an interpolation qualifier at all.
+
The GLSL defines a number of [[GLSL_Predefined_Variables|predefined variables]] at the various shader stages. These pre-defined variables are defined with a particular set of qualifiers, as stated in the above article. If you wish to use pre-defined variables with a different qualifier, you can re-declare the variable, but the re-declaration must use the same type. Some variables cannot be redeclared with a new qualifier. For example: gl_Position in the vertex shader cannot use an interpolation qualifier at all.
  
 
== Removed qualifiers ==
 
== Removed qualifiers ==

Latest revision as of 12:39, 16 July 2015

A type qualifier is used in the OpenGL Shading Language (GLSL) to modify the storage or behavior of global and locally defined variables. These qualifiers change particular aspects of the variable, such as where they get their data from and so forth. They come in a number of different categories.

Storage qualifiers

Storage qualifiers define where a variable's storage comes from.

Default

If no storage qualifier is specified when declaring a global variable, then the variable is just a normal global variable. All global variables have a scope of the particular shader stage. So if you have two vertex shader objects that define int someValue;​, when you link them into a program, they will both be referring to the same value.

Each separate invocation of the same shader stage will refer to different versions of the same global variable. So invocations cannot communicate between each other through default-qualified global variables; that would require the shared qualifier.

If no storage qualifier is specified for a local variable, then the variable is a local variable that can be modified. Local variables are scoped as with C/C++: the local scope in which they are declared.

Constant qualifier

Global and local variables, as well as input function parameters, can be declared with the const​ qualifier. This means that the variable's value cannot be changed after it is initialized. This also means that the variable declaration must initialize the variable.

GLSL versions before 4.20 required that const​ qualified variables (but not parameters) be initialized only with Constant Expressions. Therefore, const​ variables were always constant expressions. 4.20 permits such variables to be initialized with non-constant expressions, but the variable in that case will not be a constant expression.

Shader stage inputs and outputs

Global variables declared with the in​ qualifier are shader stage input variables. These variables are given values by the previous stage (possibly via interpolation of values output from multiple shader executions). These variables are not constant (in the sense of const​), but they cannot be changed by user code.

Global variables declared with the out​ qualifier are shader stage output variables. These values are passed to the next stage of the pipeline (possibly via interpolation of values output from multiple shader executions). The shader must set all output variables at some point in its execution; there are only two exceptions to this:

  1. The shader is a Fragment Shader which executes the discard​ statement.
  2. The output variables which are not written are not read by the next shader stage.

These qualifiers can not be used on local variables. And on Function Parameters, they take on an entirely different meaning.

Variables qualified with these can be of any non-opaque basic type (though some stages have more restrictive limitations on types. See below). They cannot be of struct types, but they can be arrays. Input/output variables can be aggregated into interface blocks. There are usually very strict limits on the number of user-defined input and output values available to each shader stage.

The input and output-qualified variables define an interface between this shader and the previous/next part of the pipeline. The interfaces between two shader stages must match, though not necessarily exactly.

There are some special cases with input and output variables for different stages.

Vertex shader inputs

User-defined inputs for vertex shaders are called vertex attributes. They are passed via vertex arrays to the vertex shader, usually from data stored in Buffer Objects.

Vertex shader inputs have attribute location indices that are used in vertex specification to identify a particular input. Most inputs take up only one attribute location index, but certain types (matrices, array inputs, and some double-precision types) can take up more than one index.

Tessellation control shader outputs

Tessellation Control Shader outputs can be either per-vertex or per-patch. Per-vertex outputs are aggregated into arrays, where the length of the arrays is the number of output vertices in the patch. Per-patch outputs (declared with the patch​ keyword) are not arrays (you can declare arrays of them, but they won't be indexed per-vertex).

TCS's can read from any per-vertex or per-patch output, so each TCS invocation can read data written by other TCS invocations (assuming you take steps to ensure that the other invocations have written to them). But each TCS invocation can only write to per-vertex outputs that are for their particular vertex. This means that the only expression in the subscript that can be when writing to a per-vertex output is gl_InvocationID​.

Tessellation evaluation shader inputs

Tessellation Evaluation Shader inputs are like TCS outputs: either per-vertex or per-patch (declared with the patch​ keyword. Any TES invocation can read any per-vertex or per-patch input.

Geometry shader inputs

Geometry Shader inputs are aggregated into arrays, one per vertex in the primitive. The length of the array depends on the input primitive type used by the GS. Each array index represents a single vertex in the input primitive.

Fragment shader outputs

Fragment shader outputs cannot be matrices or boolean types. They must be vectors or scalars of single-precision floating-point or integer types. They may also be arrays of these types. Like vertex shader inputs, fragment shader outputs are assigned indices, either explicitly by the user or implicitly by the system.

Each fragment shader output's index corresponds to a draw buffer, as defined by the current draw framebuffer's draw-buffer setting, set with the glDrawBuffers command. The indices in the array passed to this function correspond to an output variable's assigned index. The value in the array at that index refers to a specific image in the current drawing framebuffer.

Output variables from the fragment shader do not have to be written. However, unwritten outputs will have undefined values. This is OK if the current Framebuffer Draw Buffer setting would discard that value (by using GL_NONE).

Interpolation qualifiers

Certain inputs and outputs can use interpolation qualifiers. These are for any values which could be interpolated as a result of rasterization. These include:

  • Vertex shader outputs
  • Tessellation control shader inputs (to match with outputs from the VS)
  • Tessellation evaluation shader outputs
  • Geometry shader inputs (to match with outputs from the TES/VS) and outputs
  • Fragment shader inputs

Interpolation qualifiers control how interpolation of values happens across a triangle or other primitive. There are three basic interpolation qualifiers.

flat​
The value will not be interpolated. The value given to the fragment shader is the value from the Provoking Vertex for that primitive.
noperspective​
The value will be linearly interpolated in window-space. This is usually not what you want, but it can have its uses.
smooth​
The value will be interpolated in a perspective-correct fashion. This is the default if no qualifier is present.

The centroid​ and sample​ (the latter requires OpenGL 4.0 or ARB_gpu_shader5) qualifiers affect interpolation, but they are somewhat special, grammatically speaking. Before OpenGL 4.2, these were considered part of the in/out​ storage qualifier. So their use must always be together: centroid in​ or sample out​; no qualifiers can come between them. In 4.2 and above, they are considered axillary qualifiers, so they can be separated from the in/out​ storage qualifier.

They may not technically be interpolation qualifiers, but they do control aspects of interpolation. They only have an effect when Multisampling is being used.

During multisampling, if centroid​ is not present, then the written value can be interpolated to to an arbitrary position within the pixel. This may be the pixel's center, one of the sample locations within the pixel, or an arbitrary location. Most importantly of all, this sample may lie outside of the actual primitive being rendered, since a primitive can cover only part of a pixel's area. If the implementation computes the sample based on the center of the pixel, and the primitive doesn't actually cover the pixel's center (remember: in multisampling, this can still produce a non-zero number of samples), then the interpolated value will be outside of the primitive's borders.

The centroid​ qualifier is used to prevent this; the interpolation point must fall within both the pixel's area and the primitive's area. This is useful for parameters or computations that would have undefined values if they fell outside of the primitive's area. A square root is only defined for positive numbers, so if you are taking the square root of an interpolated value, you may need to use centroid​ interpolation.

You should only use centroid​ if there is a real problem like this. In many cases interpolating without centroid doesn't pose a problem.

The sample​ qualifier forces OpenGL to interpolate this qualifier to the location of the particular sample for each generated fragment. This is only really useful with per-sample shading.

Uniforms

Global variables and Interface Blocks can be declared with the uniform​ qualifier. This means that the value does not change between multiple executions of a shader during the rendering of a primitive (ie: during a glDraw* call). These values are set by the user from the OpenGL API.

They are constant, but not compile-time constant (so not const​).

Buffer

In OpenGL 4.3 or ARB_shader_storage_buffer_object, individual global variables (as well as interface blocks) can be qualified with the buffer​ qualifier. This means that the storage for the variable/block comes from a buffer object, similarly to Uniform Buffer Objects and uniform blocks. Unlike UBOs, storage blocks can be written to. They can also have an array with an unbounded size, who's size is determined by the size of the SSBO bound at render time.

Interface blocks

Inputs, outputs, uniforms, and buffer variables for various stages can grouped into interface blocks.

Shared

Variables declared with the shared​ qualifier are shared among several shader invocations. Such variables can only be used in Compute Shaders. Shared variables are shared among all invocations in a work group.

Layout qualifiers

There are a large number of layout qualifiers which can be applied to a variety of defined constructs, from interface blocks to shader stage inputs and outputs. These affect the storage location of their data and many other properties about where the variable's data comes from or other user-facing interfaces about the data.

Precision qualifiers

Note: Precision qualifiers in GLSL are supported for compatibility with OpenGL ES 2.0. They use the same syntax as ES 2.0's qualifiers, but they have no functional effects. Do not use them unless you want your shaders to be ES 2.0 compatible.

There are three precision qualifiers: highp​, mediump​, and lowp​. They have no semantic meaning or functional effect. They can apply to any floating-point type (vector or matrix), or any integer type.

Precision statements

All variables of a certain type can be declared to have a precision by using the precision​ statement. It's syntax is as follows:

precision precision-qualifier​ type​;

In this case, type​ can only be float​ or int​. This will affect all collections of that basic type. So float​ will affect all floating-point scalars, vectors, and matrices. The int​ type will affect all signed and unsigned integer scalars and vectors.

Memory qualifiers

Image Load/Store
Core in version 4.5
Core since version 4.2
Core ARB extension ARB_shader_image_load_store

image​ variables, buffer​ variables, and shader storage blocks (and their contents) can have a number of memory qualifiers applied to them. These affect how they can be used and how values read from/written to them will be seen in other shader invocations. Multiple qualifiers can be used on the same variable.

coherent​
Normally, the compiler is free to assume that this shader invocation is the only invocation that modifies values read through this variable. It also can freely assume that other shader invocations may not see values written through this variable.
Using this qualifier is required to allow dependent shader invocations to communicate with one another, as it enforces the coherency of memory accesses. Using this requires the appropriate memory barriers to be executed, so that visibility can be achieved.
When communicating between shader invocations for different rendering commands, glMemoryBarrier should be used instead of this qualifier.
volatile​
The compiler normally is free to assume that values accessed through variables will only change after memory barriers or other synchronization. With this qualifier, the compiler assumes that the contents of the storage represented by the variable could be changed at any time.
restrict​
Normally, the compiler must assume that you could access the same image/buffer object separate variables in the same shader. Therefore, if you write to one variable, and read from a second, the compiler assumes that it is possible that you could be reading the value you just wrote. With this qualifier, you are telling the compiler that this particular variable is the only variable that can modify the memory visible through that variable within this shader invocation (other shader stages don't count here). This allows the compiler to optimize reads/writes better.
You should use this wherever possible.
readonly​
Normally, the compiler allows you to read and write from variables as you wish. If you use this, the variable can only be used for reading operations.
writeonly​
Normally, the compiler allows you to read and write from variables as you wish. If you use this, the variable can only be used for writing operations (atomic writes are forbidden because they also count as reads).

These qualifiers can be used on parameters of image types. If you pass an image to a function, the function parameter's qualifier list much match that of the image declaration. The parameter could have more qualifiers, but it cannot have fewer.

Invariance qualifiers

There is a way to qualify certain output variables as being invariant. This allows different programs to compute the exact same answer, assuming certain conditions are met.

The invariant​ qualifier can be applied to an existing declaration, as in this case:

invariant gl_Position; //Not redeclared; just uses invariant.
out vec3 Color;
invariant Color; //Again makes existing declaration invariant.

Or you can use it at the declaration site.

invariant out vec3 Color;

Only input and output variables can be declared invariant​. However, for input variables, it has no meaning; it is only allowed for symmetry. Note that the variant​ qualifier does not participate in interface matching, so you do not have to use it at all on input variables from stages that declared that output as invariant​.

Precise qualifiers

Qualifier order

Unless you are in OpenGL 4.2 or ARB_shading_language_420pack, qualifiers always come in a particular order. For non-parameter values, the order is always this:

invariant-qualifier interpolation-qualifier layout-qualifier other-storage-qualifier precision-qualifier

The centroid​ qualifier, if present, must immediately precede in​ or out​. For the purpose of ordering, it is considered part of the in​ or out​ storage qualifier, not part of the interpolation qualifier.

OpenGL 4.2 or ARB_shading_language_420pack removes the ordering restriction in most cases. centroid​ still has to immediate precede in​ or out​. It also allows multiple layout qualifiers, but you can still only use one qualifier from most other groups (there can be multiple memory qualifiers). Also, all qualifiers must still come before the type specifier. The groups of qualifiers match the main headings above: storage, layout, precision, etc.

Built-in redeclaration

The GLSL defines a number of predefined variables at the various shader stages. These pre-defined variables are defined with a particular set of qualifiers, as stated in the above article. If you wish to use pre-defined variables with a different qualifier, you can re-declare the variable, but the re-declaration must use the same type. Some variables cannot be redeclared with a new qualifier. For example: gl_Position in the vertex shader cannot use an interpolation qualifier at all.

Removed qualifiers

The following qualifiers are deprecated as of GLSL 1.30 (OpenGL 3.0) and removed from GLSL 1.40 and above.

The attribute​ qualifier is effectively equivalent to an input qualifier in vertex shaders. It cannot be used in any other shader stage. It cannot be used in interface blocks.

The varying​ qualifier is equivalent to the input of a fragment shader or the output of a vertex shader. It cannot be used in any other shader stages. It cannot be used in interface blocks.