summaryrefslogtreecommitdiff
path: root/ir_to_mesa.cpp
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2010-05-05 17:21:18 -0700
committerEric Anholt <eric@anholt.net>2010-06-24 15:05:19 -0700
commit12f654c63bc42d353e258cde989d9114cdde26c6 (patch)
treeda31dee2fa16ecc8a579e977cb105d7dc2fd4ed3 /ir_to_mesa.cpp
parentb2ed4dd7b0270e469302965269007292117d02e2 (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.cpp47
1 files changed, 46 insertions, 1 deletions
diff --git a/ir_to_mesa.cpp b/ir_to_mesa.cpp
index eb55f82e27..77ca6df73c 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]);