summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp17
1 files changed, 16 insertions, 1 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
index 310f3470dd7..9fc7ec7996c 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
@@ -2469,9 +2469,24 @@ vec4_visitor::emit_scratch_write(vec4_instruction *inst, int base_offset)
int reg_offset = base_offset + inst->dst.reg_offset;
src_reg index = get_scratch_offset(inst, inst->dst.reladdr, reg_offset);
- /* Create a temporary register to store *inst's result in. */
+ /* Create a temporary register to store *inst's result in.
+ *
+ * We have to be careful in MOVing from our temporary result register in
+ * the scratch write. If we swizzle from channels of the temporary that
+ * weren't initialized, it will confuse live interval analysis, which will
+ * make spilling fail to make progress.
+ */
src_reg temp = src_reg(this, glsl_type::vec4_type);
temp.type = inst->dst.type;
+ int first_writemask_chan = ffs(inst->dst.writemask) - 1;
+ int swizzles[4];
+ for (int i = 0; i < 4; i++)
+ if (inst->dst.writemask & (1 << i))
+ swizzles[i] = i;
+ else
+ swizzles[i] = first_writemask_chan;
+ temp.swizzle = BRW_SWIZZLE4(swizzles[0], swizzles[1],
+ swizzles[2], swizzles[3]);
dst_reg dst = dst_reg(brw_writemask(brw_vec8_grf(0, 0),
inst->dst.writemask));