[g3dvl] remove some unneeded Makefiles
[mesa.git] / src / glsl / lower_variable_index_to_cond_assign.cpp
index d9e6379c3907af8955ebfc62328f0f1bf2ed40e8..8eb1612f0a0da921fb6e3ee30b8bd56e211b4ef5 100644 (file)
@@ -42,6 +42,7 @@ struct assignment_generator
    ir_instruction* base_ir;
    ir_rvalue* array;
    bool is_write;
+   unsigned int write_mask;
    ir_variable* var;
 
    assignment_generator()
@@ -53,15 +54,19 @@ struct assignment_generator
       /* Just clone the rest of the deref chain when trying to get at the
        * underlying variable.
        */
-      void *mem_ctx = talloc_parent(base_ir);
-      ir_rvalue *element =
+      void *mem_ctx = ralloc_parent(base_ir);
+      ir_dereference *element =
         new(mem_ctx) ir_dereference_array(this->array->clone(mem_ctx, NULL),
                                           new(mem_ctx) ir_constant(i));
       ir_rvalue *variable = new(mem_ctx) ir_dereference_variable(this->var);
 
-      ir_assignment *assignment = (is_write)
-        ? new(mem_ctx) ir_assignment(element, variable, condition)
-        : new(mem_ctx) ir_assignment(variable, element, condition);
+      ir_assignment *assignment;
+      if (is_write) {
+        assignment = new(mem_ctx) ir_assignment(element, variable, condition,
+                                                write_mask);
+      } else {
+        assignment = new(mem_ctx) ir_assignment(variable, element, condition);
+      }
 
       list->push_tail(assignment);
    }
@@ -86,7 +91,7 @@ struct switch_generator
        linear_sequence_max_length(linear_sequence_max_length),
        condition_components(condition_components)
    {
-      this->mem_ctx = talloc_parent(index);
+      this->mem_ctx = ralloc_parent(index);
    }
 
    void linear_sequence(unsigned begin, unsigned end, exec_list *list)
@@ -117,7 +122,7 @@ struct switch_generator
            new(this->mem_ctx) ir_dereference_variable(index);
 
          if (comps) {
-           const ir_swizzle_mask m = { 0, 1, 2, 3, comps, false };
+           const ir_swizzle_mask m = { 0, 0, 0, 0, comps, false };
            broadcast_index = new(this->mem_ctx) ir_swizzle(broadcast_index, m);
         }
 
