ir_to_mesa: Handle swizzles on LHS of assignment (writemasks).
authorEric Anholt <eric@anholt.net>
Thu, 6 May 2010 16:25:56 +0000 (09:25 -0700)
committerEric Anholt <eric@anholt.net>
Thu, 24 Jun 2010 22:05:19 +0000 (15:05 -0700)
ir_to_mesa.cpp
ir_to_mesa.h
mesa_codegen.brg

index 77ca6df73c709d21c40bbeb2b84c2d3a34062a95..3976f437f93df1732abbea292c7408f0417413c3 100644 (file)
@@ -139,6 +139,16 @@ ir_to_mesa_emit_scalar_op1(struct mbtree *tree, enum prog_opcode op,
    }
 }
 
+static void
+ir_to_mesa_set_tree_reg(struct mbtree *tree, int file, int index)
+{
+   tree->dst_reg.file = file;
+   tree->dst_reg.index = index;
+
+   tree->src_reg.file = file;
+   tree->src_reg.index = index;
+}
+
 struct mbtree *
 ir_to_mesa_visitor::create_tree(int op,
                                ir_instruction *ir,
@@ -153,6 +163,8 @@ ir_to_mesa_visitor::create_tree(int op,
    tree->right = right;
    tree->v = this;
    tree->src_reg.swizzle = SWIZZLE_XYZW;
+   tree->dst_reg.writemask = WRITEMASK_XYZW;
+   ir_to_mesa_set_tree_reg(tree, PROGRAM_UNDEFINED, 0);
    tree->ir = ir;
 
    return tree;
@@ -167,8 +179,7 @@ ir_to_mesa_visitor::create_tree(int op,
 void
 ir_to_mesa_visitor::get_temp(struct mbtree *tree)
 {
-   tree->src_reg.file = PROGRAM_TEMPORARY;
-   tree->src_reg.index = this->next_temp++;
+   ir_to_mesa_set_tree_reg(tree, PROGRAM_TEMPORARY, this->next_temp++);
 }
 
 void
@@ -180,8 +191,7 @@ ir_to_mesa_visitor::get_temp_for_var(ir_variable *var, struct mbtree *tree)
       entry = (temp_entry *)iter.get();
 
       if (entry->var == var) {
-        tree->src_reg.file = entry->file;
-        tree->src_reg.index = entry->index;
+        ir_to_mesa_set_tree_reg(tree, entry->file, entry->index);
         return;
       }
    }
@@ -189,8 +199,7 @@ ir_to_mesa_visitor::get_temp_for_var(ir_variable *var, struct mbtree *tree)
    entry = new temp_entry(var, PROGRAM_TEMPORARY, this->next_temp++);
    this->variable_storage.push_tail(entry);
 
-   tree->src_reg.file = entry->file;
-   tree->src_reg.index = entry->index;
+   ir_to_mesa_set_tree_reg(tree, entry->file, entry->index);
 }
 
 static void
@@ -351,7 +360,10 @@ ir_to_mesa_visitor::visit(ir_swizzle *ir)
    int i;
    int swizzle[4];
 
-   /* FINISHME: Handle swizzles on the left side of an assignment. */
+   /* Note that this is only swizzles in expressions, not those on the left
+    * hand side of an assignment, which do write masking.  See ir_assignment
+    * for that.
+    */
 
    ir->val->accept(this);
    assert(this->result);
@@ -410,12 +422,11 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir)
     */
    assert(!var->type->is_matrix());
 
