Compiler Behavior Notes

From shaderLABS



  • Includes before the #version argument are not supported.
    • The GLSL spec says that #version must be the first non-whitespace line in your code.
  • Equal conditions using floats may not work as intended.
    • e.g. if (a == 1.0)
    • Comparing floats this way is considered bad practice since there's multiple ways to represent a lot of numbers, meaning that they might have different values. A more reliable way is to either convert them to ints first or do something like if(abs(a - 1.0) < 0.0001)
  • Constant arguments of functions get compiled as actual constants and can be used in constant expressions.
    • e.g. void blah(const int a, const float b)
  • mix() is not supported in constant expressions on GeForce 500 and older.
    • Can be manually implemented like this: #define cmix(x, y, a) (y * a + x * (1.0 - a))
  • GL Extensions have to be explicitly enabled (e.g. GL_ARB_shader_texture_lod).
  • GL Extension #extension GL_EXT_gpu_shader4 : enable is required for specific operations, even on GL300 and newer when using function calls with the 2D or 3D suffix (e.g. texelFetch2D()).
  • NaNs may occur when not clamping the framebuffer used for the main scene color, especially on blacks.
    • Doing a clamp with a minimum of 1.0 / k on said buffer fixes the issue, with k being the maximum amount of discreet values supported by the current buffer precision (e.g. 255.0 on 8 bit and 65535.0 on 16 bit).
  • Normalizing a zero vector results in NaNs.
  • Implicit casts from int / uint to float may fail to compile.
  • Variables marked as const that aren't constant expressions are allowed treated as immutable, even prior to GLSL 4.2 where this is illegal according to the spec.


  • Constants using some of the built-in functions are not supported.
    • e.g. const float f = const_func();
    • They can be manually implemented as macro, just like non-built-in functions:
      • e.g. #define add(x, y) (x + y) instead of float add(float x, float y) { return x + y; }
    • The same might apply to constants made of other constants.
  • Sampling textures outside of void main() causes sampling of a wrong texture.
    • Sampling inside a function works fine, as long as it doesn't get used outside of void main() or other functions.
  • Reserved words: buffer, input and half
    • input is reserved for future use as part of specification.
    • half is reserved as part of specification.
  • Using gl_MultiTexcoord on GLSL 1.3+ without the compatibility profile is allowed.
    • gl_MultiTexCoord was deprecated in GLSL 1.3 and removed from the core profile in 1.4, so it shouldn't be possible to use in a core profile of 1.4 or later.
  • Some GL Extensions will be enabled automatically when used without explicitly being enabled (e.g. GL_ARB_shader_texture_lod).
  • The usage of geometry shaders on terrain requires external triangulation for quad-geometry.
  • Using shadow mipmaps with a shadow map resolution that is not a power of two can cause a crash on loading.
  • Function type casting from float to a vector type is apparently supported.
  • Variables marked as const that aren't constant expressions are not allowed, even in GLSL 4.2+ where this is legal according to the spec (the variables should be treated as immutable).


  • Reserved word: half
    • half is reserved as part of specification.
  • Only up to seven framebuffer attachments are supported.
    • The specification only guarantees seven but allows more.
    • GLSL 3.0+ guarantees eight framebuffer attachments.
  • Recursive macros are not allowed (e.g. #define smoothstep(x, low, high) smoothstep(low, high, x)).
  • Extensions have to be declared directly after the #version directive.
  • Constants using built-in functions may fail to compile.
    • e.g. const float f = const_func();
    • They can be manually implemented as macro.
      • e.g. #define add(x, y) (x+y) instead of float add(float x, float y) {return x + y;}
  • Constants using struct inputs are not supported.


  • Empty external declarations (just a single ; at the global level) are not allowed. This includes semicolons after function definitions like void main() { ... }; where the semicolon is technically separate from the function definition and constitutes its own (empty) external declaration.


  • Calling a function in the global scope (outside of other functions) crashes the whole application.
    • Instead, move the initialization to the top of the main function and only keep the declaration in its original location.


Mesa (AMD, open source)

  • Only GLSL 1.1, 1.2, 1.3, 1.0 ES, 3.0 ES, 3.1 ES and 3.2 ES are supported (possibly only affects APUs).
    • On Polaris/Vega based cards, GLSL 4.3 compatibility is available.
  • EXT_gpu_shader_4 is not supported.
    • Certain features can be achieved with different extensions.
  • If an image has LODs enabled but gets overwritten in the next pass, the LODs from the previous pass are still bound.
    • This can lead to wrong information being read unless the LOD to be read from is explicitly declared (textureLod()).

Nouveau (NVIDIA, open source)

  • Not compatible.

NVIDIA (proprietary)

  • Same as on Windows.

AMD (proprietary)

  • Same as on Windows.