[Mesa-dev] [PATCH 2/3] gallium: dereference are now handled by a separate visitor in glsl_to_tgsi

Vincent Lejeune vljn at ovi.com
Thu Dec 29 09:42:05 PST 2011


---
 src/mesa/state_tracker/st_glsl_to_tgsi.cpp |  455 ++++++++++++++++++----------
 1 files changed, 296 insertions(+), 159 deletions(-)

diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index 59ecb52..becb774 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -293,6 +293,46 @@ public:
    void push(class variable_storage *);
 };
 
+/**
+ * This visitor will retrieve offset and expression of indirect addressing
+ * from any ir_dereference*
+ */
+class glsl_to_tgsi_dereference_to_address : public ir_visitor {
+public:
+   unsigned offset;
+   struct {
+      unsigned stride;
+      ir_rvalue *expr;
+   } indirect_address_expression[8];
+   unsigned indirect_address_expression_count;
+   variable_store &store;
+   int &next_temp;
+   glsl_to_tgsi_dereference_to_address(variable_store&,int&);
+   void* mem_ctx;
+   gl_register_file file;
+   const glsl_type* type;
+
+   void visit(class ir_dereference_variable *);
+   void visit(class ir_dereference_array *);
+   void visit(class ir_dereference_record *);
+
+   void visit(ir_variable *);
+   void visit(ir_function_signature *);
+   void visit(ir_function *);
+   void visit(ir_expression *);
+   void visit(ir_texture *);
+   void visit(ir_swizzle *);
+   void visit(ir_assignment *);
+   void visit(ir_constant *);
+   void visit(ir_call *);
+   void visit(ir_discard *);
+   void visit(ir_if *);
+   void visit(ir_loop *);
+   void visit(ir_loop_jump *);
+   void visit(ir_return *);
+};
+
+
 class glsl_to_tgsi_visitor : public ir_visitor {
 public:
    glsl_to_tgsi_visitor();
@@ -354,6 +394,8 @@ public:
    virtual void visit(ir_if *);
    /*@}*/
 
+   void handle_dereference(ir_dereference *);
+
    st_src_reg result;
 
    /** List of variable_storage */
@@ -491,6 +533,212 @@ num_inst_src_regs(unsigned opcode)
    return info->is_tex ? info->num_src - 1 : info->num_src;
 }
 
