Compiler Behavior Notes
From shaderLABS
More actions
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
#versionargument are not supported.- The GLSL spec says that
#versionmust be the first non-whitespace line in your code.
- The GLSL spec says that
- 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 likeif(abs(a - 1.0) < 0.0001)
- e.g.
- 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)
- e.g.
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))
- Can be manually implemented like this:
- GL Extensions have to be explicitly enabled (e.g.
GL_ARB_shader_texture_lod). - GL Extension
#extension GL_EXT_gpu_shader4 : enableis required for specific operations, even on GL300 and newer when using function calls with the2Dor3Dsuffix (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 / kon said buffer fixes the issue, with k being the maximum amount of discreet values supported by the current buffer precision (e.g.255.0on 8 bit and65535.0on 16 bit).
- Doing a clamp with a minimum of
- Normalizing a zero vector results in NaNs.
- Implicit casts from
int/uintto float may fail to compile. - Variables marked as
constthat 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 offloat add(float x, float y) { return x + y; }
- e.g.
- The same might apply to constants made of other constants.
- e.g.
- 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.
- Sampling inside a function works fine, as long as it doesn't get used outside of
- Reserved words:
buffer,inputandhalfinputis reserved for future use as part of specification.halfis reserved as part of specification.
- Using
gl_MultiTexcoordon GLSL 1.3+ without the compatibility profile is allowed.gl_MultiTexCoordwas 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
constthat 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:
halfhalfis 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
#versiondirective. - 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 offloat add(float x, float y) {return x + y;}
- e.g.
- e.g.
- Constants using
structinputs are not supported.
macOS
- Empty external declarations (just a single
;at the global level) are not allowed. This includes semicolons after function definitions likevoid 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
mainfunction and only keep the declaration in its original location.
- Instead, move the initialization to the top of the
- 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_4is 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()).
- This can lead to wrong information being read unless the LOD to be read from is explicitly declared (
Nouveau (Nvidia, Open Source)
- Not compatible.
Nvidia (proprietary)
- Same as on Windows.
AMD (proprietary)
- Same as on Windows.