summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2011-08-05 20:46:03 -0700
committerEric Anholt <[email protected]>2011-08-16 13:04:42 -0700
commit979072613139870f12e329e4b483c7f688b40560 (patch)
tree7cbe9a62261746826ef5baab3c5c39f096c7973e
parent930afd1774bdcd013bccbd7b5717ae0bb8e3dea3 (diff)
i965/vs: Handle assignment of structures/arrays/matrices better.
This gets the right types on the instructions, as well as emitting minimal swizzles/writemasks.
-rw-r--r--src/mesa/drivers/dri/i965/brw_vec4.h3
-rw-r--r--src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp69
2 files changed, 51 insertions, 21 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_vec4.h b/src/mesa/drivers/dri/i965/brw_vec4.h
index 01058243f04..1619c2e1ef6 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4.h
+++ b/src/mesa/drivers/dri/i965/brw_vec4.h
@@ -390,7 +390,8 @@ public:
void emit_bool_comparison(unsigned int op, dst_reg dst, src_reg src0, src_reg src1);
void emit_if_gen6(ir_if *ir);
- void emit_block_move(ir_assignment *ir);
+ void emit_block_move(dst_reg *dst, src_reg *src,
+ const struct glsl_type *type, bool predicated);
/**
* Emit the correct dot-product instruction for the type of arguments
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
index 27620c47085..4f7763d61bb 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
@@ -1269,38 +1269,69 @@ get_assignment_lhs(ir_dereference *ir, vec4_visitor *v)
}
void
-vec4_visitor::emit_block_move(ir_assignment *ir)
+vec4_visitor::emit_block_move(dst_reg *dst, src_reg *src,
+ const struct glsl_type *type, bool predicated)
{
- ir->rhs->accept(this);
- src_reg src = this->result;
-
- dst_reg dst = get_assignment_lhs(ir->lhs, this);
+ if (type->base_type == GLSL_TYPE_STRUCT) {
+ for (unsigned int i = 0; i < type->length; i++) {
+ emit_block_move(dst, src, type->fields.structure[i].type, predicated);
+ }
+ return;
+ }
- if (ir->condition) {
- emit_bool_to_cond_code(ir->condition);
+ if (type->is_array()) {
+ for (unsigned int i = 0; i < type->length; i++) {
+ emit_block_move(dst, src, type->fields.array, predicated);
+ }
+ return;
}
- /* FINISHME: This should really set to the correct maximal writemask for each
- * FINISHME: component written (in the loops below).
- */
- dst.writemask = WRITEMASK_XYZW;
+ if (type->is_matrix()) {
+ const struct glsl_type *vec_type;
- for (int i = 0; i < type_size(ir->lhs->type); i++) {
- vec4_instruction *inst = emit(BRW_OPCODE_MOV, dst, src);
- if (ir->condition)
- inst->predicate = BRW_PREDICATE_NORMAL;
+ vec_type = glsl_type::get_instance(GLSL_TYPE_FLOAT,
+ type->vector_elements, 1);
- dst.reg_offset++;
- src.reg_offset++;
+ for (int i = 0; i < type->matrix_columns; i++) {
+ emit_block_move(dst, src, vec_type, predicated);
+ }
+ return;
}
+
+ assert(type->is_scalar() || type->is_vector());
+
+ dst->type = brw_type_for_base_type(type);
+ src->type = dst->type;
+
+ dst->writemask = (1 << type->vector_elements) - 1;
+
+ /* Do we need to worry about swizzling a swizzle? */
+ assert(src->swizzle = BRW_SWIZZLE_NOOP);
+ src->swizzle = swizzle_for_size(type->vector_elements);
+
+ vec4_instruction *inst = emit(BRW_OPCODE_MOV, *dst, *src);
+ if (predicated)
+ inst->predicate = BRW_PREDICATE_NORMAL;
+
+ dst->reg_offset++;
+ src->reg_offset++;
}
void
vec4_visitor::visit(ir_assignment *ir)
{
+ dst_reg dst = get_assignment_lhs(ir->lhs, this);
+
if (!ir->lhs->type->is_scalar() &&
!ir->lhs->type->is_vector()) {
- emit_block_move(ir);
+ ir->rhs->accept(this);
+ src_reg src = this->result;
+
+ if (ir->condition) {
+ emit_bool_to_cond_code(ir->condition);
+ }
+
+ emit_block_move(&dst, &src, ir->rhs->type, ir->condition != NULL);
return;
}
@@ -1310,8 +1341,6 @@ vec4_visitor::visit(ir_assignment *ir)
ir->rhs->accept(this);
src_reg src = this->result;
- dst_reg dst = get_assignment_lhs(ir->lhs, this);
-
int swizzles[4];
int first_enabled_chan = 0;
int src_chan = 0;