[Mesa-dev] [PATCH 07/21] glsl: fix cross validation for explicit locations on structs and arrays

Timothy Arceri timothy.arceri at collabora.com
Mon Dec 21 22:01:54 PST 2015


---
 src/glsl/link_varyings.cpp | 53 ++++++++++++++++++++++++++++++++--------------
 1 file changed, 37 insertions(+), 16 deletions(-)

diff --git a/src/glsl/link_varyings.cpp b/src/glsl/link_varyings.cpp
index fd4b27c..06882fc 100644
--- a/src/glsl/link_varyings.cpp
+++ b/src/glsl/link_varyings.cpp
@@ -239,18 +239,24 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog,
          /* User-defined varyings with explicit locations are handled
           * differently because they do not need to have matching names.
           */
-         const unsigned idx = var->data.location - VARYING_SLOT_VAR0;
+         const glsl_type *type = get_varying_type(var, producer->Stage);
+         unsigned num_elements = type->count_attribute_slots(false);
+         unsigned idx = var->data.location - VARYING_SLOT_VAR0;
+         unsigned slot_limit = idx + num_elements;
 
-         if (explicit_locations[idx] != NULL) {
-            linker_error(prog,
+         while(idx < slot_limit) {
+            if (explicit_locations[idx] != NULL) {
+               linker_error(prog,
                          "%s shader has multiple outputs explicitly "
                          "assigned to location %d\n",
                          _mesa_shader_stage_to_string(producer->Stage),
                          idx);
-            return;
-         }
+               return;
+            }
 
-         explicit_locations[idx] = var;
+            explicit_locations[idx] = var;
+            idx++;
+         }
       }
    }
 
@@ -298,14 +304,25 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog,
          ir_variable *output = NULL;
          if (input->data.explicit_location
              && input->data.location >= VARYING_SLOT_VAR0) {
-            output = explicit_locations[input->data.location - VARYING_SLOT_VAR0];
 
-            if (output == NULL) {
-               linker_error(prog,
-                            "%s shader input `%s' with explicit location "
-                            "has no matching output\n",
-                            _mesa_shader_stage_to_string(consumer->Stage),
-                            input->name);
+            const glsl_type *type = get_varying_type(input, consumer->Stage);
+            unsigned num_elements = type->count_attribute_slots(false);
+            unsigned idx = input->data.location - VARYING_SLOT_VAR0;
+            unsigned slot_limit = idx + num_elements;
+
+            while(idx < slot_limit) {
+               output = explicit_locations[idx];
+
+               if (output == NULL ||
+                   input->data.location != output->data.location) {
+                  linker_error(prog,
+                               "%s shader input `%s' with explicit location "
+                               "has no matching output\n",
+                               _mesa_shader_stage_to_string(consumer->Stage),
+                               input->name);
+                  break;
+               }
+               idx++;
             }
          } else {
             output = parameters.get_variable(input->name);
@@ -1097,15 +1114,19 @@ varying_matches::assign_locations(struct gl_shader_program *prog,
 
       const ir_variable *var;
       const glsl_type *type;
+      bool is_vertex_input = false;
       if (matches[i].consumer_var) {
          var = matches[i].consumer_var;
          type = get_varying_type(var, consumer_stage);
+         is_vertex_input = false;
+         if (consumer_stage == MESA_SHADER_VERTEX)
+            is_vertex_input = true;
       } else {
          var = matches[i].producer_var;
          type = get_varying_type(var, producer_stage);
       }
 
-      unsigned num_elements =  type->count_attribute_slots();
+      unsigned num_elements =  type->count_attribute_slots(is_vertex_input);
       unsigned slot_end = this->disable_varying_packing ? 4 :
          type->without_array()->vector_elements;
       slot_end += *location - 1;
@@ -1533,8 +1554,8 @@ reserved_varying_slot(struct gl_shader *stage, ir_variable_mode io_mode)
 
       var_slot = var->data.location - VARYING_SLOT_VAR0;
 
-      unsigned num_elements =
-         get_varying_type(var, stage->Stage)->count_attribute_slots();
+      unsigned num_elements = get_varying_type(var, stage->Stage)
+         ->count_attribute_slots(stage->Stage == MESA_SHADER_VERTEX);
       for (unsigned i = 0; i < num_elements; i++) {
          if (var_slot >= 0 && var_slot < MAX_VARYING)
             slots |= 1u << var_slot;
-- 
2.4.3



More information about the mesa-dev mailing list