[Mesa-dev] [PATCH v2] glsl: Prohibit illegal mixing of redeclarations inside/outside gl_PerVertex.

Paul Berry stereotype441 at gmail.com
Tue Nov 19 17:55:15 PST 2013


>From section 7.1 (Built-In Language Variables) of the GLSL 4.10
spec:

    Also, if a built-in interface block is redeclared, no member of
    the built-in declaration can be redeclared outside the block
    redeclaration.

We have been regarding this text as a clarification to the behaviour
established for gl_PerVertex by GLSL 1.50, so we apply it regardless
of GLSL version.

This patch enforces the rule by adding a boolean to ir_variable to
track how the variable was declared: implicitly, normally, or in an
interface block.

Fixes piglit tests:
- gs-redeclares-pervertex-out-after-global-redeclaration.geom
- vs-redeclares-pervertex-out-after-global-redeclaration.vert
- gs-redeclares-pervertex-out-after-other-global-redeclaration.geom
- vs-redeclares-pervertex-out-after-other-global-redeclaration.vert
- gs-redeclares-pervertex-out-before-global-redeclaration
- vs-redeclares-pervertex-out-before-global-redeclaration

Cc: "10.0" <mesa-stable at lists.freedesktop.org>

v2: Don't set "how_declared" redundantly in builtin_variables.cpp.
Properly clone "how_declared".
---
 src/glsl/ast_to_hir.cpp        | 20 ++++++++++++++++++++
 src/glsl/builtin_variables.cpp |  1 +
 src/glsl/ir.cpp                |  3 ++-
 src/glsl/ir.h                  | 36 ++++++++++++++++++++++++++++++++++++
 src/glsl/ir_clone.cpp          |  1 +
 5 files changed, 60 insertions(+), 1 deletion(-)

diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
index 76b256c..0128047 100644
--- a/src/glsl/ast_to_hir.cpp
+++ b/src/glsl/ast_to_hir.cpp
@@ -3355,6 +3355,15 @@ ast_declarator_list::hir(exec_list *instructions,
       ir_variable *earlier =
          get_variable_being_redeclared(var, decl->get_location(), state,
                                        false /* allow_all_redeclarations */);
+      if (earlier != NULL) {
+         if (strncmp(var->name, "gl_", 3) == 0 &&
+             earlier->how_declared == ir_var_declared_in_block) {
+            _mesa_glsl_error(&loc, state,
+                             "`%s' has already been redeclared using "
+                             "gl_PerVertex", var->name);
+         }
+         earlier->how_declared = ir_var_declared_normally;
+      }
 
       if (decl->initializer != NULL) {
 	 result = process_initializer((earlier == NULL) ? var : earlier,
@@ -5048,6 +5057,7 @@ ast_interface_block::hir(exec_list *instructions,
             _mesa_glsl_error(&loc, state, "`%s' redeclared",
                              this->instance_name);
          }
+         earlier->how_declared = ir_var_declared_normally;
          earlier->type = var->type;
          earlier->reinit_interface_type(block_type);
          delete var;
@@ -5078,7 +5088,11 @@ ast_interface_block::hir(exec_list *instructions,
                _mesa_glsl_error(&loc, state,
                                 "redeclaration of gl_PerVertex can only "
                                 "include built-in variables");
+            } else if (earlier->how_declared == ir_var_declared_normally) {
+               _mesa_glsl_error(&loc, state,
+                                "`%s' has already been redeclared", var->name);
             } else {
+               earlier->how_declared = ir_var_declared_in_block;
                earlier->reinit_interface_type(block_type);
             }
             continue;
@@ -5125,6 +5139,12 @@ ast_interface_block::hir(exec_list *instructions,
             if (var != NULL &&
                 var->get_interface_type() == earlier_per_vertex &&
                 var->mode == var_mode) {
+               if (var->how_declared == ir_var_declared_normally) {
+                  _mesa_glsl_error(&loc, state,
+                                   "redeclaration of gl_PerVertex cannot "
+                                   "follow a redeclaration of `%s'",
+                                   var->name);
+               }
                state->symbols->disable_variable(var->name);
                var->remove();
             }
diff --git a/src/glsl/builtin_variables.cpp b/src/glsl/builtin_variables.cpp
index 4d44104..d57324c 100644
--- a/src/glsl/builtin_variables.cpp
+++ b/src/glsl/builtin_variables.cpp
@@ -434,6 +434,7 @@ builtin_variable_generator::add_variable(const char *name,
                                          enum ir_variable_mode mode, int slot)
 {
    ir_variable *var = new(symtab) ir_variable(type, name, mode);
+   var->how_declared = ir_var_declared_implicitly;
 
    switch (var->mode) {
    case ir_var_auto:
diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp
index 1b49736..ffff297 100644
--- a/src/glsl/ir.cpp
+++ b/src/glsl/ir.cpp
@@ -1586,7 +1586,8 @@ ir_variable::ir_variable(const struct glsl_type *type, const char *name,
 			 ir_variable_mode mode)
    : max_array_access(0), max_ifc_array_access(NULL),
      read_only(false), centroid(false), invariant(false),
-        mode(mode), interpolation(INTERP_QUALIFIER_NONE), atomic()
+     how_declared(ir_var_declared_normally), mode(mode),
+     interpolation(INTERP_QUALIFIER_NONE), atomic()
 {
    this->ir_type = ir_type_variable;
    this->type = type;
diff --git a/src/glsl/ir.h b/src/glsl/ir.h
index 7859702..4f775da 100644
--- a/src/glsl/ir.h
+++ b/src/glsl/ir.h
@@ -294,6 +294,34 @@ enum ir_variable_mode {
 };
 
 /**
+ * Enum keeping track of how a variable was declared.  For error checking of
+ * the gl_PerVertex redeclaration rules.
+ */
+enum ir_var_declaration_type {
+   /**
+    * Normal declaration (for most variables, this means an explicit
+    * declaration.  Exception: temporaries are always implicitly declared, but
+    * they still use ir_var_declared_normally).
+    *
+    * Note: an ir_variable that represents a named interface block uses
+    * ir_var_declared_normally.
+    */
+   ir_var_declared_normally = 0,
+
+   /**
+    * Variable was explicitly declared (or re-declared) in an unnamed
+    * interface block.
+    */
+   ir_var_declared_in_block,
+
+   /**
+    * Variable is an implicitly declared built-in that has not been explicitly
+    * re-declared by the shader.
+    */
+   ir_var_declared_implicitly,
+};
+
+/**
  * \brief Layout qualifiers for gl_FragDepth.
  *
  * The AMD/ARB_conservative_depth extensions allow gl_FragDepth to be redeclared
@@ -526,6 +554,14 @@ public:
    unsigned assigned:1;
 
    /**
+    * Enum indicating how the variable was declared.  See
+    * ir_var_declaration_type.
+    *
+    * This is used to detect certain kinds of illegal variable redeclarations.
+    */
+   unsigned how_declared:2;
+
+   /**
     * Storage class of the variable.
     *
     * \sa ir_variable_mode
diff --git a/src/glsl/ir_clone.cpp b/src/glsl/ir_clone.cpp
index b0f173a..40ed33a 100644
--- a/src/glsl/ir_clone.cpp
+++ b/src/glsl/ir_clone.cpp
@@ -68,6 +68,7 @@ ir_variable::clone(void *mem_ctx, struct hash_table *ht) const
    var->has_initializer = this->has_initializer;
    var->depth_layout = this->depth_layout;
    var->assigned = this->assigned;
+   var->how_declared = this->how_declared;
    var->used = this->used;
 
    var->num_state_slots = this->num_state_slots;
-- 
1.8.4.2



More information about the mesa-dev mailing list