Core Language (GLSL)

From OpenGL Wiki
(Redirected from GLSL Core Language)
Jump to: navigation, search


Compilation settings




The OpenGL Shading Language has gone through a number of revisions, some of them quite substantial. As part of the OpenGL Specification, each version of OpenGL is required to support specific versions of GLSL; it may optionally support more.


  #version 150


The version number can be followed by the profile name. This can be core or compatibility. If a profile name is not specified, the default is core.

The #version directive must appear before anything else in a shader, save for whitespace and comments. If a #version directive does not appear at the top, then it assumes 1.10, which is almost certainly not what you want.

OpenGL and GLSL versions


OpenGL Version GLSL Version
2.0 1.10
2.1 1.20
3.0 1.30
3.1 1.40
3.2 1.50





 #extension extension_name​ : behavior​

The extension_name​ can also be the string all. This means it works for all extensions. The available behaviors are:

  • warn: Causes the named extension to work; however, using the extension will emit warnings. If used with all, then the use of any extensions will emit warnings.
  • disable: Prevents the named extension from working at all. Thus, any use of it will be seen as undefined syntax and cause an error. If used with all, then this prevents any extensions from working.

Preprocessor directives



#line directive


#line line
#line line source-string-number


Standard macros



Reserved names







GLSL has some unique expression definitions.

Constant expression

Constant expressions are expressions that can be evaluated at compile time. Constant expressions in GLSL are expressions that consist of:

  • A literal value.
    • A constant expression.
  • The result of the length() function of an array, but only if the array has an explicit size (who's size must be a constant expression).
  • The return value of any built-in function, but only if all of the arguments to the function are themselves constant expressions. Opaque Types are never constant expressions. Note that the functions dFdx, dFdy, fwidth, and their Coarse and Fine variations will return 0, when given a constant expression as an argument.

Integral constant expression


Dynamically uniform expression

Dynamically Uniform Expression
Core in version 4.6
Core since version 4.0

A dynamically uniform expression is a GLSL expression in which all invocations of that shader within a particular set of invocations will have the same value.

Only GLSL 4.00 and above makes a distinction about dynamically uniform expressions. Any restrictions you see that require a "dynamically uniform expression" will, in older GLSL versions require a "constant expression".

An expression in a GLSL shader is said to be dynamically uniform if, and only if, every shader invocation within the same invocation group will have the same value, in the same order. Whether an expression is dynamically uniform depends on the values provided; it cannot always be a priori determined from a shader's code.


Other expressions may or may not be dynamically uniform. For example, a shader stage input value will usually not be dynamically uniform. However, if every shader in the rendering command is given the exact same input value, then it will be dynamically uniform. It is the value of the expression which must be uniform; every shader invocation must get the same value, even if that same value is being read from different memory location.

gl_InstanceID is an example. If you render only a single instance, then gl_InstanceID will be dynamically uniform for that rendering command. However, if you render multiple instances in the same command, it will not. The same goes for Instanced Array input values.



Invocation group

Dynamically uniform expressions are based on shader invocations "within the same invocation group." The definition of "invocation group" depends on the shader stage in question. For Compute Shaders, the scope is all invocations within a work group. For shaders launched through Rendering Commands, this gets more complex.

Rendering scope extends to all invocations of all shader stages created to service a single drawing command. This means that, for Fragment Shaders, two distinct primitives in a rendering command are considered part of the same scope. This means that gl_PrimitiveID is not dynamically uniform (unless you render only one primitive). This is also why gl_InstanceID is only dynamically uniform when rendering a single instance; instanced rendering is considered a single drawing command.

However, there are drawing commands that create multiple scopes. The Multidraw Rendering commands, including the indirect versions, have separate scopes for their separate drawing sub-commands. So while doing instanced rendering in a draw command places all instances in a single scope, rendering multiple times with a multidraw command with a base instance creates multiple scopes, one per internal draw.

Note: The above information in this section is based on GLSL 4.60. As such, this may not be entirely correct for earlier versions; they defined the idea of "dynamically uniform", but didn't really go into explicit details. However, since they are based mainly on the hardware rather than the compiler, and this definition is really about the behavior of the hardware, it is not unreasonable to assume that they apply to older GLSL versions as well.



  • The array index for arrays of opaque types.
  • The index to buffer-backed interface block arrays.
  • In Compute Shaders, the expressions leading to the execution of a barrier() call. So if there is a loop or a conditional statement or somesuch, all of these conditions must be dynamically uniform expressions, so that every compute shader invocation encounters every barrier() statement in the same sequence and the same number of times.


V · E


in vec3 fromPrevious;
in uvec2 fromRange;

const int foo = 5;
const uvec2 range = uvec2(2, 5);
uniform vec2 pairs;

uniform sampler2d tex;

void main()
  foo; // constant expressions are dynamically uniform.
  value = range.x; // still dynamically uniform.
  value = 4; // dynamically uniform again.
  if (fromPrevious.y < 3.14)
    value = 12;












So, no recursion in GLSL. Of any kind.









The default if no qualifier is specific is in.

Consider the following:

  inputValue = 0.0;
  outputValue = int(inAndOutValue + inputValue);
  inAndOutValue = 3.0;

void main()
  float in1 = 10.5;
  int out1 = 5;
  float out2 = 10.0;
  MyFunction(in1, out1, out2);


in1 10.5
out1 10
out2 3.0

Notice that the value of in1 does not change.




Control flow

GLSL uses the standard C/C++ set of statements. It has selection statements (if-else and switch-case), iteration statements (for, while, and do-while), and Jump statments (break, continue, and return). These statements work essentially as C++ defines them (you can declare variables in a for statement, for example), though there are some limitations. For example, you can declare variables in if conditions in C++, but not in GLSL.

Notice that goto is absent from the list of jump statements. GLSL has no goto construct.

It does have a new jump command (effectively): discard. This keyword can only be used in Fragment Shaders. It causes the fragment shader's results to be discarded and ignored by the rest of the pipeline. That fragment's value(s) will not be written to the framebuffer.


Using discard is different from return from main. Executing return still means that the values written to the shader outputs will be used by the rest of the pipeline. Executing discard means that they will not. Also, returning before writing outputs to all of the outputs yields undefined behavior for the unwritten outputs, whereas discard has defined behavior for unwritten outputs.