glsl: Cross validate variable's invariance by explicit invariance only
authorDanylo Piliaiev <danylo.piliaiev@globallogic.com>
Tue, 4 Sep 2018 08:42:04 +0000 (11:42 +0300)
committerJordan Justen <jordan.l.justen@intel.com>
Fri, 22 Mar 2019 06:28:08 +0000 (23:28 -0700)
'invariant' qualifier is propagated on variables which are used
to calculate other invariant variables, however when we are matching
variable's declarations we should take into account only explicitly
declared invariance because invariance propagation is an implementation
specific detail.

Thus new flag is added to ir_variable_data which indicates 'invariant'
qualifier being explicitly set in the shader.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=100316
Fixes: 89b60492 ('glsl: Add a pass to propagate the "invariant" and
  "precise" qualifiers')

Signed-off-by: Danylo Piliaiev <danylo.piliaiev@globallogic.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
src/compiler/glsl/ast_to_hir.cpp
src/compiler/glsl/ir.cpp
src/compiler/glsl/ir.h
src/compiler/glsl/ir_print_visitor.cpp
src/compiler/glsl/ir_reader.cpp
src/compiler/glsl/link_varyings.cpp
src/compiler/glsl/linker.cpp

index 3875fa1e384e5dae6a8203d621c497d5a255eb63..2a71a13d545a970bb3b8e58188ac59478e60a24e 100644 (file)
@@ -3942,7 +3942,8 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
                           "`invariant' after being used",
                           var->name);
       } else {
-         var->data.invariant = 1;
+         var->data.explicit_invariant = true;
+         var->data.invariant = true;
       }
    }
 
@@ -4150,8 +4151,10 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
       }
    }
 
-   if (state->all_invariant && var->data.mode == ir_var_shader_out)
+   if (state->all_invariant && var->data.mode == ir_var_shader_out) {
+      var->data.explicit_invariant = true;
       var->data.invariant = true;
+   }
 
    var->data.interpolation =
       interpret_interpolation_qualifier(qual, var->type,
@@ -4862,6 +4865,7 @@ ast_declarator_list::hir(exec_list *instructions,
                             "`invariant' after being used",
                             earlier->name);
          } else {
+            earlier->data.explicit_invariant = true;
             earlier->data.invariant = true;
          }
       }
index 060bd3ae7f5295416fd6890090ec98a3866e386f..6b455cdf5106fcdc7e86676c36417bd4f3c29243 100644 (file)
@@ -1732,6 +1732,7 @@ ir_variable::ir_variable(const struct glsl_type *type, const char *name,
    this->data.centroid = false;
    this->data.sample = false;
    this->data.patch = false;
+   this->data.explicit_invariant = false;
    this->data.invariant = false;
    this->data.how_declared = ir_var_declared_normally;
    this->data.mode = mode;
index 9ec332ab46cee8a27fdb81043bd8888adebb612a..4dc2a5f6bc75bd44fd5b3adbad0daa0b7c15cff8 100644 (file)
@@ -657,6 +657,19 @@ public:
       unsigned centroid:1;
       unsigned sample:1;
       unsigned patch:1;
+      /**
+       * Was an 'invariant' qualifier explicitly set in the shader?
+       *
+       * This is used to cross validate qualifiers.
+       */
+      unsigned explicit_invariant:1;
+      /**
+       * Is the variable invariant?
+       *
+       * It can happen either by having the 'invariant' qualifier
+       * explicitly set in the shader or by being used in calculations
+       * of other invariant variables.
+       */
       unsigned invariant:1;
       unsigned precise:1;
 
index 119e3ee1e2e67dc24b4c7e678746f2911eb23fad..e208aaef88891752f89d1b7df20d30fc9c13f10a 100644 (file)
@@ -199,6 +199,7 @@ void ir_print_visitor::visit(ir_variable *ir)
    const char *const samp = (ir->data.sample) ? "sample " : "";
    const char *const patc = (ir->data.patch) ? "patch " : "";
    const char *const inv = (ir->data.invariant) ? "invariant " : "";
+   const char *const explicit_inv = (ir->data.explicit_invariant) ? "explicit_invariant " : "";
    const char *const prec = (ir->data.precise) ? "precise " : "";
    const char *const bindless = (ir->data.bindless) ? "bindless " : "";
    const char *const bound = (ir->data.bound) ? "bound " : "";
@@ -215,11 +216,11 @@ void ir_print_visitor::visit(ir_variable *ir)
    const char *const interp[] = { "", "smooth", "flat", "noperspective" };
    STATIC_ASSERT(ARRAY_SIZE(interp) == INTERP_MODE_COUNT);
 
-   fprintf(f, "(%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s) ",
+   fprintf(f, "(%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s) ",
            binding, loc, component, cent, bindless, bound,
            image_format, memory_read_only, memory_write_only,
            memory_coherent, memory_volatile, memory_restrict,
-           samp, patc, inv, prec, mode[ir->data.mode],
+           samp, patc, inv, explicit_inv, prec, mode[ir->data.mode],
            stream,
            interp[ir->data.interpolation]);
 
index b87933ba511f3ecc669789d067a122433d629f35..d4f0e58b155cbe5edc70508b2f49cf3fb05a4660 100644 (file)
@@ -419,8 +419,10 @@ ir_reader::read_declaration(s_expression *expr)
          var->data.sample = 1;
       } else if (strcmp(qualifier->value(), "patch") == 0) {
          var->data.patch = 1;
+      } else if (strcmp(qualifier->value(), "explicit_invariant") == 0) {
+         var->data.explicit_invariant = true;
       } else if (strcmp(qualifier->value(), "invariant") == 0) {
-        var->data.invariant = 1;
+         var->data.invariant = true;
       } else if (strcmp(qualifier->value(), "uniform") == 0) {
         var->data.mode = ir_var_uniform;
       } else if (strcmp(qualifier->value(), "shader_storage") == 0) {
index 618610039ea758fbd68fa48e4dcd7b3921405704..352cd7e522bf5a28436d38bc2605db36cd9c6960 100644 (file)
@@ -309,16 +309,16 @@ cross_validate_types_and_qualifiers(struct gl_context *ctx,
     *    "The invariance of varyings that are declared in both the vertex
     *     and fragment shaders must match."
     */
-   if (input->data.invariant != output->data.invariant &&
+   if (input->data.explicit_invariant != output->data.explicit_invariant &&
        prog->data->Version < (prog->IsES ? 300 : 430)) {
       linker_error(prog,
                    "%s shader output `%s' %s invariant qualifier, "
                    "but %s shader input %s invariant qualifier\n",
                    _mesa_shader_stage_to_string(producer_stage),
                    output->name,
-                   (output->data.invariant) ? "has" : "lacks",
+                   (output->data.explicit_invariant) ? "has" : "lacks",
                    _mesa_shader_stage_to_string(consumer_stage),
-                   (input->data.invariant) ? "has" : "lacks");
+                   (input->data.explicit_invariant) ? "has" : "lacks");
       return;
    }
 
index 53887ab71da517610e4fbed162226100a04106fa..c6664e98ce3754267b7eace0c7ebdea165f50dc1 100644 (file)
@@ -1090,7 +1090,7 @@ cross_validate_globals(struct gl_context *ctx, struct gl_shader_program *prog,
             }
          }
 
-         if (existing->data.invariant != var->data.invariant) {
+         if (existing->data.explicit_invariant != var->data.explicit_invariant) {
             linker_error(prog, "declarations for %s `%s' have "
                          "mismatching invariant qualifiers\n",
                          mode_string(var), var->name);