ir_to_mesa: Add support for variable indexing of temporary arrays.
authorEric Anholt <eric@anholt.net>
Mon, 10 May 2010 17:06:36 +0000 (10:06 -0700)
committerEric Anholt <eric@anholt.net>
Thu, 24 Jun 2010 22:05:20 +0000 (15:05 -0700)
Fixes loop-01.vert, loop-02.vert.

ir_to_mesa.cpp
ir_to_mesa.h
mesa_codegen.brg

index 3451fc887dbc9c7f26869361d67f6b047c614175..44786258db1ed85ba7f32d6b000cc7e5c0d39515 100644 (file)
@@ -51,7 +51,7 @@ extern "C" {
 }
 
 ir_to_mesa_src_reg ir_to_mesa_undef = {
-   PROGRAM_UNDEFINED, 0, SWIZZLE_NOOP
+   PROGRAM_UNDEFINED, 0, SWIZZLE_NOOP, false,
 };
 
 ir_to_mesa_dst_reg ir_to_mesa_undef_dst = {
@@ -659,13 +659,11 @@ ir_to_mesa_visitor::visit(ir_dereference_array *ir)
     */
    assert(!var->type->is_matrix());
 
-   tree = this->create_tree(MB_TERM_reference_vec4, ir, NULL, NULL);
-
    if (strncmp(var->name, "gl_", 3) == 0) {
       unsigned int i;
       unsigned int offset = 0;
 
-      assert(index); /* FINISHME: Handle variable indexing of builtins. */
+      tree = this->create_tree(MB_TERM_reference_vec4, ir, NULL, NULL);
 
       offset = index->value.i[0];
 
@@ -677,11 +675,24 @@ ir_to_mesa_visitor::visit(ir_dereference_array *ir)
       ir_to_mesa_set_tree_reg(tree, builtin_var_to_mesa_reg[i].file,
                              builtin_var_to_mesa_reg[i].index + offset);
    } else {
+      tree = this->create_tree(MB_TERM_reference_vec4, ir, NULL, NULL);
       this->get_temp_for_var(var, tree);
-      assert(index); /* FINISHME: Handle variable indexing. */
 
-      tree->src_reg.index += index->value.i[0];
-      tree->dst_reg.index += index->value.i[0];
+      if (index) {
+        tree->src_reg.index += index->value.i[0];
+        tree->dst_reg.index += index->value.i[0];
+      } else {
+        /* Variable index array dereference.  It eats the "vec4" of the
+         * base of the array and an index that offsets the Mesa register
+         * index.
+         */
+        ir->array_index->accept(this);
+
+        tree->src_reg.reladdr = true;
+        tree = this->create_tree(MB_TERM_array_reference_vec4_vec4,
+                                 ir, tree, this->result);
+        this->get_temp(tree, ir->type->vector_elements);
+      }
    }
 
    /* If the type is smaller than a vec4, replicate the last channel out. */
@@ -841,6 +852,7 @@ mesa_src_reg_from_ir_src_reg(ir_to_mesa_src_reg reg)
    assert(reg.index < (1 << INST_INDEX_BITS) - 1);
    mesa_reg.Index = reg.index;
    mesa_reg.Swizzle = reg.swizzle;
+   mesa_reg.RelAddr = reg.reladdr;
 
    return mesa_reg;
 }
index 43ddd5fe517fe249dd48e283a5cb4d1dbbf2f58a..515feb19a3822f3d13b4cb8394073622de87c81b 100644 (file)
@@ -40,6 +40,7 @@ typedef struct ir_to_mesa_src_reg {
    int file; /**< PROGRAM_* from Mesa */
    int index; /**< temporary index, VERT_ATTRIB_*, FRAG_ATTRIB_*, etc. */
    int swizzle; /**< SWIZZLE_XYZWONEZERO swizzles from Mesa. */
+   bool reladdr; /**< Register index should be offset by address reg. */
 } ir_to_mesa_src_reg;
 
 typedef struct ir_to_mesa_dst_reg {
@@ -145,6 +146,9 @@ public:
    exec_list instructions;
 };
 
+extern ir_to_mesa_src_reg ir_to_mesa_undef;
+extern ir_to_mesa_dst_reg ir_to_mesa_undef_dst;
+
 ir_to_mesa_instruction *
 ir_to_mesa_emit_op1(struct mbtree *tree, enum prog_opcode op);
 
index a906542dd53973908cf4e43ab9488af16836a415..109e8b2d5134120e925050659f78a54d35a8666d 100644 (file)
@@ -48,6 +48,7 @@
 # generate in its trees.
 %term assign
 %term reference_vec4
+%term array_reference_vec4_vec4
 %term exp_vec4
 %term exp2_vec4
 %term log_vec4
 # so it can be used as an argument for pretty much anything.
 vec4: reference_vec4 0
 
+# A reference of a variable is just a vec4 register location,
+# so it can be used as an argument for pretty much anything.
+vec4: array_reference_vec4_vec4 1
+{
+       ir_to_mesa_dst_reg address_reg = {PROGRAM_ADDRESS, 0, WRITEMASK_X};
+
+       ir_to_mesa_emit_op1_full(tree->v, tree->ir, OPCODE_ARL,
+                                address_reg,
+                                tree->right->src_reg);
+       ir_to_mesa_emit_op1_full(tree->v, tree->ir, OPCODE_MOV,
+                                tree->dst_reg,
+                                tree->left->src_reg);
+}
+
 # Here's the rule everyone will hit: Moving the result of an
 # expression into a variable-dereference register location.
 #