+static int
+type_size(const struct glsl_type *type)
+{
+   unsigned int i;
+   int size;
+
+   switch (type->base_type) {
+   case GLSL_TYPE_UINT:
+   case GLSL_TYPE_INT:
+   case GLSL_TYPE_FLOAT:
+   case GLSL_TYPE_BOOL:
+      if (type->is_matrix()) {
+         return type->matrix_columns;
+      } else {
+         /* Regardless of size of vector, it gets a vec4. This is bad
+          * packing for things like floats, but otherwise arrays become a
+          * mess.  Hopefully a later pass over the code can pack scalars
+          * down if appropriate.
+          */
+         return 1;
+      }
+   case GLSL_TYPE_ARRAY:
+      assert(type->length > 0);
+      return type_size(type->fields.array) * type->length;
+   case GLSL_TYPE_STRUCT:
+      size = 0;
+      for (i = 0; i < type->length; i++) {
+         size += type_size(type->fields.structure[i].type);
+      }
+      return size;
+   case GLSL_TYPE_SAMPLER:
+      /* Samplers take up one slot in UNIFORMS[], but they're baked in
+       * at link time.
+       */
+      return 1;
+   default:
+      assert(0);
+      return 0;
+   }
+}
+
+glsl_to_tgsi_dereference_to_address::glsl_to_tgsi_dereference_to_address(variable_store &s, int &t):indirect_address_expression_count(0),store(s),next_temp(t)
+{
+
+}
+
+void glsl_to_tgsi_dereference_to_address::visit(ir_dereference_variable *ir)
+{
+   variable_storage *entry = store.find_variable_storage(ir->var);
+   ir_variable *var = ir->var;
+
+   if (!entry) {
+      switch (var->mode) {
+      case ir_var_uniform:
+         entry = new(mem_ctx) variable_storage(var, PROGRAM_UNIFORM,
+                                     var->location);
+         store.push(entry);
+         break;
+      case ir_var_in:
+      case ir_var_inout:
+         /* The linker assigns locations for varyings and attributes,
+          * including deprecated builtins (like gl_Color), user-assign
+          * generic attributes (glBindVertexLocation), and
+          * user-defined varyings.
+          *
+          * FINISHME: We would hit this path for function arguments.  Fix!
+          */
+         assert(var->location != -1);
+         entry = new(mem_ctx) variable_storage(var,
+                                               PROGRAM_INPUT,
+                                               var->location);
+         break;
+      case ir_var_out:
+         assert(var->location != -1);
+         entry = new(mem_ctx) variable_storage(var,
+                                               PROGRAM_OUTPUT,
+                                               var->location);
+         break;
+      case ir_var_system_value:
+         entry = new(mem_ctx) variable_storage(var,
+                                               PROGRAM_SYSTEM_VALUE,
+                                               var->location);
+         break;
+      case ir_var_auto:
+      case ir_var_temporary:
+         entry = new(mem_ctx) variable_storage(var, PROGRAM_TEMPORARY,
+                                     this->next_temp);
+         store.push(entry);
+
+         next_temp += type_size(var->type);
+         break;
+      }
+
+      if (!entry) {
+         printf("Failed to make storage for %s\n", var->name);
+         exit(1);
+      }
+   }
+   offset = entry->index;
+   file = entry->file;
+   type = var->type;
+   return;
+}
+
+void glsl_to_tgsi_dereference_to_address::visit(ir_dereference_record *ir)
+{
+   unsigned int i;
+   const glsl_type *struct_type = ir->record->type;
+   ir->record->accept(this);
+
+   for (i = 0; i < struct_type->length; i++) {
+      if (strcmp(struct_type->fields.structure[i].name, ir->field) == 0)
+         break;
+      offset += type_size(struct_type->fields.structure[i].type);
+   }
+   return;
+}
+
+void glsl_to_tgsi_dereference_to_address::visit(ir_dereference_array *ir)
+{
+   ir_constant *index;
+   int element_size = type_size(ir->type);
+   ir->array->accept(this);
+
+   index = ir->array_index->constant_expression_value();
+
+   if (index) {
+      offset += index->value.i[0] * element_size;
+   } else {
+      indirect_address_expression[indirect_address_expression_count].expr = ir->array_index;
+      indirect_address_expression[indirect_address_expression_count].stride = element_size;
+      indirect_address_expression_count++;
+   }
+   return;
+}
+
+void glsl_to_tgsi_dereference_to_address::visit(ir_function *)
+{
+   assert(0);
+}
+
+void glsl_to_tgsi_dereference_to_address::visit(ir_if *)
+{
+   assert(0);
+}
+
+void glsl_to_tgsi_dereference_to_address::visit(ir_variable *)
+{
+   assert(0);
+}
+
+void glsl_to_tgsi_dereference_to_address::visit(ir_discard *)
+{
+   assert(0);
+}
+
+void glsl_to_tgsi_dereference_to_address::visit(ir_function_signature *)
+{
+   assert(0);
+}
+
+void glsl_to_tgsi_dereference_to_address::visit(ir_expression *)
+{
+   assert(0);
+}
+
+void glsl_to_tgsi_dereference_to_address::visit(ir_call *)
+{
+   assert(0);
+}
+
+void glsl_to_tgsi_dereference_to_address::visit(ir_texture *)
+{
+   assert(0);
+}
+
+void glsl_to_tgsi_dereference_to_address::visit(ir_constant *)
+{
+   assert(0);
+}
+
+void glsl_to_tgsi_dereference_to_address::visit(ir_loop *)
+{
+   assert(0);
+}
+
+void glsl_to_tgsi_dereference_to_address::visit(ir_return *)
+{
+   assert(0);
+}
+
+void glsl_to_tgsi_dereference_to_address::visit(ir_loop_jump *)
+{
+   assert(0);
+}
+
+void glsl_to_tgsi_dereference_to_address::visit(ir_assignment *)
+{
+   assert(0);
+}
+
+void glsl_to_tgsi_dereference_to_address::visit(ir_swizzle *)
+{
+   assert(0);
+}
+
 glsl_to_tgsi_instruction *
 glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op,
         		 st_dst_reg dst,
@@ -931,46 +1179,7 @@ glsl_to_tgsi_visitor::st_src_reg_for_type(int type, int val)
       return st_src_reg_for_float(val);
 }
 
