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