linker: Refactor code that gets an input matching an output
authorIan Romanick <ian.d.romanick@intel.com>
Thu, 3 Oct 2013 01:01:13 +0000 (18:01 -0700)
committerIan Romanick <ian.d.romanick@intel.com>
Fri, 2 May 2014 14:19:40 +0000 (07:19 -0700)
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
src/glsl/link_varyings.cpp
src/glsl/tests/varyings_test.cpp

index 8935c89..9b5ae3e 100644 (file)
@@ -1067,6 +1067,37 @@ populate_consumer_input_sets(void *mem_ctx, exec_list *ir,
    return true;
 }
 
+/**
+ * Find a variable from the consumer that "matches" the specified variable
+ *
+ * This function only finds inputs with names that match.  There is no
+ * validation (here) that the types, etc. are compatible.
+ */
+ir_variable *
+get_matching_input(void *mem_ctx,
+                   const ir_variable *output_var,
+                   hash_table *consumer_inputs,
+                   hash_table *consumer_interface_inputs)
+{
+   ir_variable *input_var;
+
+   if (output_var->get_interface_type() != NULL) {
+      char *const iface_field_name =
+         ralloc_asprintf(mem_ctx, "%s.%s",
+                         output_var->get_interface_type()->name,
+                         output_var->name);
+      input_var =
+         (ir_variable *) hash_table_find(consumer_interface_inputs,
+                                         iface_field_name);
+   } else {
+      input_var =
+         (ir_variable *) hash_table_find(consumer_inputs, output_var->name);
+   }
+
+   return (input_var == NULL || input_var->data.mode != ir_var_shader_in)
+      ? NULL : input_var;
+}
+
 }
 
 /**
@@ -1142,23 +1173,9 @@ assign_varying_locations(struct gl_context *ctx,
       tfeedback_candidate_generator g(mem_ctx, tfeedback_candidates);
       g.process(output_var);
 
-      ir_variable *input_var;
-      if (output_var->get_interface_type() != NULL) {
-         char *const iface_field_name =
-            ralloc_asprintf(mem_ctx, "%s.%s",
-                            output_var->get_interface_type()->name,
-                            output_var->name);
-         input_var =
-            (ir_variable *) hash_table_find(consumer_interface_inputs,
-                                            iface_field_name);
-      } else {
-         input_var =
-            (ir_variable *) hash_table_find(consumer_inputs, output_var->name);
-      }
-
-      if (input_var && input_var->data.mode != ir_var_shader_in)
-         input_var = NULL;
-
+      ir_variable *const input_var =
+         linker::get_matching_input(mem_ctx, output_var, consumer_inputs,
+                                    consumer_interface_inputs);
       if (input_var) {
          matches.record(output_var, input_var);
       }
index 76a08e3..1749112 100644 (file)
@@ -39,6 +39,12 @@ bool
 populate_consumer_input_sets(void *mem_ctx, exec_list *ir,
                              hash_table *consumer_inputs,
                              hash_table *consumer_interface_inputs);
+
+ir_variable *
+get_matching_input(void *mem_ctx,
+                   const ir_variable *output_var,
+                   hash_table *consumer_inputs,
+                   hash_table *consumer_interface_inputs);
 }
 
 class link_varyings : public ::testing::Test {
@@ -265,3 +271,77 @@ TEST_F(link_varyings, invalid_interface_input)
                                                     consumer_inputs,
                                                     consumer_interface_inputs));
 }
+
+TEST_F(link_varyings, interface_field_doesnt_match_noninterface)
+{
+   char *const iface_field_name = interface_field_name(simple_interface);
+
+   /* The input shader has a single input variable name "a.v"
+    */
+   ir_variable *const in_v =
+      new(mem_ctx) ir_variable(glsl_type::vec(4),
+                               iface_field_name,
+                               ir_var_shader_in);
+
+   ir.push_tail(in_v);
+
+   ASSERT_TRUE(linker::populate_consumer_input_sets(mem_ctx,
+                                                    &ir,
+                                                    consumer_inputs,
+                                                    consumer_interface_inputs));
+
+   /* Create an output variable, "v", that is part of an interface block named
+    * "a".  They should not match.
+    */
+   ir_variable *const out_v =
+      new(mem_ctx) ir_variable(simple_interface->fields.structure[0].type,
+                               simple_interface->fields.structure[0].name,
+                               ir_var_shader_in);
+
+   out_v->init_interface_type(simple_interface);
+
+   ir_variable *const match =
+      linker::get_matching_input(mem_ctx,
+                                 out_v,
+                                 consumer_inputs,
+                                 consumer_interface_inputs);
+
+   EXPECT_EQ(NULL, match);
+}
+
+TEST_F(link_varyings, interface_field_doesnt_match_noninterface_vice_versa)
+{
+   char *const iface_field_name = interface_field_name(simple_interface);
+
+   /* In input shader has a single variable, "v", that is part of an interface
+    * block named "a".
+    */
+   ir_variable *const in_v =
+      new(mem_ctx) ir_variable(simple_interface->fields.structure[0].type,
+                               simple_interface->fields.structure[0].name,
+                               ir_var_shader_in);
+
+   in_v->init_interface_type(simple_interface);
+
+   ir.push_tail(in_v);
+
+   ASSERT_TRUE(linker::populate_consumer_input_sets(mem_ctx,
+                                                    &ir,
+                                                    consumer_inputs,
+                                                    consumer_interface_inputs));
+
+   /* Create an output variable "a.v".  They should not match.
+    */
+   ir_variable *const out_v =
+      new(mem_ctx) ir_variable(glsl_type::vec(4),
+                               iface_field_name,
+                               ir_var_shader_out);
+
+   ir_variable *const match =
+      linker::get_matching_input(mem_ctx,
+                                 out_v,
+                                 consumer_inputs,
+                                 consumer_interface_inputs);
+
+   EXPECT_EQ(NULL, match);
+}