i965/fs: Properly write-mask spills
authorJason Ekstrand <jason.ekstrand@intel.com>
Mon, 25 Jan 2016 20:42:01 +0000 (12:42 -0800)
committerJason Ekstrand <jason.ekstrand@intel.com>
Mon, 25 Jan 2016 23:23:10 +0000 (15:23 -0800)
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
src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp

index 5a7a0eb5f63a3c6b596d60a5783c6c2b4ddee069..c931910136db98113b4c9e39857db2e4c50a69d6 100644 (file)
@@ -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();
index 2347cd5d33f726233b1f04d29c337623584594c0..791da0e038ebe0269ab3246bc0bfdc936015c129 100644 (file)
@@ -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);
       }
    }