summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ir_to_mesa.cpp26
-rw-r--r--ir_to_mesa.h4
-rw-r--r--mesa_codegen.brg15
3 files changed, 38 insertions, 7 deletions
diff --git a/ir_to_mesa.cpp b/ir_to_mesa.cpp
index 3451fc887d..44786258db 100644
--- a/ir_to_mesa.cpp
+++ b/ir_to_mesa.cpp
@@ -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;
}
diff --git a/ir_to_mesa.h b/ir_to_mesa.h
index 43ddd5fe51..515feb19a3 100644
--- a/ir_to_mesa.h
+++ b/ir_to_mesa.h
@@ -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);
diff --git a/mesa_codegen.brg b/mesa_codegen.brg
index a906542dd5..109e8b2d51 100644
--- a/mesa_codegen.brg
+++ b/mesa_codegen.brg
@@ -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
@@ -93,6 +94,20 @@
# 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.
#