From 9c0109a1f6e0c9c8dd81fc215f8c0c5976e05790 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Mon, 25 Jan 2016 12:42:01 -0800 Subject: [PATCH] i965/fs: Properly write-mask spills For unspills (scratch reads), we can just set WE_all all the time because we always unspill into a new GRF. For spills, we have two options: If the instruction has a 32-bit-per-channel destination and "normal" regioning, then we just do a regular write and it will interleave channels from different control-flow paths properly. If, on the other hand, the the regioning is non-normal, then we have to unspill, run the instruction, and spill afterwards. In this second case, we need to do the spill with we_ALL. --- src/mesa/drivers/dri/i965/brw_fs.h | 2 +- src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h index 5a7a0eb5f63..c931910136d 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.h +++ b/src/mesa/drivers/dri/i965/brw_fs.h @@ -224,7 +224,7 @@ public: void emit_unspill(bblock_t *block, fs_inst *inst, fs_reg reg, uint32_t spill_offset, int count); void emit_spill(bblock_t *block, fs_inst *inst, fs_reg reg, - uint32_t spill_offset, int count); + uint32_t spill_offset, int count, bool we_all); void emit_nir_code(); void nir_setup_inputs(); 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 2347cd5d33f..791da0e038e 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp @@ -751,6 +751,7 @@ fs_visitor::emit_unspill(bblock_t *block, fs_inst *inst, fs_reg dst, dst); unspill_inst->offset = spill_offset; unspill_inst->regs_written = reg_size; + unspill_inst->force_writemask_all = true; if (!gen7_read) { unspill_inst->base_mrf = FIRST_SPILL_MRF(devinfo->gen) + 1; @@ -764,11 +765,11 @@ fs_visitor::emit_unspill(bblock_t *block, fs_inst *inst, fs_reg dst, void fs_visitor::emit_spill(bblock_t *block, fs_inst *inst, fs_reg src, - uint32_t spill_offset, int count) + uint32_t spill_offset, int count, bool we_all) { int reg_size = 1; int spill_base_mrf = FIRST_SPILL_MRF(devinfo->gen) + 1; - if (dispatch_width == 16 && count % 2 == 0) { + if (inst->exec_size == 16 && count % 2 == 0) { spill_base_mrf = FIRST_SPILL_MRF(devinfo->gen); reg_size = 2; } @@ -784,6 +785,8 @@ fs_visitor::emit_spill(bblock_t *block, fs_inst *inst, fs_reg src, spill_inst->offset = spill_offset + i * reg_size * REG_SIZE; spill_inst->mlen = 1 + reg_size; /* header, value */ spill_inst->base_mrf = spill_base_mrf; + spill_inst->force_writemask_all = we_all; + spill_inst->force_sechalf = inst->force_sechalf; } } @@ -938,12 +941,15 @@ fs_visitor::spill_reg(int spill_reg) * inst->regs_written(), then we need to unspill the destination * since we write back out all of the regs_written(). */ - if (inst->is_partial_write()) + bool need_unspill = inst->is_partial_write() || + type_sz(inst->dst.type) != 4; + if (need_unspill) emit_unspill(block, inst, spill_src, subset_spill_offset, inst->regs_written); emit_spill(block, inst, spill_src, subset_spill_offset, - inst->regs_written); + inst->regs_written, + need_unspill || inst->force_writemask_all); } } -- 2.30.2