diff options
author | Francisco Jerez <[email protected]> | 2016-05-16 01:23:44 -0700 |
---|---|---|
committer | Francisco Jerez <[email protected]> | 2016-05-23 14:05:21 -0700 |
commit | 11260cc54f277cadd2abfd22ec313f3f0f504487 (patch) | |
tree | d4b0f33110221652f9a5934475dac955cdd7c1ca /src/mesa/drivers | |
parent | bb67c467a48f89177cf5a1c9904a627704ea7844 (diff) |
i965/fs: Set exec_all on spills not matching the channel layout of the instruction.
This prevents the application of an incorrect channel mask by the
scratch write instruction for spilled variables that don't have an
exact one-to-one correspondence between channels of the variable and
32-bit components of the scratch write instruction.
Reviewed-by: Jason Ekstrand <[email protected]>
Diffstat (limited to 'src/mesa/drivers')
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp b/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp index bc847bfdb2b..4b921137ca0 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp @@ -977,14 +977,27 @@ fs_visitor::spill_reg(int spill_reg) const unsigned width = dispatch_width == 16 && inst->regs_written % 2 == 0 ? 16 : 8; + /* Spills should only write data initialized by the instruction for + * whichever channels are enabled in the excution mask. If that's + * not possible we'll have to emit a matching unspill before the + * instruction and set force_writemask_all on the spill. + */ + const bool per_channel = + inst->dst.is_contiguous() && type_sz(inst->dst.type) == 4 && + inst->exec_size == width; + /* Builder used to emit the scratch messages. */ - const fs_builder ubld = ibld.group(width, 0); + const fs_builder ubld = ibld.exec_all(!per_channel).group(width, 0); /* If our write is going to affect just part of the * inst->regs_written(), then we need to unspill the destination - * since we write back out all of the regs_written(). + * since we write back out all of the regs_written(). If the + * original instruction had force_writemask_all set and is not a + * partial write, there should be no need for the unspill since the + * instruction will be overwriting the whole destination in any case. */ - if (inst->is_partial_write()) + if (inst->is_partial_write() || + (!inst->force_writemask_all && !per_channel)) emit_unspill(ubld, spill_src, subset_spill_offset, inst->regs_written); |