Mesa (master): i965: Fix whole-structure/array assignment in new FS.

Eric Anholt anholt at kemper.freedesktop.org
Thu Sep 30 20:47:22 UTC 2010


Module: Mesa
Branch: master
Commit: 6f6542a483ec726538f8a4555bddaeb0be6b2146
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=6f6542a483ec726538f8a4555bddaeb0be6b2146

Author: Eric Anholt <eric at anholt.net>
Date:   Thu Sep 30 11:46:24 2010 -0700

i965: Fix whole-structure/array assignment in new FS.

We need to walk the type tree to get the right register types for
structure components.  Fixes glsl-fs-statevar-call.

---

 src/mesa/drivers/dri/i965/brw_fs.cpp |   76 ++++++++++++++++++++++++---------
 1 files changed, 55 insertions(+), 21 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp
index efbb4c6..efa0f21 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs.cpp
@@ -469,6 +469,8 @@ public:
    void emit_general_interpolation(ir_variable *ir);
    void emit_interpolation_setup();
    void emit_fb_writes();
+   void emit_assignment_writes(fs_reg &l, fs_reg &r,
+			       const glsl_type *type, bool predicated);
 
    struct brw_reg interp_reg(int location, int channel);
    int setup_uniform_values(int loc, const glsl_type *type);
@@ -1138,11 +1140,50 @@ fs_visitor::visit(ir_expression *ir)
 }
 
 void
+fs_visitor::emit_assignment_writes(fs_reg &l, fs_reg &r,
+				   const glsl_type *type, bool predicated)
+{
+   switch (type->base_type) {
+   case GLSL_TYPE_FLOAT:
+   case GLSL_TYPE_UINT:
+   case GLSL_TYPE_INT:
+   case GLSL_TYPE_BOOL:
+      for (unsigned int i = 0; i < type->components(); i++) {
+	 l.type = brw_type_for_base_type(type);
+	 r.type = brw_type_for_base_type(type);
+
+	 fs_inst *inst = emit(fs_inst(BRW_OPCODE_MOV, l, r));
+	 inst->predicated = predicated;
+
+	 l.reg_offset++;
+	 r.reg_offset++;
+      }
+      break;
+   case GLSL_TYPE_ARRAY:
+      for (unsigned int i = 0; i < type->length; i++) {
+	 emit_assignment_writes(l, r, type->fields.array, predicated);
+      }
+
+   case GLSL_TYPE_STRUCT:
+      for (unsigned int i = 0; i < type->length; i++) {
+	 emit_assignment_writes(l, r, type->fields.structure[i].type,
+				predicated);
+      }
+      break;
+
+   case GLSL_TYPE_SAMPLER:
+      break;
+
+   default:
+      assert(!"not reached");
+      break;
+   }
+}
+
+void
 fs_visitor::visit(ir_assignment *ir)
 {
    struct fs_reg l, r;
-   int i;
-   int write_mask;
    fs_inst *inst;
 
    /* FINISHME: arrays on the lhs */
@@ -1152,18 +1193,6 @@ fs_visitor::visit(ir_assignment *ir)
    ir->rhs->accept(this);
    r = this->result;
 
-   /* FINISHME: This should really set to the correct maximal writemask for each
-    * FINISHME: component written (in the loops below).  This case can only
-    * FINISHME: occur for matrices, arrays, and structures.
-    */
-   if (ir->write_mask == 0) {
-      assert(!ir->lhs->type->is_scalar() && !ir->lhs->type->is_vector());
-      write_mask = WRITEMASK_XYZW;
-   } else {
-      assert(ir->lhs->type->is_vector() || ir->lhs->type->is_scalar());
-      write_mask = ir->write_mask;
-   }
-
    assert(l.file != BAD_FILE);
    assert(r.file != BAD_FILE);
 
@@ -1174,14 +1203,19 @@ fs_visitor::visit(ir_assignment *ir)
       inst->conditional_mod = BRW_CONDITIONAL_NZ;
    }
 
-   for (i = 0; i < type_size(ir->lhs->type); i++) {
-      if (i >= 4 || (write_mask & (1 << i))) {
-	 inst = emit(fs_inst(BRW_OPCODE_MOV, l, r));
-	 if (ir->condition)
-	    inst->predicated = true;
-	 r.reg_offset++;
+   if (ir->lhs->type->is_scalar() ||
+       ir->lhs->type->is_vector()) {
+      for (int i = 0; i < ir->lhs->type->vector_elements; i++) {
+	 if (ir->write_mask & (1 << i)) {
+	    inst = emit(fs_inst(BRW_OPCODE_MOV, l, r));
+	    if (ir->condition)
+	       inst->predicated = true;
+	    r.reg_offset++;
+	 }
+	 l.reg_offset++;
       }
-      l.reg_offset++;
+   } else {
+      emit_assignment_writes(l, r, ir->lhs->type, ir->condition != NULL);
    }
 }
 




More information about the mesa-commit mailing list