intel/compiler/fs: Implement FS_OPCODE_LINTERP with MADs on Gen11+
authorMatt Turner <mattst88@gmail.com>
Wed, 14 Jun 2017 21:47:19 +0000 (14:47 -0700)
committerMatt Turner <mattst88@gmail.com>
Wed, 28 Feb 2018 19:15:47 +0000 (11:15 -0800)
The PLN instruction is no more. Its functionality is now implemented
using two MAD instructions with the new native-float type. Instead of

   pln(16) r20.0<1>:F r10.4<0;1,0>:F r4.0<8;8,1>:F

we now have

   mad(8) acc0<1>:NF r10.7<0;1,0>:F r4.0<8;8,1>:F r10.4<0;1,0>:F
   mad(8) r20.0<1>:F acc0<8;8,1>:NF r5.0<8;8,1>:F r10.5<0;1,0>:F
   mad(8) acc0<1>:NF r10.7<0;1,0>:F r6.0<8;8,1>:F r10.4<0;1,0>:F
   mad(8) r21.0<1>:F acc0<8;8,1>:NF r7.0<8;8,1>:F r10.5<0;1,0>:F

... and in the case of SIMD8 only the first pair of MAD instructions is
used.

Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
src/intel/compiler/brw_eu_emit.c
src/intel/compiler/brw_fs_generator.cpp

index ec871e5aa75f80c07db214e43c92e184d031cd57..a96fe43556eac289b70f71466e8cd20474949f78 100644 (file)
@@ -968,7 +968,7 @@ ALU2(DP4)
 ALU2(DPH)
 ALU2(DP3)
 ALU2(DP2)
-ALU3F(MAD)
+ALU3(MAD)
 ALU3F(LRP)
 ALU1(BFREV)
 ALU3(BFE)
index 3abd7cf5388c41eeeb8b6463e023ce34b4734df8..736b3b5fba040d601b0c5114a2e3b34db3c3ec83 100644 (file)
@@ -673,10 +673,52 @@ fs_generator::generate_linterp(fs_inst *inst,
    struct brw_reg delta_x = src[0];
    struct brw_reg delta_y = offset(src[0], inst->exec_size / 8);
    struct brw_reg interp = src[1];
-   brw_inst *i[2];
+   brw_inst *i[4];
 
-   if (devinfo->has_pln &&
-       (devinfo->gen >= 7 || (delta_x.nr & 1) == 0)) {
+   if (devinfo->gen >= 11) {
+      struct brw_reg acc = retype(brw_acc_reg(8), BRW_REGISTER_TYPE_NF);
+      struct brw_reg dwP = suboffset(interp, 0);
+      struct brw_reg dwQ = suboffset(interp, 1);
+      struct brw_reg dwR = suboffset(interp, 3);
+
+      brw_set_default_exec_size(p, BRW_EXECUTE_8);
+
+      if (inst->exec_size == 8) {
+         i[0] = brw_MAD(p,            acc, dwR, offset(delta_x, 0), dwP);
+         i[1] = brw_MAD(p, offset(dst, 0), acc, offset(delta_y, 0), dwQ);
+
+         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 of each pair.
+          */
+         brw_inst_set_saturate(p->devinfo, i[0], false);
+      } else {
+         brw_set_default_compression_control(p, BRW_COMPRESSION_NONE);
+         i[0] = brw_MAD(p,            acc, dwR, offset(delta_x, 0), dwP);
+         i[1] = brw_MAD(p, offset(dst, 0), acc, offset(delta_x, 1), dwQ);
+
+         brw_set_default_compression_control(p, BRW_COMPRESSION_2NDHALF);
+         i[2] = brw_MAD(p,            acc, dwR, offset(delta_y, 0), dwP);
+         i[3] = brw_MAD(p, offset(dst, 1), acc, offset(delta_y, 1), dwQ);
+
+         brw_set_default_compression_control(p, BRW_COMPRESSION_COMPRESSED);
+
+         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 if (devinfo->has_pln &&
+              (devinfo->gen >= 7 || (delta_x.nr & 1) == 0)) {
       brw_PLN(p, dst, interp, delta_x);
 
       return false;