glsl: add a parse check to check for the index layout qualifier
[mesa.git] / src / glsl / lower_named_interface_blocks.cpp
index d0d491d3db170d66ca3938f0de0245954255c4fb..114bb5811b45cd9f6a5585d741ed9118c2ce9258 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
 {
 public:
@@ -83,6 +118,8 @@ public:
    virtual void handle_rvalue(ir_rvalue **rvalue);
 };
 
+} /* anonymous namespace */
+
 void
 flatten_named_interface_blocks_declarations::run(exec_list *instructions)
 {
@@ -95,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;
 
@@ -104,54 +141,54 @@ flatten_named_interface_blocks_declarations::run(exec_list *instructions)
        * but, this will require changes to the other uniform block
        * support code.
        */
-      if (var->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",
-                            iface_t->name, field_name);
+            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 =
             (ir_variable *) hash_table_find(interface_namespace,
                                             iface_field_name);
          if (!found_var) {
             ir_variable *new_var;
-            if (array_t == NULL) {
-               char *var_name =
-                  ralloc_strdup(mem_ctx, iface_t->fields.structure[i].name);
+            char *var_name =
+               ralloc_strdup(mem_ctx, iface_t->fields.structure[i].name);
+            if (!var->type->is_array()) {
                new_var =
                   new(mem_ctx) ir_variable(iface_t->fields.structure[i].type,
                                            var_name,
-                                           (ir_variable_mode) var->mode);
+                                           (ir_variable_mode) var->data.mode);
+               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);
-               char *var_name =
-                  ralloc_asprintf(mem_ctx, "%s[%d]",
-                                  iface_t->fields.structure[i].name,
-                                  array_t->length);
+                  process_array_type(var->type, i);
                new_var =
                   new(mem_ctx) ir_variable(new_array_type,
                                            var_name,
-                                           (ir_variable_mode) var->mode);
+                                           (ir_variable_mode) var->data.mode);
+               new_var->data.from_named_ifc_block_array = 1;
             }
+            new_var->data.location = iface_t->fields.structure[i].location;
+            new_var->data.explicit_location = (new_var->data.location >= 0);
+            new_var->data.interpolation =
+               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->interface_type = iface_t;
+            new_var->init_interface_type(iface_t);
             hash_table_insert(interface_namespace, new_var,
                               iface_field_name);
             insert_pos->insert_after(new_var);
@@ -204,13 +241,15 @@ flatten_named_interface_blocks_declarations::handle_rvalue(ir_rvalue **rvalue)
     * but, this will require changes to the other uniform block
     * support code.
     */
-   if (var->mode == ir_var_uniform)
+   if (var->data.mode == ir_var_uniform || var->data.mode == ir_var_shader_storage)
       return;
 
-   if (var->interface_type != NULL) {
+   if (var->get_interface_type() != NULL) {
       char *iface_field_name =
-         ralloc_asprintf(mem_ctx, "%s.%s", var->interface_type->name,
-                         ir->field);
+         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 =
          (ir_variable *) hash_table_find(interface_namespace,
@@ -223,9 +262,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;
       }