Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

Compiler Behavior Notes

From shaderLABS

All GPU drivers have quirks that violate the GLSL specification or interpret it differently. They can lead to crashes, compilation errors and visual glitches. This non-exhaustive list aims to document as many of them as possible.

Windows

Nvidia

  • 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.

AMD

  • 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).

Intel

  • 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.

macOS

  • 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.

Apple Silicon (M1 or Newer)

  • 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.
  • Arrays of arrays (eg. vec2[8][4]) crash the whole application as well.

Linux

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.