glsl: Refactor a bunch of the code out of cross_validate_outputs_to_inputs
[mesa.git] / src / glsl / lower_named_interface_blocks.cpp
index f3a2ad5d7def72e821903b02dd603380ccb9cc04..20196a35648e0a6bcbc04987b645e031a2549cb3 100644 (file)
@@ -72,7 +72,8 @@ public:
    hash_table *interface_namespace;
 
    flatten_named_interface_blocks_declarations(void *mem_ctx)
-      : mem_ctx(mem_ctx)
+      : mem_ctx(mem_ctx),
+        interface_namespace(NULL)
    {
    }
 
@@ -106,22 +107,47 @@ flatten_named_interface_blocks_declarations::run(exec_list *instructions)
       if (var->mode == ir_var_uniform)
          continue;
 
-      const glsl_type *const t = var->type;
+      const glsl_type * iface_t = var->type;
+      const glsl_type * array_t = NULL;
       exec_node *insert_pos = var;
-      char *iface_field_name;
-      for (unsigned i = 0; i < t->length; i++) {
-         iface_field_name = ralloc_asprintf(mem_ctx, "%s.%s", t->name,
-                                            t->fields.structure[i].name);
+
+      if (iface_t->is_array()) {
+         array_t = iface_t;
+         iface_t = array_t->fields.array;
+      }
+
+      assert (iface_t->is_interface());
+
+      for (unsigned i = 0; i < iface_t->length; i++) {
+         const char * field_name = iface_t->fields.structure[i].name;
+         char *iface_field_name =
+            ralloc_asprintf(mem_ctx, "%s.%s",
+                            iface_t->name, field_name);
 
          ir_variable *found_var =
             (ir_variable *) hash_table_find(interface_namespace,
                                             iface_field_name);
          if (!found_var) {
-            ir_variable *new_var =
-               new(mem_ctx) ir_variable(t->fields.structure[i].type,
-                                        ralloc_strdup(mem_ctx, t->fields.structure[i].name),
-                                        (ir_variable_mode) var->mode);
-            new_var->interface_type = t;
+            ir_variable *new_var;
+            char *var_name =
+               ralloc_strdup(mem_ctx, iface_t->fields.structure[i].name);
+            if (array_t == NULL) {
+               new_var =
+                  new(mem_ctx) ir_variable(iface_t->fields.structure[i].type,
+                                           var_name,
+                                           (ir_variable_mode) var->mode);
+            } else {
+               const glsl_type *new_array_type =
+                  glsl_type::get_array_instance(
+                     iface_t->fields.structure[i].type,
+                     array_t->length);
+               new_var =
+                  new(mem_ctx) ir_variable(new_array_type,
+                                           var_name,
+                                           (ir_variable_mode) var->mode);
+            }
+
+            new_var->interface_type = iface_t;
             hash_table_insert(interface_namespace, new_var,
                               iface_field_name);
             insert_pos->insert_after(new_var);
@@ -164,6 +190,8 @@ flatten_named_interface_blocks_declarations::handle_rvalue(ir_rvalue **rvalue)
       return;
 
    ir_variable *var = ir->variable_referenced();
+   if (var == NULL)
+      return;
 
    if (!var->is_interface_instance())
       return;
@@ -184,9 +212,19 @@ flatten_named_interface_blocks_declarations::handle_rvalue(ir_rvalue **rvalue)
          (ir_variable *) hash_table_find(interface_namespace,
                                          iface_field_name);
       assert(found_var);
+
       ir_dereference_variable *deref_var =
          new(mem_ctx) ir_dereference_variable(found_var);
-      *rvalue = deref_var;
+
+      ir_dereference_array *deref_array =
+         ir->record->as_dereference_array();
+      if (deref_array != NULL) {
+         *rvalue =
+            new(mem_ctx) ir_dereference_array(deref_var,
+                                              deref_array->array_index);
+      } else {
+         *rvalue = deref_var;
+      }
    }
 }