On 31 October 2011 18:07, Ian Romanick <span dir="ltr">&lt;<a href="mailto:idr@freedesktop.org">idr@freedesktop.org</a>&gt;</span> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
From: Ian Romanick &lt;<a href="mailto:ian.d.romanick@intel.com">ian.d.romanick@intel.com</a>&gt;<br>
<br>
This requires tracking a couple extra fields in ir_variable:<br>
<br>
 * A flag to indicate that a variable had an initializer.<br>
<br>
 * For non-const variables, a field to track the constant value of the<br>
   variable&#39;s initializer.<br>
<br>
For variables non-constant initalizers, ir_variable::has_initializer<br>
will be true, but ir_variable::constant_initializer will be NULL.  The<br>
linker can use the values of these fields to check adherence to the<br>
GLSL 4.20 rules for shared global variables:<br>
<br>
    &quot;If a shared global has multiple initializers, the initializers<br>
    must all be constant expressions, and they must all have the same<br>
    value. Otherwise, a link error will result. (A shared global<br>
    having only one initializer does not require that initializer to<br>
    be a constant expression.)&quot;<br>
<br>
Previous to 4.20 the GLSL spec simply said that initializers must have<br>
the same value.  In this case of non-constant initializers, this was<br>
impossible to determine.  As a result, no vendor actually implemented<br>
that behavior.  The 4.20 behavior matches the behavior of NVIDIA&#39;s<br>
shipping implementations.<br>
<br>
NOTE: This is candidate for the 7.11 branch.  This patch also needs<br>
the preceding patch &quot;glsl: Refactor generate_ARB_draw_buffers_variables<br>
to use add_builtin_constant&quot;<br>
<br>
Signed-off-by: Ian Romanick &lt;<a href="mailto:ian.d.romanick@intel.com">ian.d.romanick@intel.com</a>&gt;<br>
Bugzilla: <a href="https://bugs.freedesktop.org/show_bug.cgi?id=34687" target="_blank">https://bugs.freedesktop.org/show_bug.cgi?id=34687</a><br></blockquote><div><br>I have a few concerns about this patch, which we talked about in person today.  To summarize for the list:<br>
<br>- There&#39;s a &quot;finishme&quot; comment just above the last hunk that I think we should really address.  The test &quot;glsl-link-initializers-03&quot; is trying to demonstrate that problem, but it has bugs.  I&#39;ll submit an improved &quot;glsl-link-initializers-03&quot; to the list.<br>
<br>- I think these changes regress propagation of uniform initializers.  In other words, if one shader initializes a uniform and the other doesn&#39;t, then depending on the order in which the shaders are linked, the initializer might be lost.<br>
<br>That said, this is clearly an improvement over the previous state of the code, and I would be ok with accepting the patches and then doing some follow-up fixes.<br> </div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">

---<br>
 src/glsl/ast_to_hir.cpp  |    3 ++<br>
 src/glsl/ir.cpp          |    5 ++++<br>
 src/glsl/ir.h            |   18 +++++++++++++++++<br>
 src/glsl/ir_clone.cpp    |    5 ++++<br>
 src/glsl/ir_validate.cpp |    7 ++++++<br>
 src/glsl/ir_variable.cpp |    2 +<br>
 src/glsl/linker.cpp      |   48 +++++++++++++++++++++++++++++++++++++++------<br>
 7 files changed, 81 insertions(+), 7 deletions(-)<br>
<br>
diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp<br>
index 7584fdf..bd9c33d 100644<br>
--- a/src/glsl/ast_to_hir.cpp<br>
+++ b/src/glsl/ast_to_hir.cpp<br>
@@ -2351,6 +2351,9 @@ process_initializer(ir_variable *var, ast_declaration *decl,<br>
       } else<br>
         initializer_type = rhs-&gt;type;<br>
