diff options
author | Ian Romanick <[email protected]> | 2010-08-02 18:48:25 -0700 |
---|---|---|
committer | Ian Romanick <[email protected]> | 2010-08-04 16:47:27 -0700 |
commit | 5a7758efbe14dee026245a4f4f4fb3ccf7b2c23b (patch) | |
tree | be214c6f3ea4be5ec4472afa5b3426d5191380f5 /src/mesa | |
parent | 8e9ce2eb56a087c2544112700ae1abe3f96648dd (diff) |
glsl2: Add ir_assignment::write_mask and associated methods
Replace swizzles on the LHS with additional swizzles on the RHS and a
write mask in the assignment instruction. As part of this add
ir_assignment::set_lhs. Ideally we'd make ir_assignment::lhs private
to prevent erroneous writes, but that would require a lot of code
butchery at this point.
Add ir_assignment constructor that takes an explicit write mask. This
is required for ir_assignment::clone, but it can also be used in other
places. Without this, ir_assignment clones lose their write masks,
and incorrect IR is generated in optimization passes.
Add ir_assignment::whole_variable_written method. This method gets
the variable on the LHS if the whole variable is written or NULL
otherwise. This is different from
ir->lhs->whole_variable_referenced() because the latter has no
knowledge of the write mask stored in the ir_assignment.
Gut all code from ir_to_mesa that handled swizzles on the LHS of
assignments. There is probably some other refactoring that could be
done here, but that can be left for another day.
Diffstat (limited to 'src/mesa')
-rw-r--r-- | src/mesa/program/ir_to_mesa.cpp | 67 |
1 files changed, 25 insertions, 42 deletions
diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 777b4d91f48..1cec4aa6212 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -356,6 +356,7 @@ ir_to_mesa_visitor::ir_to_mesa_emit_op1(ir_instruction *ir, ir_to_mesa_dst_reg dst, ir_to_mesa_src_reg src0) { + assert(dst.writemask != 0); return ir_to_mesa_emit_op3(ir, op, dst, src0, ir_to_mesa_undef, ir_to_mesa_undef); } @@ -1615,21 +1616,17 @@ ir_to_mesa_visitor::visit(ir_dereference_record *ir) * We want to be careful in assignment setup to hit the actual storage * instead of potentially using a temporary like we might with the * ir_dereference handler. - * - * Thanks to ir_swizzle_swizzle, and ir_vec_index_to_swizzle, we - * should only see potentially one variable array index of a vector, - * and one swizzle, before getting to actual vec4 storage. So handle - * those, then go use ir_dereference to handle the rest. */ static struct ir_to_mesa_dst_reg -get_assignment_lhs(ir_instruction *ir, ir_to_mesa_visitor *v, +get_assignment_lhs(ir_dereference *ir, ir_to_mesa_visitor *v, ir_to_mesa_src_reg *r) { - struct ir_to_mesa_dst_reg dst_reg; - ir_swizzle *swiz; - + /* The LHS must be a dereference. If the LHS is a variable indexed array + * access of a vector, it must be separated into a series conditional moves + * before reaching this point (see ir_vec_index_to_cond_assign). + */ + assert(ir->as_dereference()); ir_dereference_array *deref_array = ir->as_dereference_array(); - /* This should have been handled by ir_vec_index_to_cond_assign */ if (deref_array) { assert(!deref_array->array->type->is_vector()); } @@ -1638,38 +1635,7 @@ get_assignment_lhs(ir_instruction *ir, ir_to_mesa_visitor *v, * swizzles in it and write swizzles using writemask, though. */ ir->accept(v); - dst_reg = ir_to_mesa_dst_reg_from_src(v->result); - - if ((swiz = ir->as_swizzle())) { - int swizzles[4] = { - swiz->mask.x, - swiz->mask.y, - swiz->mask.z, - swiz->mask.w - }; - int new_r_swizzle[4]; - int orig_r_swizzle = r->swizzle; - int i; - - for (i = 0; i < 4; i++) { - new_r_swizzle[i] = GET_SWZ(orig_r_swizzle, 0); - } - - dst_reg.writemask = 0; - for (i = 0; i < 4; i++) { - if (i < swiz->mask.num_components) { - dst_reg.writemask |= 1 << swizzles[i]; - new_r_swizzle[swizzles[i]] = GET_SWZ(orig_r_swizzle, i); - } - } - - r->swizzle = MAKE_SWIZZLE4(new_r_swizzle[0], - new_r_swizzle[1], - new_r_swizzle[2], - new_r_swizzle[3]); - } - - return dst_reg; + return ir_to_mesa_dst_reg_from_src(v->result); } void @@ -1684,6 +1650,23 @@ ir_to_mesa_visitor::visit(ir_assignment *ir) l = get_assignment_lhs(ir->lhs, this, &r); + /* 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()); + l.writemask = WRITEMASK_XYZW; + } else if (ir->lhs->type->is_scalar()) { + /* FINISHME: This hack makes writing to gl_FragData, which lives in the + * FINISHME: W component of fragment shader output zero, work correctly. + */ + l.writemask = WRITEMASK_XYZW; + } else { + assert(ir->lhs->type->is_vector()); + l.writemask = ir->write_mask; + } + assert(l.file != PROGRAM_UNDEFINED); assert(r.file != PROGRAM_UNDEFINED); |