i965/fs: Use conditional sends to do FB writes on HSW+.
authorEric Anholt <eric@anholt.net>
Fri, 14 Feb 2014 05:37:50 +0000 (21:37 -0800)
committerEric Anholt <eric@anholt.net>
Tue, 18 Feb 2014 18:11:36 +0000 (10:11 -0800)
This drops the MOVs for header setup, which are totally mis-scheduled.

total instructions in shared programs: 1590047 -> 1589331 (-0.05%)
instructions in affected programs:     43729 -> 43013 (-1.64%)
GAINED:                                0
LOST:                                  0

glb27-trex:
x before
+ after
+-----------------------------------------------------------------------------+
|               +      x     xx        +  +    +                              |
|              ++  + xxx ++x xx + ** *x+  +  + +  x *                         |
|+x xx x*    x+++xx*x*xx+++*+*xx++** *x* x+***x*+xx+*     + *    +  +        *|
|               |__|__________MA___A___________|___|                          |
+-----------------------------------------------------------------------------+
    N           Min           Max        Median           Avg        Stddev
x  49         62.33         65.41         63.49      63.53449    0.62757822
+  50         62.28          65.4          63.7       63.6982      0.656564
No difference proven at 95.0% confidence

Reviewed-by: Matt Turner <mattst88@gmail.com>
src/mesa/drivers/dri/i965/brw_eu_emit.c
src/mesa/drivers/dri/i965/brw_fs_generator.cpp
src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
src/mesa/drivers/dri/i965/gen8_fs_generator.cpp

index 8ab043fd63c8a63024a7d51d3445a369c634d765..5360b56bcfefc4a476dff09d8345cf7a3eb7d448 100644 (file)
@@ -2241,8 +2241,6 @@ void brw_fb_WRITE(struct brw_compile *p,
    } else {
       insn = next_insn(p, BRW_OPCODE_SEND);
    }