<br>
+      var-&gt;constant_initializer = rhs-&gt;constant_expression_value();<br>
+      var-&gt;has_initializer = true;<br>
+<br>
       /* If the declared variable is an unsized array, it must inherrit<br>
        * its full type from the initializer.  A declaration such as<br>
        *<br>
diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp<br>
index ef7300e..a5eca5a 100644<br>
--- a/src/glsl/ir.cpp<br>
+++ b/src/glsl/ir.cpp<br>
@@ -1326,9 +1326,11 @@ ir_variable::ir_variable(const struct glsl_type *type, const char *name,<br>
    this-&gt;type = type;<br>
    this-&gt;name = ralloc_strdup(this, name);<br>
    this-&gt;explicit_location = false;<br>
+   this-&gt;has_initializer = false;<br>
    this-&gt;location = -1;<br>
    this-&gt;warn_extension = NULL;<br>
    this-&gt;constant_value = NULL;<br>
+   this-&gt;constant_initializer = NULL;<br>
    this-&gt;origin_upper_left = false;<br>
    this-&gt;pixel_center_integer = false;<br>
    this-&gt;depth_layout = ir_depth_layout_none;<br>
@@ -1489,6 +1491,9 @@ steal_memory(ir_instruction *ir, void *new_ctx)<br>
    if (var != NULL &amp;&amp; var-&gt;constant_value != NULL)<br>
       steal_memory(var-&gt;constant_value, ir);<br>
<br>
+   if (var != NULL &amp;&amp; var-&gt;constant_initializer != NULL)<br>
+      steal_memory(var-&gt;constant_initializer, ir);<br>
+<br>
    /* The components of aggregate constants are not visited by the normal<br>
     * visitor, so steal their values by hand.<br>
     */<br>
diff --git a/src/glsl/ir.h b/src/glsl/ir.h<br>
index abbf455..5878c05 100644<br>
--- a/src/glsl/ir.h<br>
+++ b/src/glsl/ir.h<br>
@@ -365,6 +365,14 @@ public:<br>
    unsigned explicit_location:1;<br>
<br>
    /**<br>
+    * Does this variable have an initializer?<br>
+    *<br>
+    * This is used by the linker to cross-validiate initializers of global<br>
+    * variables.<br>
+    */<br>
+   unsigned has_initializer:1;<br>
+<br>
+   /**<br>
     * \brief Layout qualifier for gl_FragDepth.<br>
     *<br>
     * This is not equal to \c ir_depth_layout_none if and only if this<br>
@@ -414,6 +422,16 @@ public:<br>
     * Value assigned in the initializer of a variable declared &quot;const&quot;<br>
     */<br>
    ir_constant *constant_value;<br>
+<br>
+   /**<br>
+    * Constant expression assigned in the initializer of the variable<br>
+    *<br>
+    * \warning<br>
+    * This field and \c ::constant_value are distinct.  Even if the two fields<br>
+    * refer to constants with the same value, they must point to separate<br>
+    * objects.<br>
+    */<br>
+   ir_constant *constant_initializer;<br>
 };<br>
<br>
<br>
diff --git a/src/glsl/ir_clone.cpp b/src/glsl/ir_clone.cpp<br>
index 9adf470..e8ac9fb 100644<br>
--- a/src/glsl/ir_clone.cpp<br>
+++ b/src/glsl/ir_clone.cpp<br>
@@ -50,6 +50,7 @@ ir_variable::clone(void *mem_ctx, struct hash_table *ht) const<br>
    var-&gt;origin_upper_left = this-&gt;origin_upper_left;<br>
    var-&gt;pixel_center_integer = this-&gt;pixel_center_integer;<br>
    var-&gt;explicit_location = this-&gt;explicit_location;<br>
+   var-&gt;has_initializer = this-&gt;has_initializer;<br>
<br>
    var-&gt;num_state_slots = this-&gt;num_state_slots;<br>
    if (this-&gt;state_slots) {<br>
@@ -68,6 +69,10 @@ ir_variable::clone(void *mem_ctx, struct hash_table *ht) const<br>
    if (this-&gt;constant_value)<br>
       var-&gt;constant_value = this-&gt;constant_value-&gt;clone(mem_ctx, ht);<br>
<br>
+   if (this-&gt;constant_initializer)<br>
+      var-&gt;constant_initializer =<br>
+        this-&gt;constant_initializer-&gt;clone(mem_ctx, ht);<br>
+<br>
    if (ht) {<br>
       hash_table_insert(ht, var, (void *)const_cast&lt;ir_variable *&gt;(this));<br>
    }<br>
diff --git a/src/glsl/ir_validate.cpp b/src/glsl/ir_validate.cpp<br>
index c387ecb..a352012 100644<br>
--- a/src/glsl/ir_validate.cpp<br>
+++ b/src/glsl/ir_validate.cpp<br>
@@ -496,6 +496,13 @@ ir_validate::visit(ir_variable *ir)<br>
       }<br>
    }<br>
<br>
+   if (ir-&gt;constant_initializer != NULL &amp;&amp; !ir-&gt;has_initializer) {<br>
+      printf(&quot;ir_variable didn&#39;t have an initializer, but has a constant &quot;<br>
+            &quot;initializer value.\n&quot;);<br>
+      ir-&gt;print();<br>
+      abort();<br>
+   }<br>
+<br>
    return visit_continue;<br>
 }<br>
