diff options
author | Vadym Shovkoplias <[email protected]> | 2018-09-07 15:14:52 +0300 |
---|---|---|
committer | Tapani Pälli <[email protected]> | 2018-09-12 11:43:21 +0300 |
commit | 9b5c0c520f6e41f19b3568a4e0532c836bc522e4 (patch) | |
tree | 461785c1a157f3d016fd4c4ee8c0a0f2281df82a /src/compiler/glsl | |
parent | 30580640f2508e935e667e25f0e0cf4ff0ce55af (diff) |
glsl/linker: Check the invariance of built-in special variables
From Section 4.6.4 (Invariance and Linkage) of the GLSL ES 1.0 specification
"The invariance of varyings that are declared in both the vertex and
fragment shaders must match. For the built-in special variables,
gl_FragCoord can only be declared invariant if and only if
gl_Position is declared invariant. Similarly gl_PointCoord can only
be declared invariant if and only if gl_PointSize is declared
invariant. It is an error to declare gl_FrontFacing as invariant.
The invariance of gl_FrontFacing is the same as the invariance of
gl_Position."
Fixes:
* glsl-pcoord-invariant.shader_test
* glsl-fcoord-invariant.shader_test
* glsl-fface-invariant.shader_test
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=107734
Signed-off-by: Vadym Shovkoplias <[email protected]>
Reviewed-by: Tapani Pälli <[email protected]>
Diffstat (limited to 'src/compiler/glsl')
-rw-r--r-- | src/compiler/glsl/linker.cpp | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp index 57cf7eb2a8c..3fde7e78d31 100644 --- a/src/compiler/glsl/linker.cpp +++ b/src/compiler/glsl/linker.cpp @@ -1287,6 +1287,66 @@ interstage_cross_validate_uniform_blocks(struct gl_shader_program *prog, return true; } +/** + * Verifies the invariance of built-in special variables. + */ +static bool +validate_invariant_builtins(struct gl_shader_program *prog, + const gl_linked_shader *vert, + const gl_linked_shader *frag) +{ + const ir_variable *var_vert; + const ir_variable *var_frag; + + if (!vert || !frag) + return true; + + /* + * From OpenGL ES Shading Language 1.0 specification + * (4.6.4 Invariance and Linkage): + * "The invariance of varyings that are declared in both the vertex and + * fragment shaders must match. For the built-in special variables, + * gl_FragCoord can only be declared invariant if and only if + * gl_Position is declared invariant. Similarly gl_PointCoord can only + * be declared invariant if and only if gl_PointSize is declared + * invariant. It is an error to declare gl_FrontFacing as invariant. + * The invariance of gl_FrontFacing is the same as the invariance of + * gl_Position." + */ + var_frag = frag->symbols->get_variable("gl_FragCoord"); + if (var_frag && var_frag->data.invariant) { + var_vert = vert->symbols->get_variable("gl_Position"); + if (var_vert && !var_vert->data.invariant) { + linker_error(prog, + "fragment shader built-in `%s' has invariant qualifier, " + "but vertex shader built-in `%s' lacks invariant qualifier\n", + var_frag->name, var_vert->name); + return false; + } + } + + var_frag = frag->symbols->get_variable("gl_PointCoord"); + if (var_frag && var_frag->data.invariant) { + var_vert = vert->symbols->get_variable("gl_PointSize"); + if (var_vert && !var_vert->data.invariant) { + linker_error(prog, + "fragment shader built-in `%s' has invariant qualifier, " + "but vertex shader built-in `%s' lacks invariant qualifier\n", + var_frag->name, var_vert->name); + return false; + } + } + + var_frag = frag->symbols->get_variable("gl_FrontFacing"); + if (var_frag && var_frag->data.invariant) { + linker_error(prog, + "fragment shader built-in `%s' can not be declared as invariant\n", + var_frag->name); + return false; + } + + return true; +} /** * Populates a shaders symbol table with all global declarations @@ -5012,6 +5072,12 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) lower_named_interface_blocks(mem_ctx, prog->_LinkedShaders[i]); } + if (prog->IsES && prog->data->Version == 100) + if (!validate_invariant_builtins(prog, + prog->_LinkedShaders[MESA_SHADER_VERTEX], + prog->_LinkedShaders[MESA_SHADER_FRAGMENT])) + goto done; + /* Implement the GLSL 1.30+ rule for discard vs infinite loops Do * it before optimization because we want most of the checks to get * dropped thanks to constant propagation. |