-   /* The execution mask is ignored for render target writes. */
-   insn->header.predicate_control = 0;
    insn->header.compression_control = BRW_COMPRESSION_NONE;
 
    if (brw->gen >= 6) {
index 00f19dcac71c6f1fdfe9acf8f9c1096f7c003c30..ee13ced9e57b67ebbb0ae341325dada8601641ad 100644 (file)
@@ -114,18 +114,22 @@ fs_generator::generate_fb_write(fs_inst *inst)
    brw_set_mask_control(p, BRW_MASK_DISABLE);
    brw_set_compression_control(p, BRW_COMPRESSION_NONE);
 
-   if ((fp && fp->UsesKill) || c->key.alpha_test_func) {
-      struct brw_reg pixel_mask;
+   if (inst->header_present) {
+      /* On HSW, the GPU will use the predicate on SENDC, unless the header is
+       * present.
+       */
+      if (!brw->is_haswell && ((fp && fp->UsesKill) ||
+                               c->key.alpha_test_func)) {
+         struct brw_reg pixel_mask;
 
-      if (brw->gen >= 6)
-         pixel_mask = retype(brw_vec1_grf(1, 7), BRW_REGISTER_TYPE_UW);
-      else
-         pixel_mask = retype(brw_vec1_grf(0, 0), BRW_REGISTER_TYPE_UW);
+         if (brw->gen >= 6)
+            pixel_mask = retype(brw_vec1_grf(1, 7), BRW_REGISTER_TYPE_UW);
+         else
+            pixel_mask = retype(brw_vec1_grf(0, 0), BRW_REGISTER_TYPE_UW);
 
-      brw_MOV(p, pixel_mask, brw_flag_reg(0, 1));
-   }
+         brw_MOV(p, pixel_mask, brw_flag_reg(0, 1));
+      }
 
-   if (inst->header_present) {
       if (brw->gen >= 6) {
         brw_set_compression_control(p, BRW_COMPRESSION_COMPRESSED);
         brw_MOV(p,
index 45b053d540eb01c1fb65741357f84e72f7925bf5..70b7c663a8cd29ed227164a7caa2e0771c1b976d 100644 (file)
@@ -2743,7 +2743,7 @@ fs_visitor::emit_fb_writes()
     *      thread message and on all dual-source messages."
     */
    if (brw->gen >= 6 &&
-       !this->fp->UsesKill &&
+       (brw->is_haswell || brw->gen >= 8 || !this->fp->UsesKill) &&
        !do_dual_src &&
        c->key.nr_color_regions == 1) {
       header_present = false;
@@ -2840,6 +2840,10 @@ fs_visitor::emit_fb_writes()
       inst->mlen = nr - base_mrf;
       inst->eot = true;
       inst->header_present = header_present;
+      if ((brw->gen >= 8 || brw->is_haswell) && fp->UsesKill) {
+         inst->predicate = BRW_PREDICATE_NORMAL;
+         inst->flag_subreg = 1;
+      }
 
       c->prog_data.dual_src_blend = true;
       this->current_annotation = NULL;
@@ -2885,6 +2889,10 @@ fs_visitor::emit_fb_writes()
          inst->mlen = nr - base_mrf;
       inst->eot = eot;
       inst->header_present = header_present;
+      if ((brw->gen >= 8 || brw->is_haswell) && fp->UsesKill) {
+         inst->predicate = BRW_PREDICATE_NORMAL;
+         inst->flag_subreg = 1;
+      }
    }
 
    if (c->key.nr_color_regions == 0) {
@@ -2902,6 +2910,10 @@ fs_visitor::emit_fb_writes()
       inst->mlen = nr - base_mrf;
       inst->eot = true;
       inst->header_present = header_present;
+      if ((brw->gen >= 8 || brw->is_haswell) && fp->UsesKill) {
+         inst->predicate = BRW_PREDICATE_NORMAL;
+         inst->flag_subreg = 1;
+      }
    }
 
    this->current_annotation = NULL;
index 332b14f60319ccf4e189741dae778c3fe143a0a4..ea1632091e8623e5d27db1005e67b80b1b0fb6d0 100644 (file)
@@ -61,14 +61,21 @@ gen8_fs_generator::mark_surface_used(unsigned surf_index)
 void
 gen8_fs_generator::generate_fb_write(fs_inst *ir)
 {
-   if (fp && fp->UsesKill) {
-      gen8_instruction *mov =
-         MOV(retype(brw_vec1_grf(1, 7), BRW_REGISTER_TYPE_UW),
-             brw_flag_reg(0, 1));
-      gen8_set_mask_control(mov, BRW_MASK_DISABLE);
-   }
+   /* Disable the discard condition while setting up the header. */
+   default_state.predicate = BRW_PREDICATE_NONE;
+   default_state.predicate_inverse = false;
+   default_state.flag_subreg_nr = 0;
 
    if (ir->header_present) {
+      /* The GPU will use the predicate on SENDC, unless the header is present.
+       */
+      if (fp && fp->UsesKill) {
+         gen8_instruction *mov =
+            MOV(retype(brw_vec1_grf(1, 7), BRW_REGISTER_TYPE_UW),
+                brw_flag_reg(0, 1));
+         gen8_set_mask_control(mov, BRW_MASK_DISABLE);
+      }
+
       gen8_instruction *mov =
          MOV_RAW(brw_message_reg(ir->base_mrf), brw_vec8_grf(0, 0));
       gen8_set_exec_size(mov, BRW_EXECUTE_16);
@@ -88,6 +95,13 @@ gen8_fs_generator::generate_fb_write(fs_inst *ir)
       }
    }
 
+   /* Set the predicate back to get the conditional write if necessary for
+    * discards.
+    */
+   default_state.predicate = ir->predicate;
+   default_state.predicate_inverse = ir->predicate_inverse;
+   default_state.flag_subreg_nr = ir->flag_subreg;
+
    gen8_instruction *inst = next_inst(BRW_OPCODE_SENDC);
    gen8_set_dst(brw, inst, retype(vec8(brw_null_reg()), BRW_REGISTER_TYPE_UW));
    gen8_set_src0(brw, inst, brw_message_reg(ir->base_mrf));