-static int
-type_size(const struct glsl_type *type)
-{
-   unsigned int i;
-   int size;
 
-   switch (type->base_type) {
-   case GLSL_TYPE_UINT:
-   case GLSL_TYPE_INT:
-   case GLSL_TYPE_FLOAT:
-   case GLSL_TYPE_BOOL:
-      if (type->is_matrix()) {
-         return type->matrix_columns;
-      } else {
-         /* Regardless of size of vector, it gets a vec4. This is bad
-          * packing for things like floats, but otherwise arrays become a
-          * mess.  Hopefully a later pass over the code can pack scalars
-          * down if appropriate.
-          */
-         return 1;
-      }
-   case GLSL_TYPE_ARRAY:
-      assert(type->length > 0);
-      return type_size(type->fields.array) * type->length;
-   case GLSL_TYPE_STRUCT:
-      size = 0;
-      for (i = 0; i < type->length; i++) {
-         size += type_size(type->fields.structure[i].type);
-      }
-      return size;
-   case GLSL_TYPE_SAMPLER:
-      /* Samplers take up one slot in UNIFORMS[], but they're baked in
-       * at link time.
-       */
-      return 1;
-   default:
-      assert(0);
-      return 0;
-   }
-}
 
 /**
  * In the initial pass of codegen, we assign temporary numbers to
@@ -1902,145 +2111,73 @@ glsl_to_tgsi_visitor::visit(ir_swizzle *ir)
 }
 
 void
-glsl_to_tgsi_visitor::visit(ir_dereference_variable *ir)
+glsl_to_tgsi_visitor::handle_dereference(ir_dereference *ir)
 {
-   variable_storage *entry = store.find_variable_storage(ir->var);
-   ir_variable *var = ir->var;
+   glsl_to_tgsi_dereference_to_address secondary_visitor(store,next_temp);
+   secondary_visitor.mem_ctx = mem_ctx;
+   ir->accept(&secondary_visitor);
 
-   if (!entry) {
-      switch (var->mode) {
-      case ir_var_uniform:
-         entry = new(mem_ctx) variable_storage(var, PROGRAM_UNIFORM,
-        				       var->location);
-         store.push(entry);
-         break;
-      case ir_var_in:
-      case ir_var_inout:
-         /* The linker assigns locations for varyings and attributes,
-          * including deprecated builtins (like gl_Color), user-assign
-          * generic attributes (glBindVertexLocation), and
-          * user-defined varyings.
-          *
-          * FINISHME: We would hit this path for function arguments.  Fix!
-          */
-         assert(var->location != -1);
-         entry = new(mem_ctx) variable_storage(var,
-                                               PROGRAM_INPUT,
-                                               var->location);
-         break;
-      case ir_var_out:
-         assert(var->location != -1);
-         entry = new(mem_ctx) variable_storage(var,
-                                               PROGRAM_OUTPUT,
-                                               var->location);
-         break;
-      case ir_var_system_value:
-         entry = new(mem_ctx) variable_storage(var,
-                                               PROGRAM_SYSTEM_VALUE,
-                                               var->location);
-         break;
-      case ir_var_auto:
-      case ir_var_temporary:
-         entry = new(mem_ctx) variable_storage(var, PROGRAM_TEMPORARY,
-        				       this->next_temp);
-         store.push(entry);
+   st_src_reg result = st_src_reg(secondary_visitor.file,secondary_visitor.offset,result.type);
 
