diff options
author | Eric Anholt <[email protected]> | 2010-09-30 11:46:24 -0700 |
---|---|---|
committer | Eric Anholt <[email protected]> | 2010-09-30 13:45:42 -0700 |
commit | 6f6542a483ec726538f8a4555bddaeb0be6b2146 (patch) | |
tree | f1ab68ebf6c55514fe80c7dc81d6ce4e8d029518 /src/mesa/drivers/dri | |
parent | 3661f757ee7e75348f0df834ecf1febb211ddf66 (diff) |
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.
Diffstat (limited to 'src/mesa/drivers/dri')
-rw-r--r-- | 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 efbb4c66920..efa0f2136b2 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); } } |