From 9b5c0c520f6e41f19b3568a4e0532c836bc522e4 Mon Sep 17 00:00:00 2001 From: Vadym Shovkoplias Date: Fri, 7 Sep 2018 15:14:52 +0300 Subject: [PATCH] glsl/linker: Check the invariance of built-in special variables MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Tapani Pälli --- src/compiler/glsl/linker.cpp | 66 ++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) 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. -- 2.30.2