nir/spirv: Move CF emit code into vtn_cfg.c
[mesa.git] / src / glsl / lower_named_interface_blocks.cpp
index 04e0d36e675b2cca038867e77df6c2450f6db455..f29eba4f75f0b665f65ebfaf1a39d3b41aae2826 100644 (file)
 #include "ir_rvalue_visitor.h"
 #include "program/hash_table.h"
 
+static const glsl_type *
+process_array_type(const glsl_type *type, unsigned idx)
+{
+   const glsl_type *element_type = type->fields.array;
+   if (element_type->is_array()) {
+      const glsl_type *new_array_type = process_array_type(element_type, idx);
+      return glsl_type::get_array_instance(new_array_type, type->length);
+   } else {
+      return glsl_type::get_array_instance(
+         element_type->fields.structure[idx].type, type->length);
+   }
+}
+
+static ir_rvalue *
+process_array_ir(void * const mem_ctx,
+                 ir_dereference_array *deref_array_prev,
+                 ir_rvalue *deref_var)
+{
+   ir_dereference_array *deref_array =
+      deref_array_prev->array->as_dereference_array();
+
+   if (deref_array == NULL) {
+      return new(mem_ctx) ir_dereference_array(deref_var,
+                                               deref_array_prev->array_index);
+   } else {
+      deref_array = (ir_dereference_array *) process_array_ir(mem_ctx,
+                                                              deref_array,
+                                                              deref_var);
+      return new(mem_ctx) ir_dereference_array(deref_array,
+                                               deref_array_prev->array_index);
+   }
+}
+
 namespace {
 
 class flatten_named_interface_blocks_declarations : public ir_rvalue_visitor
@@ -99,8 +132,8 @@ flatten_named_interface_blocks_declarations::run(exec_list *instructions)
     * The interface block variables are stored in the interface_namespace
     * hash table so they can be used in the second pass.
     */
-   foreach_list_safe(node, instructions) {
-      ir_variable *var = ((ir_instruction *) node)->as_variable();
+   foreach_in_list_safe(ir_instruction, node, instructions) {
+      ir_variable *var = node->as_variable();
       if (!var || !var->is_interface_instance())
          continue;
 
@@ -108,24 +141,20 @@ flatten_named_interface_blocks_declarations::run(exec_list *instructions)
        * but, this will require changes to the other uniform block
        * support code.
        */
-      if (var->data.mode == ir_var_uniform)
+      if (var->data.mode == ir_var_uniform ||
+          var->data.mode == ir_var_shader_storage)
          continue;
 
-      const glsl_type * iface_t = var->type;
-      const glsl_type * array_t = NULL;
+      const glsl_type * iface_t = var->type->without_array();
       exec_node *insert_pos = var;
 
-      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.%s",
+            ralloc_asprintf(mem_ctx, "%s %s.%s.%s",
+                            var->data.mode == ir_var_shader_in ? "in" : "out",
                             iface_t->name, var->name, field_name);
 
          ir_variable *found_var =
@@ -135,7 +164,7 @@ flatten_named_interface_blocks_declarations::run(exec_list *instructions)
             ir_variable *new_var;
             char *var_name =
                ralloc_strdup(mem_ctx, iface_t->fields.structure[i].name);
-            if (array_t == NULL) {
+            if (!var->type->is_array()) {
                new_var =
                   new(mem_ctx) ir_variable(iface_t->fields.structure[i].type,
                                            var_name,
@@ -143,9 +172,7 @@ flatten_named_interface_blocks_declarations::run(exec_list *instructions)
                new_var->data.from_named_ifc_block_nonarray = 1;
             } else {
                const glsl_type *new_array_type =
-                  glsl_type::get_array_instance(
-                     iface_t->fields.structure[i].type,
-                     array_t->length);
+                  process_array_type(var->type, i);
                new_var =
                   new(mem_ctx) ir_variable(new_array_type,
                                            var_name,
@@ -158,6 +185,9 @@ flatten_named_interface_blocks_declarations::run(exec_list *instructions)
                iface_t->fields.structure[i].interpolation;
             new_var->data.centroid = iface_t->fields.structure[i].centroid;
             new_var->data.sample = iface_t->fields.structure[i].sample;
+            new_var->data.patch = iface_t->fields.structure[i].patch;
+            new_var->data.stream = var->data.stream;
+            new_var->data.how_declared = var->data.how_declared;
 
             new_var->init_interface_type(iface_t);
             hash_table_insert(interface_namespace, new_var,
@@ -212,12 +242,14 @@ flatten_named_interface_blocks_declarations::handle_rvalue(ir_rvalue **rvalue)
     * but, this will require changes to the other uniform block
     * support code.
     */
-   if (var->data.mode == ir_var_uniform)
+   if (var->data.mode == ir_var_uniform || var->data.mode == ir_var_shader_storage)
       return;
 
    if (var->get_interface_type() != NULL) {
       char *iface_field_name =
-         ralloc_asprintf(mem_ctx, "%s.%s.%s", var->get_interface_type()->name,
+         ralloc_asprintf(mem_ctx, "%s %s.%s.%s",
+                         var->data.mode == ir_var_shader_in ? "in" : "out",
+                         var->get_interface_type()->name,
                          var->name, ir->field);
       /* Find the variable in the set of flattened interface blocks */
       ir_variable *found_var =
@@ -231,9 +263,8 @@ flatten_named_interface_blocks_declarations::handle_rvalue(ir_rvalue **rvalue)
       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);
+         *rvalue = process_array_ir(mem_ctx, deref_array,
+                                    (ir_rvalue *)deref_var);
       } else {
          *rvalue = deref_var;
       }