Mesa (master): glsl: Add linker support for explicit attribute locations

Ian Romanick idr at kemper.freedesktop.org
Fri Oct 8 21:25:00 UTC 2010


Module: Mesa
Branch: master
Commit: 68a4fc9d5a9dd3b61472451d659275531253b67d
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=68a4fc9d5a9dd3b61472451d659275531253b67d

Author: Ian Romanick <ian.d.romanick at intel.com>
Date:   Thu Oct  7 17:21:22 2010 -0700

glsl: Add linker support for explicit attribute locations

---

 src/glsl/ast_to_hir.cpp  |   18 +++++++++++++++---
 src/glsl/ir_variable.cpp |    1 +
 src/glsl/linker.cpp      |   33 ++++++++++++++++++++++++++++++++-
 3 files changed, 48 insertions(+), 4 deletions(-)

diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
index 47fe7a3..6e8a1fd 100644
--- a/src/glsl/ast_to_hir.cpp
+++ b/src/glsl/ast_to_hir.cpp
@@ -1668,9 +1668,21 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
 			  string);
       } else {
 	 var->explicit_location = true;
-	 var->location = (state->target == vertex_shader)
-	    ? (qual->location + VERT_ATTRIB_GENERIC0)
-	    : (qual->location + FRAG_RESULT_DATA0);
+
+	 /* This bit of silliness is needed because invalid explicit locations
+	  * are supposed to be flagged during linking.  Small negative values
+	  * biased by VERT_ATTRIB_GENERIC0 or FRAG_RESULT_DATA0 could alias
+	  * built-in values (e.g., -16+VERT_ATTRIB_GENERIC0 = VERT_ATTRIB_POS).
+	  * The linker needs to be able to differentiate these cases.  This
+	  * ensures that negative values stay negative.
+	  */
+	 if (qual->location >= 0) {
+	    var->location = (state->target == vertex_shader)
+	       ? (qual->location + VERT_ATTRIB_GENERIC0)
+	       : (qual->location + FRAG_RESULT_DATA0);
+	 } else {
+	    var->location = qual->location;
+	 }
       }
    }
 
diff --git a/src/glsl/ir_variable.cpp b/src/glsl/ir_variable.cpp
index 1eff740..ddc3bb0 100644
--- a/src/glsl/ir_variable.cpp
+++ b/src/glsl/ir_variable.cpp
@@ -52,6 +52,7 @@ add_variable(const char *name, enum ir_variable_mode mode, int slot,
    }
 
    var->location = slot;
+   var->explicit_location = (slot >= 0);
 
    /* Once the variable is created an initialized, add it to the symbol table
     * and add the declaration to the IR stream.
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index bddf878..c612fe5 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -191,7 +191,7 @@ invalidate_variable_locations(gl_shader *sh, enum ir_variable_mode mode,
 
       /* Only assign locations for generic attributes / varyings / etc.
        */
-      if (var->location >= generic_base)
+      if ((var->location >= generic_base) && !var->explicit_location)
 	  var->location = -1;
    }
 }
@@ -365,6 +365,19 @@ cross_validate_globals(struct gl_shader_program *prog,
 	       }
 	    }
 
+	    if (var->explicit_location) {
+	       if (existing->explicit_location
+		   && (var->location != existing->location)) {
+		     linker_error_printf(prog, "explicit locations for %s "
+					 "`%s' have differing values\n",
+					 mode_string(var), var->name);
+		     return false;
+	       }
+
+	       existing->location = var->location;
+	       existing->explicit_location = true;
+	    }
+
 	    /* FINISHME: Handle non-constant initializers.
 	     */
 	    if (var->constant_value != NULL) {
@@ -1186,6 +1199,24 @@ assign_attribute_locations(gl_shader_program *prog, unsigned max_attribute_index
       if ((var == NULL) || (var->mode != ir_var_in))
 	 continue;
 
+      if (var->explicit_location) {
+	 const unsigned slots = count_attribute_slots(var->type);
+	 const unsigned use_mask = (1 << slots) - 1;
+	 const int attr = var->location - VERT_ATTRIB_GENERIC0;
+
+	 if ((var->location >= (int)(max_attribute_index + VERT_ATTRIB_GENERIC0))
+	     || (var->location < 0)) {
+	    linker_error_printf(prog,
+				"invalid explicit location %d specified for "
+				"`%s'\n",
+				(var->location < 0) ? var->location : attr,
+				var->name);
+	    return false;
+	 } else if (var->location >= VERT_ATTRIB_GENERIC0) {
+	    used_locations |= (use_mask << attr);
+	 }
+      }
+
       /* The location was explicitly assigned, nothing to do here.
        */
       if (var->location != -1)




More information about the mesa-commit mailing list