glsl: add a is_implicit_initializer flag
authorPierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Thu, 30 Apr 2020 13:06:08 +0000 (15:06 +0200)
committerPierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Tue, 5 May 2020 10:26:02 +0000 (12:26 +0200)
Shared globals and glsl_zero_init can cause linker errors if the
variable is only initialized in 1 place.

This commit adds a flag to variables that have been implicitely
initialized to be able in this situation to keep the explicit
initialization value.

Without this change the global-single-initializer-2-shaders piglit
test fails when using glsl_zero_init.

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4607>

src/compiler/glsl/ast_to_hir.cpp
src/compiler/glsl/ir.cpp
src/compiler/glsl/ir.h
src/compiler/glsl/linker.cpp

index fb7c2cce924e14873b225839dbd2e311bb144c7d..8e6174998115f521c074f701f9e598a10b57c4d5 100644 (file)
@@ -4630,6 +4630,7 @@ process_initializer(ir_variable *var, ast_declaration *decl,
       if (!error_emitted) {
          var->constant_initializer = rhs->constant_expression_value(mem_ctx);
          var->data.has_initializer = true;
+         var->data.is_implicit_initializer = false;
 
          /* If the declared variable is an unsized array, it must inherrit
          * its full type from the initializer.  A declaration such as
@@ -5269,6 +5270,7 @@ ast_declarator_list::hir(exec_list *instructions,
           (var->type->is_numeric() || var->type->is_boolean())) {
          const ir_constant_data data = { { 0 } };
          var->data.has_initializer = true;
+         var->data.is_implicit_initializer = true;
          var->constant_initializer = new(var) ir_constant(var->type, &data);
       }
 
@@ -5863,6 +5865,7 @@ ast_parameter_declarator::hir(exec_list *instructions,
        (var->type->is_numeric() || var->type->is_boolean())) {
          const ir_constant_data data = { { 0 } };
          var->data.has_initializer = true;
+         var->data.is_implicit_initializer = true;
          var->constant_initializer = new(var) ir_constant(var->type, &data);
    }
 
@@ -8776,6 +8779,7 @@ ast_cs_input_layout::hir(exec_list *instructions,
    var->constant_initializer =
       new(var) ir_constant(glsl_type::uvec3_type, &data);
    var->data.has_initializer = true;
+   var->data.is_implicit_initializer = false;
 
    return NULL;
 }
@@ -8807,6 +8811,7 @@ detect_conflicting_assignments(struct _mesa_glsl_parse_state *state,
          if (!var->constant_initializer && state->zero_init) {
             const ir_constant_data data = { { 0 } };
             var->data.has_initializer = true;
+            var->data.is_implicit_initializer = true;
             var->constant_initializer = new(var) ir_constant(var->type, &data);
          }
       }
index 922dcd3c8198f9ee2553779e45c587ca7c59b757..66660c73c75b1f5e0c16f2ba1be2b6d511eacafc 100644 (file)
@@ -1834,6 +1834,7 @@ ir_variable::ir_variable(const struct glsl_type *type, const char *name,
    this->data.explicit_binding = false;
    this->data.explicit_component = false;
    this->data.has_initializer = false;
+   this->data.is_implicit_initializer = false;
    this->data.is_unmatched_generic_inout = false;
    this->data.is_xfb_only = false;
    this->data.explicit_xfb_buffer = false;
index e84da9a50278b496f024ca05192969b2f130deb7..c6edffea34a33c0cd77c1cc8aade8433b27b57fc 100644 (file)
@@ -758,6 +758,11 @@ public:
        */
       unsigned has_initializer:1;
 
+      /**
+       * Is the initializer created by the compiler (glsl_zero_init)
+       */
+      unsigned is_implicit_initializer:1;
+
       /**
        * Is this variable a generic output or input that has not yet been matched
        * up to a variable in another stage of the pipeline?
index a49c5e6ccc201dcc29ac7a0f0ae13019f3d66365..a674726312f73af0277ff76714e27c795e854fe9 100644 (file)
@@ -1064,9 +1064,13 @@ cross_validate_globals(struct gl_context *ctx, struct gl_shader_program *prog,
           * no vendor actually implemented that behavior.  The 4.20
           * behavior matches the implemented behavior of at least one other
           * vendor, so we'll implement that for all GLSL versions.
+          * If (at least) one of these constant expressions is implicit,
+          * because it was added by glsl_zero_init, we skip the verification.
           */
          if (var->constant_initializer != NULL) {
-            if (existing->constant_initializer != NULL) {
+            if (existing->constant_initializer != NULL &&
+                !existing->data.is_implicit_initializer &&
+                !var->data.is_implicit_initializer) {
                if (!var->constant_initializer->has_value(existing->constant_initializer)) {
                   linker_error(prog, "initializers for %s "
                                "`%s' have differing values\n",
@@ -1078,7 +1082,8 @@ cross_validate_globals(struct gl_context *ctx, struct gl_shader_program *prog,
                 * not have an initializer but a later instance does,
                 * replace the former with the later.
                 */
-               variables->replace_variable(existing->name, var);
+               if (!var->data.is_implicit_initializer)
+                  variables->replace_variable(existing->name, var);
             }
          }