<br>
diff --git a/src/glsl/ir_variable.cpp b/src/glsl/ir_variable.cpp<br>
index bea0b2b..e719abe 100644<br>
--- a/src/glsl/ir_variable.cpp<br>
+++ b/src/glsl/ir_variable.cpp<br>
@@ -408,6 +408,8 @@ add_builtin_constant(exec_list *instructions, glsl_symbol_table *symtab,<br>
                                         name, glsl_type::int_type,<br>
                                         ir_var_auto, -1);<br>
    var-&gt;constant_value = new(var) ir_constant(value);<br>
+   var-&gt;constant_initializer = new(var) ir_constant(value);<br>
+   var-&gt;has_initializer = true;<br>
    return var;<br>
 }<br>
<br>
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp<br>
index a595c9c..915d5bb 100644<br>
--- a/src/glsl/linker.cpp<br>
+++ b/src/glsl/linker.cpp<br>
@@ -448,17 +448,30 @@ cross_validate_globals(struct gl_shader_program *prog,<br>
               }<br>
            }<br>
<br>
-           /* FINISHME: Handle non-constant initializers.<br>
+           /* Page 35 (page 41 of the PDF) of the GLSL 4.20 spec says:<br>
+            *<br>
+            *     &quot;If a shared global has multiple initializers, the<br>
+            *     initializers must all be constant expressions, and they<br>
+            *     must all have the same value. Otherwise, a link error will<br>
+            *     result. (A shared global having only one initializer does<br>
+            *     not require that initializer to be a constant expression.)&quot;<br>
+            *<br>
+            * Previous to 4.20 the GLSL spec simply said that initializers<br>
+            * must have the same value.  In this case of non-constant<br>
+            * initializers, this was impossible to determine.  As a result,<br>
+            * no vendor actually implemented that behavior.  The 4.20<br>
+            * behavior matches the implemented behavior of at least one other<br>
+            * vendor, so we&#39;ll implement that for all GLSL versions.<br>
             */<br>
-           if (var-&gt;constant_value != NULL) {<br>
-              if (existing-&gt;constant_value != NULL) {<br>
-                 if (!var-&gt;constant_value-&gt;has_value(existing-&gt;constant_value)) {<br>
+           if (var-&gt;constant_initializer != NULL) {<br>
+              if (existing-&gt;constant_initializer != NULL) {<br>
+                 if (!var-&gt;constant_initializer-&gt;has_value(existing-&gt;constant_initializer)) {<br>
                     linker_error(prog, &quot;initializers for %s &quot;<br>
                                  &quot;`%s&#39; have differing values\n&quot;,<br>
                                  mode_string(var), var-&gt;name);<br>
                     return false;<br>
                  }<br>
-              } else<br>
+              } else {<br>
                  /* If the first-seen instance of a particular uniform did not<br>
                   * have an initializer but a later instance does, copy the<br>
                   * initializer to the version stored in the symbol table.<br>
@@ -471,8 +484,29 @@ cross_validate_globals(struct gl_shader_program *prog,<br>
                   * FINISHME: modify the shader, and linking with the second<br>
                   * FINISHME: will fail.<br>
                   */<br>
-                 existing-&gt;constant_value =<br>
-                    var-&gt;constant_value-&gt;clone(ralloc_parent(existing), NULL);<br>
+                 existing-&gt;constant_initializer =<br>
+                    var-&gt;constant_initializer-&gt;clone(ralloc_parent(existing),<br>
+                                                     NULL);<br>
+              }<br>
+           }<br>
+<br>
+           if (var-&gt;has_initializer) {<br>
+              if (existing-&gt;has_initializer<br>
+                  &amp;&amp; (var-&gt;constant_initializer == NULL<br>
+                      || existing-&gt;constant_initializer == NULL)) {<br>
+                 linker_error(prog,<br>
+                              &quot;shared global variable `%s&#39; has multiple &quot;<br>
+                              &quot;non-constant initializers.\n&quot;,<br>
+                              var-&gt;name);<br>
+                 return false;<br>
+              }<br>
+<br>
+              /* Some instance had an initializer, so keep track of that.  In<br>
+               * this location, all sorts of initializers (constant or<br>
+               * otherwise) will propagate the existence to the variable<br>
+               * stored in the symbol table.<br>
+               */<br>
+              existing-&gt;has_initializer = true;<br>
            }<br>
<br>
            if (existing-&gt;invariant != var-&gt;invariant) {<br>
<font color="#888888">--<br>
1.7.6.4<br>
<br>
_______________________________________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/mesa-dev" target="_blank">http://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
</font></blockquote></div><br>