-         next_temp += type_size(var->type);
-         break;
-      }
+   if (secondary_visitor.indirect_address_expression_count > 0) {
+      for (unsigned i = 0; i < secondary_visitor.indirect_address_expression_count; i++) {
+         secondary_visitor.indirect_address_expression[i].expr->accept(this);
+         unsigned element_size = secondary_visitor.indirect_address_expression[i].stride;
+         st_src_reg index_reg;
 
-      if (!entry) {
-         printf("Failed to make storage for %s\n", var->name);
-         exit(1);
+         if (i == 0) {
+            if (element_size == 1) {
+               index_reg = this->result;
+            } else {
+               index_reg = get_temp(native_integers ?
+                                    glsl_type::int_type : glsl_type::float_type);
+
+               emit(ir, TGSI_OPCODE_MUL, st_dst_reg(index_reg),
+                    this->result, st_src_reg_for_type(index_reg.type, element_size));
+            }
+         }
+         else {
+            if (element_size == 1) {
+               emit(ir, TGSI_OPCODE_ADD, st_dst_reg(index_reg),
+                    index_reg, this->result);
+            }
+            else {
+               emit(ir, TGSI_OPCODE_UMAD, st_dst_reg(index_reg),
+                     this->result, st_src_reg_for_type(index_reg.type,element_size),index_reg);
+            }
+         }
+         result.reladdr = ralloc(mem_ctx, st_src_reg);
+         memcpy(result.reladdr, &index_reg, sizeof(index_reg));
       }
    }
 
-   this->result = st_src_reg(entry->file, entry->index, var->type);
+   this->result = result;
+   /* If the type is smaller than a vec4, replicate the last channel out. */
+   if (secondary_visitor.type->is_scalar() || secondary_visitor.type->is_vector())
+      this->result.swizzle = swizzle_for_size(secondary_visitor.type->vector_elements);
+   else
+      this->result.swizzle = SWIZZLE_NOOP;
+
    if (!native_integers)
       this->result.type = GLSL_TYPE_FLOAT;
 }
 
 void
-glsl_to_tgsi_visitor::visit(ir_dereference_array *ir)
+glsl_to_tgsi_visitor::visit(ir_dereference_variable *ir)
 {
-   ir_constant *index;
-   st_src_reg src;
-   int element_size = type_size(ir->type);
-
-   index = ir->array_index->constant_expression_value();
-
-   ir->array->accept(this);
-   src = this->result;
-
-   if (index) {
-      src.index += index->value.i[0] * element_size;
-   } else {
-      /* Variable index array dereference.  It eats the "vec4" of the
-       * base of the array and an index that offsets the TGSI register
-       * index.
-       */
-      ir->array_index->accept(this);
-
-      st_src_reg index_reg;
-
-      if (element_size == 1) {
-         index_reg = this->result;
-      } else {
-         index_reg = get_temp(native_integers ?
-                              glsl_type::int_type : glsl_type::float_type);
-
-         emit(ir, TGSI_OPCODE_MUL, st_dst_reg(index_reg),
-              this->result, st_src_reg_for_type(index_reg.type, element_size));
-      }
-
-      /* If there was already a relative address register involved, add the
-       * new and the old together to get the new offset.
-       */
-      if (src.reladdr != NULL) {
-         st_src_reg accum_reg = get_temp(native_integers ?
-                                glsl_type::int_type : glsl_type::float_type);
-
-         emit(ir, TGSI_OPCODE_ADD, st_dst_reg(accum_reg),
-              index_reg, *src.reladdr);
-
-         index_reg = accum_reg;
-      }
-
-      src.reladdr = ralloc(mem_ctx, st_src_reg);
-      memcpy(src.reladdr, &index_reg, sizeof(index_reg));
-   }
-
-   /* If the type is smaller than a vec4, replicate the last channel out. */
-   if (ir->type->is_scalar() || ir->type->is_vector())
-      src.swizzle = swizzle_for_size(ir->type->vector_elements);
-   else
-      src.swizzle = SWIZZLE_NOOP;
+   handle_dereference(ir);
+}
 
-   this->result = src;
+void
+glsl_to_tgsi_visitor::visit(ir_dereference_array *ir)
+{
+   handle_dereference(ir);
 }
 
 void
 glsl_to_tgsi_visitor::visit(ir_dereference_record *ir)
 {
-   unsigned int i;
-   const glsl_type *struct_type = ir->record->type;
-   int offset = 0;
-
-   ir->record->accept(this);
-
-   for (i = 0; i < struct_type->length; i++) {
-      if (strcmp(struct_type->fields.structure[i].name, ir->field) == 0)
-         break;
-      offset += type_size(struct_type->fields.structure[i].type);
-   }
-
-   /* If the type is smaller than a vec4, replicate the last channel out. */
-   if (ir->type->is_scalar() || ir->type->is_vector())
-      this->result.swizzle = swizzle_for_size(ir->type->vector_elements);
-   else
-      this->result.swizzle = SWIZZLE_NOOP;
-
-   this->result.index += offset;
+   handle_dereference(ir);
 }
 
 /**
-- 
1.7.7



More information about the mesa-dev mailing list