-   tree = this->create_tree(MB_TERM_reference_vec4, NULL, NULL);
+   tree = this->create_tree(MB_TERM_reference_vec4, ir, NULL, NULL);
 
    if (strncmp(var->name, "gl_", 3) == 0) {
       if (strcmp(var->name, "gl_FragColor") == 0) {
-        tree->src_reg.file = PROGRAM_INPUT;
-        tree->src_reg.index = FRAG_ATTRIB_COL0;
+        ir_to_mesa_set_tree_reg(tree, PROGRAM_INPUT, FRAG_ATTRIB_COL0);
       } else {
         assert(0);
       }
@@ -442,17 +453,14 @@ ir_to_mesa_visitor::visit(ir_dereference_array *ir)
 
    ir_variable *var = ir->array->as_variable();
    ir_constant *index = ir->array_index->constant_expression_value();
-   char *name;
 
    assert(var);
    assert(index);
    assert(strcmp(var->name, "gl_TexCoord") == 0);
 
-   asprintf(&name, "fragment.texcoord[%d]", index->value.i[0]);
    tree = this->create_tree(MB_TERM_reference_vec4, ir, NULL, NULL);
-   tree->src_reg.file = PROGRAM_INPUT;
-   tree->src_reg.index = FRAG_ATTRIB_TEX0 + index->value.i[0];
-   tree->reg_name = name;
+   ir_to_mesa_set_tree_reg(tree, PROGRAM_INPUT,
+                          FRAG_ATTRIB_TEX0 + index->value.i[0]);
 
    /* If the type is smaller than a vec4, replicate the last channel out. */
    tree->src_reg.swizzle = size_swizzles[ir->type->vector_elements - 1];
@@ -460,6 +468,34 @@ ir_to_mesa_visitor::visit(ir_dereference_array *ir)
    this->result = tree;
 }
 
