diff options
author | Eric Anholt <[email protected]> | 2010-05-05 17:21:18 -0700 |
---|---|---|
committer | Eric Anholt <[email protected]> | 2010-06-24 15:05:19 -0700 |
commit | 12f654c63bc42d353e258cde989d9114cdde26c6 (patch) | |
tree | da31dee2fa16ecc8a579e977cb105d7dc2fd4ed3 /ir_to_mesa.cpp | |
parent | b2ed4dd7b0270e469302965269007292117d02e2 (diff) |
ir_to_mesa: Produce multiple scalar ops when required to produce vec4s.
Fixes the code emitted in a test shader for vec2 texcoord / vec2 tex_size.
Diffstat (limited to 'ir_to_mesa.cpp')
-rw-r--r-- | ir_to_mesa.cpp | 47 |
1 files changed, 46 insertions, 1 deletions
diff --git a/ir_to_mesa.cpp b/ir_to_mesa.cpp index eb55f82e27f..77ca6df73c7 100644 --- a/ir_to_mesa.cpp +++ b/ir_to_mesa.cpp @@ -94,6 +94,51 @@ ir_to_mesa_emit_op1(struct mbtree *tree, enum prog_opcode op, dst, src0, ir_to_mesa_undef, ir_to_mesa_undef); } +/** + * Emits Mesa scalar opcodes to produce unique answers across channels. + * + * Some Mesa opcodes are scalar-only, like ARB_fp/vp. The src X + * channel determines the result across all channels. So to do a vec4 + * of this operation, we want to emit a scalar per source channel used + * to produce dest channels. + */ +void +ir_to_mesa_emit_scalar_op1(struct mbtree *tree, enum prog_opcode op, + ir_to_mesa_dst_reg dst, + ir_to_mesa_src_reg src0) +{ + int i, j; + int done_mask = 0; + + /* Mesa RCP is a scalar operation splatting results to all channels, + * like ARB_fp/vp. So emit as many RCPs as necessary to cover our + * dst channels. + */ + for (i = 0; i < 4; i++) { + int this_mask = (1 << i); + ir_to_mesa_instruction *inst; + ir_to_mesa_src_reg src = src0; + + if (done_mask & this_mask) + continue; + + int src_swiz = GET_SWZ(src.swizzle, i); + for (j = i + 1; j < 4; j++) { + if (GET_SWZ(src.swizzle, j) == src_swiz) { + this_mask |= (1 << j); + } + } + src.swizzle = MAKE_SWIZZLE4(src_swiz, src_swiz, + src_swiz, src_swiz); + + inst = ir_to_mesa_emit_op1(tree, op, + dst, + src); + inst->dst_reg.writemask = this_mask; + done_mask |= this_mask; + } +} + struct mbtree * ir_to_mesa_visitor::create_tree(int op, ir_instruction *ir, @@ -553,7 +598,7 @@ do_ir_to_mesa(exec_list *instructions) mesa_inst->DstReg.File = inst->dst_reg.file; mesa_inst->DstReg.Index = inst->dst_reg.index; mesa_inst->DstReg.CondMask = COND_TR; - mesa_inst->DstReg.WriteMask = WRITEMASK_XYZW; + mesa_inst->DstReg.WriteMask = inst->dst_reg.writemask; mesa_inst->SrcReg[0] = mesa_src_reg_from_ir_src_reg(inst->src_reg[0]); mesa_inst->SrcReg[1] = mesa_src_reg_from_ir_src_reg(inst->src_reg[1]); mesa_inst->SrcReg[2] = mesa_src_reg_from_ir_src_reg(inst->src_reg[2]); |