summaryrefslogtreecommitdiff
path: root/src/glsl/linker.cpp
diff options
context:
space:
mode:
authorIan Romanick <ian.d.romanick@intel.com>2010-10-07 17:21:22 -0700
committerIan Romanick <ian.d.romanick@intel.com>2010-10-08 14:21:23 -0700
commit68a4fc9d5a9dd3b61472451d659275531253b67d (patch)
tree2458cf332f819c61cbdc589e637cc0f171328892 /src/glsl/linker.cpp
parenteee68d3631813580a14fa51fda6f0c959279256c (diff)
glsl: Add linker support for explicit attribute locations
Diffstat (limited to 'src/glsl/linker.cpp')
-rw-r--r--src/glsl/linker.cpp33
1 files changed, 32 insertions, 1 deletions
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index bddf8788b4..c612fe5466 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)