+static struct mbtree *
+get_assignment_lhs(ir_instruction *ir, ir_to_mesa_visitor *v)
+{
+   struct mbtree *tree = NULL;
+   ir_dereference *deref;
+   ir_swizzle *swiz;
+
+   if ((deref = ir->as_dereference())) {
+      ir->accept(v);
+      tree = v->result;
+   } else if ((swiz = ir->as_swizzle())) {
+      tree = get_assignment_lhs(swiz->val, v);
+      tree->dst_reg.writemask = 0;
+      if (swiz->mask.num_components >= 1)
+        tree->dst_reg.writemask |= (1 << swiz->mask.x);
+      if (swiz->mask.num_components >= 2)
+        tree->dst_reg.writemask |= (1 << swiz->mask.y);
+      if (swiz->mask.num_components >= 3)
+        tree->dst_reg.writemask |= (1 << swiz->mask.z);
+      if (swiz->mask.num_components >= 4)
+        tree->dst_reg.writemask |= (1 << swiz->mask.w);
+   }
+
+   assert(tree);
+
+   return tree;
+}
+
 void
 ir_to_mesa_visitor::visit(ir_dereference_record *ir)
 {
@@ -472,8 +508,8 @@ ir_to_mesa_visitor::visit(ir_assignment *ir)
 {
    struct mbtree *l, *r, *t;
 
-   ir->lhs->accept(this);
-   l = this->result;
+   l = get_assignment_lhs(ir->lhs, this);
+
    ir->rhs->accept(this);
    r = this->result;
    assert(l);
@@ -504,8 +540,7 @@ ir_to_mesa_visitor::visit(ir_constant *ir)
     */
    /* FINISHME: Do something with the constant values for now.
     */
-   tree->src_reg.file = PROGRAM_CONSTANT;
-   tree->src_reg.index = this->next_constant++;
+   ir_to_mesa_set_tree_reg(tree, PROGRAM_CONSTANT, this->next_constant++);
    tree->src_reg.swizzle = SWIZZLE_NOOP;
 
    this->result = tree;
index c8ceb4c1715fdda34f7ef06db8228b8763931bc1..00328e5fab2c288d7a3ee66221af04aa17d83ac0 100644 (file)
@@ -69,6 +69,8 @@ struct mbtree {
    /** Pointer to the ir source this tree came from for debugging */
    ir_instruction *ir;
 
+   ir_to_mesa_dst_reg dst_reg;
+
    /**
     * This is the representation of this tree node's results as a
     * source register for its consumer.
index 3191a44c2103923e8fd6dac567c33adceb27d64b..b117aff0f6be752e1cc2707166f70e133d23bf10 100644 (file)
@@ -105,7 +105,7 @@ vec4: reference_vec4 0
 stmt: assign(vec4, vec4) 1
 {
        ir_to_mesa_emit_op1(tree, OPCODE_MOV,
-                           ir_to_mesa_dst_reg_from_src(tree->left->src_reg),
+                           tree->left->dst_reg,
                            tree->right->src_reg);
 }
 
@@ -126,14 +126,14 @@ vec4: swizzle_vec4(vec4) 1
        reg.swizzle = MAKE_SWIZZLE4(swiz[0], swiz[1], swiz[2], swiz[3]);
 
        ir_to_mesa_emit_op1(tree, OPCODE_MOV,
-                          ir_to_mesa_dst_reg_from_src(tree->src_reg),
+                          tree->dst_reg,
                           reg);
 }
 
 vec4: add_vec4_vec4(vec4, vec4) 1
 {
        ir_to_mesa_emit_op2(tree, OPCODE_ADD,
-                           ir_to_mesa_dst_reg_from_src(tree->src_reg),
+                           tree->dst_reg,
                            tree->left->src_reg,
                            tree->right->src_reg);
 }
@@ -141,7 +141,7 @@ vec4: add_vec4_vec4(vec4, vec4) 1
 vec4: sub_vec4_vec4(vec4, vec4) 1
 {
        ir_to_mesa_emit_op2(tree, OPCODE_SUB,
-                           ir_to_mesa_dst_reg_from_src(tree->src_reg),
+                           tree->dst_reg,
                            tree->left->src_reg,
                            tree->right->src_reg);
 }
@@ -149,7 +149,7 @@ vec4: sub_vec4_vec4(vec4, vec4) 1
 vec4: mul_vec4_vec4(vec4, vec4) 1
 {
        ir_to_mesa_emit_op2(tree, OPCODE_MUL,
-                           ir_to_mesa_dst_reg_from_src(tree->src_reg),
+                           tree->dst_reg,
                            tree->left->src_reg,
                            tree->right->src_reg);
 }
@@ -157,7 +157,7 @@ vec4: mul_vec4_vec4(vec4, vec4) 1
 vec4: dp4_vec4_vec4(vec4, vec4) 1
 {
        ir_to_mesa_emit_op2(tree, OPCODE_DP4,
-                           ir_to_mesa_dst_reg_from_src(tree->src_reg),
+                           tree->dst_reg,
                            tree->left->src_reg,
                            tree->right->src_reg);
        tree->src_reg.swizzle = SWIZZLE_XXXX;
@@ -166,7 +166,7 @@ vec4: dp4_vec4_vec4(vec4, vec4) 1
 vec4: dp3_vec4_vec4(vec4, vec4) 1
 {
        ir_to_mesa_emit_op2(tree, OPCODE_DP3,
-                           ir_to_mesa_dst_reg_from_src(tree->src_reg),
+                           tree->dst_reg,
                            tree->left->src_reg,
                            tree->right->src_reg);
        tree->src_reg.swizzle = SWIZZLE_XXXX;
@@ -176,7 +176,7 @@ vec4: dp3_vec4_vec4(vec4, vec4) 1
 vec4: dp2_vec4_vec4(vec4, vec4) 1
 {
        ir_to_mesa_emit_op2(tree, OPCODE_DP2,
-                           ir_to_mesa_dst_reg_from_src(tree->src_reg),
+                           tree->dst_reg,
                            tree->left->src_reg,
                            tree->right->src_reg);
        tree->src_reg.swizzle = SWIZZLE_XXXX;
@@ -185,11 +185,11 @@ vec4: dp2_vec4_vec4(vec4, vec4) 1
 vec4: div_vec4_vec4(vec4, vec4) 1
 {
        ir_to_mesa_emit_scalar_op1(tree, OPCODE_RCP,
-                                  ir_to_mesa_dst_reg_from_src(tree->src_reg),
+                                  tree->dst_reg,
                                   tree->left->src_reg);
 
        ir_to_mesa_emit_op2(tree, OPCODE_MUL,
-                           ir_to_mesa_dst_reg_from_src(tree->src_reg),
+                           tree->dst_reg,
                            tree->src_reg,
                            tree->left->src_reg);
 }
@@ -197,11 +197,11 @@ vec4: div_vec4_vec4(vec4, vec4) 1
 vec4: sqrt_vec4(vec4) 1
 {
        ir_to_mesa_emit_scalar_op1(tree, OPCODE_RSQ,
-                                  ir_to_mesa_dst_reg_from_src(tree->src_reg),
+                                  tree->dst_reg,
                                   tree->left->src_reg);
 
        ir_to_mesa_emit_op1(tree, OPCODE_RCP,
-                           ir_to_mesa_dst_reg_from_src(tree->src_reg),
+                           tree->dst_reg,
                            tree->src_reg);
 }