glsl linker: support arrays of interface block instances
authorJordan Justen <jordan.l.justen@intel.com>
Sun, 17 Mar 2013 09:04:56 +0000 (02:04 -0700)
committerJordan Justen <jordan.l.justen@intel.com>
Thu, 23 May 2013 16:37:12 +0000 (09:37 -0700)
With this change we now support interface block arrays.
For example, cases like this:

out block_name {
    float f;
} block_instance[2];

This allows Mesa to pass the piglit glsl-1.50 test:
* execution/interface-blocks-complex-vs-fs.shader_test

Signed-off-by: Jordan Justen <jordan.l.justen@intel.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
src/glsl/lower_named_interface_blocks.cpp

index f3a2ad5d7def72e821903b02dd603380ccb9cc04..eba667a8bfeb7dd9d83393419452017d0ab5287f 100644 (file)
@@ -106,22 +106,51 @@ 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;
+            if (array_t == NULL) {
+               char *var_name =
+                  ralloc_strdup(mem_ctx, iface_t->fields.structure[i].name);
+               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);
+               char *var_name =
+                  ralloc_asprintf(mem_ctx, "%s[%d]",
+                                  iface_t->fields.structure[i].name,
+                                  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);
@@ -184,9 +213,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;
+      }
    }
 }