[Mesa-dev] [PATCH 33/53] intel/fs: Emit LINE+MAC for LINTERP with unaligned coordinates

Jason Ekstrand jason at jlekstrand.net
Thu May 24 21:56:15 UTC 2018


On g4x through Sandy Bridge, src1 (the coordinates) of the PLN
instruction is required to be an even register number.  When it's odd
(which can happen with SIMD32), we have to emit a LINE+MAC combination
instead.  Unfortunately, we can't just fall through to the gen4 case
because the input registers are still set up for PLN which lays out the
four src1 registers differently in SIMD16 than LINE.
---
 src/intel/compiler/brw_fs_generator.cpp | 75 +++++++++++++++++++++++++++++----
 1 file changed, 66 insertions(+), 9 deletions(-)

diff --git a/src/intel/compiler/brw_fs_generator.cpp b/src/intel/compiler/brw_fs_generator.cpp
index a495496..ca239a2 100644
--- a/src/intel/compiler/brw_fs_generator.cpp
+++ b/src/intel/compiler/brw_fs_generator.cpp
@@ -767,16 +767,73 @@ fs_generator::generate_linterp(fs_inst *inst,
 
       return true;
    } else if (devinfo->has_pln) {
-      /* From the Sandy Bridge PRM Vol. 4, Pt. 2, Section 8.3.53, "Plane":
-       *
-       *    "[DevSNB]:<src1> must be even register aligned.
-       *
-       * This restriction is lifted on Ivy Bridge.
-       */
-      assert(devinfo->gen >= 7 || (delta_x.nr & 1) == 0);
-      brw_PLN(p, dst, interp, delta_x);
+      if (devinfo->gen <= 6 && (delta_x.nr & 1) != 0) {
+         /* From the Sandy Bridge PRM Vol. 4, Pt. 2, Section 8.3.53, "Plane":
+          *
+          *    "[DevSNB]:<src1> must be even register aligned.
+          *
+          * This restriction is lifted on Ivy Bridge.
+          *
+          * This means that we need to split PLN into LINE+MAC on-the-fly.
+          * Unfortunately, the inputs are laid out for PLN and not LIN+MAC so
+          * we have to split into SIMD8 pieces.
+          */
+         if (inst->exec_size == 8) {
+            i[0] = brw_LINE(p, brw_null_reg(), interp, delta_x);
+            i[1] = brw_MAC(p, dst, suboffset(interp, 1), delta_y);
 
-      return false;
+            /* LINE writes the accumulator automatically on gen4-5.  On Sandy
+             * Bridge and later, we have to explicitly enable it.
+             */
+            if (devinfo->gen >= 6)
+               brw_inst_set_acc_wr_control(p->devinfo, i[0], true);
+
+            brw_inst_set_cond_modifier(p->devinfo, i[1], inst->conditional_mod);
+
+            /* brw_set_default_saturate() is called before emitting
+             * instructions, so the saturate bit is set in each instruction,
+             * so we need to unset it on the first instruction.
+             */
+            brw_inst_set_saturate(p->devinfo, i[0], false);
+         } else {
+            brw_push_insn_state(p);
+            brw_set_default_exec_size(p, BRW_EXECUTE_8);
+
+            brw_set_default_group(p, inst->group);
+            i[0] = brw_LINE(p, brw_null_reg(), interp, offset(delta_x, 0));
+            i[1] = brw_MAC(p, offset(dst, 0),
+                           suboffset(interp, 1), offset(delta_x, 1));
+
+            brw_set_default_group(p, inst->group + 8);
+            i[2] = brw_LINE(p, brw_null_reg(), interp, offset(delta_y, 0));
+            i[3] = brw_MAC(p, offset(dst, 1),
+                           suboffset(interp, 1), offset(delta_y, 1));
+
+            brw_pop_insn_state(p);
+
+            /* LINE writes the accumulator automatically on gen4-5.  On Sandy
+             * Bridge and later, we have to explicitly enable it.
+             */
+            if (devinfo->gen >= 6) {
+               brw_inst_set_acc_wr_control(p->devinfo, i[0], true);
+               brw_inst_set_acc_wr_control(p->devinfo, i[2], true);
+            }
+
+            brw_inst_set_cond_modifier(p->devinfo, i[1], inst->conditional_mod);
+            brw_inst_set_cond_modifier(p->devinfo, i[3], inst->conditional_mod);
+
+            /* brw_set_default_saturate() is called before emitting
+             * instructions, so the saturate bit is set in each instruction,
+             * so we need to unset it on the first instruction of each pair.
+             */
+            brw_inst_set_saturate(p->devinfo, i[0], false);
+            brw_inst_set_saturate(p->devinfo, i[2], false);
+         }
+         return true;
+      } else {
+         brw_PLN(p, dst, interp, delta_x);
+         return false;
+      }
    } else {
       i[0] = brw_LINE(p, brw_null_reg(), interp, delta_x);
       i[1] = brw_MAC(p, dst, suboffset(interp, 1), delta_y);
-- 
2.5.0.400.gff86faf



More information about the mesa-dev mailing list