@@ -210,35 +215,92 @@ struct switch_generator
 
 class variable_index_to_cond_assign_visitor : public ir_rvalue_visitor {
 public:
-   variable_index_to_cond_assign_visitor()
+   variable_index_to_cond_assign_visitor(bool lower_input,
+                                        bool lower_output,
+                                        bool lower_temp,
+                                        bool lower_uniform)
    {
       this->progress = false;
+      this->lower_inputs = lower_input;
+      this->lower_outputs = lower_output;
+      this->lower_temps = lower_temp;
+      this->lower_uniforms = lower_uniform;
    }
 
    bool progress;
+   bool lower_inputs;
+   bool lower_outputs;
+   bool lower_temps;
+   bool lower_uniforms;
+
+   bool is_array_or_matrix(const ir_instruction *ir) const
+   {
+      return (ir->type->is_array() || ir->type->is_matrix());
+   }
+
+   bool needs_lowering(ir_dereference_array *deref) const
+   {
+      if (deref == NULL || deref->array_index->as_constant()
+         || !is_array_or_matrix(deref->array))
+        return false;
+
+      if (deref->array->ir_type == ir_type_constant)
+        return this->lower_temps;
+
+      const ir_variable *const var = deref->array->variable_referenced();
+      switch (var->mode) {
+      case ir_var_auto:
+      case ir_var_temporary:
+        return this->lower_temps;
+      case ir_var_uniform:
+        return this->lower_uniforms;
+      case ir_var_in:
+      case ir_var_const_in:
+        return (var->location == -1) ? this->lower_temps : this->lower_inputs;
+      case ir_var_out:
+        return (var->location == -1) ? this->lower_temps : this->lower_outputs;
+      case ir_var_inout:
+        return this->lower_temps;
+      }
+
+      assert(!"Should not get here.");
+      return false;
+   }
 
    ir_variable *convert_dereference_array(ir_dereference_array *orig_deref,
-                                         ir_rvalue* value)
+                                         ir_assignment* orig_assign)
    {
-      unsigned length;
-      if (orig_deref->array->type->is_array())
-         length = orig_deref->array->type->length;
-      else if (orig_deref->array->type->is_matrix())
-         length = orig_deref->array->type->matrix_columns;
-      else
-         assert(0);
+      assert(is_array_or_matrix(orig_deref->array));
+
+      const unsigned length = (orig_deref->array->type->is_array())
+         ? orig_deref->array->type->length
+         : orig_deref->array->type->matrix_columns;
 
-      void *const mem_ctx = talloc_parent(base_ir);
-      ir_variable *var =
-        new(mem_ctx) ir_variable(orig_deref->type, "dereference_array_value",
-                                 ir_var_temporary);
-      base_ir->insert_before(var);
+      void *const mem_ctx = ralloc_parent(base_ir);
+
+      /* Temporary storage for either the result of the dereference of
+       * the array, or the RHS that's being assigned into the
+       * dereference of the array.
+       */
+      ir_variable *var;
+
+      if (orig_assign) {
+        var = new(mem_ctx) ir_variable(orig_assign->rhs->type,
+                                       "dereference_array_value",
+                                       ir_var_temporary);
+        base_ir->insert_before(var);
 
-      if (value) {
         ir_dereference *lhs = new(mem_ctx) ir_dereference_variable(var);
-        ir_assignment *assign = new(mem_ctx) ir_assignment(lhs, value, NULL);
+        ir_assignment *assign = new(mem_ctx) ir_assignment(lhs,
+                                                           orig_assign->rhs,
+                                                           NULL);
 
          base_ir->insert_before(assign);
+      } else {
+        var = new(mem_ctx) ir_variable(orig_deref->type,
+                                       "dereference_array_value",
+                                       ir_var_temporary);
+        base_ir->insert_before(var);
       }
 
       /* Store the index to a temporary to avoid reusing its tree. */
@@ -256,7 +318,12 @@ public:
       ag.array = orig_deref->array;
       ag.base_ir = base_ir;
       ag.var = var;
-      ag.is_write = !!value;
+      if (orig_assign) {
+        ag.is_write = true;
+        ag.write_mask = orig_assign->write_mask;
+      } else {
+        ag.is_write = false;
+      }
 
       switch_generator sg(ag, index, 4, 4);
 
@@ -273,12 +340,10 @@ public:
          return;
 
       ir_dereference_array* orig_deref = (*pir)->as_dereference_array();
-      if (orig_deref && !orig_deref->array_index->as_constant()
-            && (orig_deref->array->type->is_array()
-               || orig_deref->array->type->is_matrix())) {
+      if (needs_lowering(orig_deref)) {
          ir_variable* var = convert_dereference_array(orig_deref, 0);
          assert(var);
-         *pir = new(talloc_parent(base_ir)) ir_dereference_variable(var);
+         *pir = new(ralloc_parent(base_ir)) ir_dereference_variable(var);
          this->progress = true;
       }
    }
@@ -290,10 +355,8 @@ public:
 
       ir_dereference_array *orig_deref = ir->lhs->as_dereference_array();
 
-      if (orig_deref && !orig_deref->array_index->as_constant()
-            && (orig_deref->array->type->is_array()
-               || orig_deref->array->type->is_matrix())) {
-         convert_dereference_array(orig_deref, ir->rhs);
+      if (needs_lowering(orig_deref)) {
+         convert_dereference_array(orig_deref, ir);
          ir->remove();
          this->progress = true;
       }
@@ -303,9 +366,16 @@ public:
 };
 
 bool
-lower_variable_index_to_cond_assign(exec_list *instructions)
+lower_variable_index_to_cond_assign(exec_list *instructions,
+                                   bool lower_input,
+                                   bool lower_output,
+                                   bool lower_temp,
+                                   bool lower_uniform)
 {
-   variable_index_to_cond_assign_visitor v;
+   variable_index_to_cond_assign_visitor v(lower_input,
+                                          lower_output,
+                                          lower_temp,
+                                          lower_uniform);
 
    visit_list_elements(&v, instructions);