[Mesa-dev] [PATCH] i965/fs: Take Dispatch/Vector mask into account in FIND_LIVE_CHANNEL

Jason Ekstrand jason at jlekstrand.net
Wed Sep 14 08:05:05 UTC 2016


On at least Sky Lake, ce0 does not contain the full story as far as enabled
channels goes.  It is possible to have completely disabled channels where
the corresponding bits in ce0 are 1.  In order to get the correct execution
mask, you have to mask off those channels which were disabled from the
beginning by taking the AND of ce0 with either sr0.2 or sr0.3 depending on
the shader stage.  Failure to do so can result in FIND_LIVE_CHANNEL
returning a completely dead channel.

Signed-off-by: Jason Ekstrand <jason at jlekstrand.net>
Cc: Francisco Jerez <currojerez at riseup.net>
---
 src/mesa/drivers/dri/i965/brw_eu.h               |  3 ++-
 src/mesa/drivers/dri/i965/brw_eu_emit.c          | 25 +++++++++++++++++-------
 src/mesa/drivers/dri/i965/brw_fs_generator.cpp   |  2 +-
 src/mesa/drivers/dri/i965/brw_vec4_generator.cpp |  2 +-
 4 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_eu.h b/src/mesa/drivers/dri/i965/brw_eu.h
index 3e52764..109ff8a 100644
--- a/src/mesa/drivers/dri/i965/brw_eu.h
+++ b/src/mesa/drivers/dri/i965/brw_eu.h
@@ -488,7 +488,8 @@ brw_pixel_interpolator_query(struct brw_codegen *p,
 
 void
 brw_find_live_channel(struct brw_codegen *p,
-                      struct brw_reg dst);
+                      struct brw_reg dst,
+                      bool vector_mask_enable);
 
 void
 brw_broadcast(struct brw_codegen *p,
diff --git a/src/mesa/drivers/dri/i965/brw_eu_emit.c b/src/mesa/drivers/dri/i965/brw_eu_emit.c
index 3b12030..a760b30 100644
--- a/src/mesa/drivers/dri/i965/brw_eu_emit.c
+++ b/src/mesa/drivers/dri/i965/brw_eu_emit.c
@@ -3361,7 +3361,8 @@ brw_pixel_interpolator_query(struct brw_codegen *p,
 }
 
 void
-brw_find_live_channel(struct brw_codegen *p, struct brw_reg dst)
+brw_find_live_channel(struct brw_codegen *p, struct brw_reg dst,
+                      bool vector_mask_enable)
 {
    const struct gen_device_info *devinfo = p->devinfo;
    const unsigned exec_size = 1 << brw_inst_exec_size(devinfo, p->current);
@@ -3377,13 +3378,23 @@ brw_find_live_channel(struct brw_codegen *p, struct brw_reg dst)
 
       if (devinfo->gen >= 8) {
          /* Getting the first active channel index is easy on Gen8: Just find
-          * the first bit set in the mask register.  The same register exists
-          * on HSW already but it reads back as all ones when the current
-          * instruction has execution masking disabled, so it's kind of
-          * useless.
+          * the first bit set in the execution mask.  The only tricky part is
+          * that ce0 needs to be combined with dispatch mask from sr0.2 in
+          * order to get the actual set of channel enables.  Both registers
+          * exist on HSW already but it reads back ec0 as all ones when the
+          * current instruction has execution masking disabled, so it's kind
+          * of useless.
           */
-         inst = brw_FBL(p, vec1(dst),
-                        retype(brw_mask_reg(0), BRW_REGISTER_TYPE_UD));
+         if (vector_mask_enable) {
+            brw_MOV(p, vec1(dst), get_element_ud(brw_sr0_reg(), 3));
+         } else {
+            brw_MOV(p, vec1(dst), get_element_ud(brw_sr0_reg(), 2));
+         }
+         brw_AND(p, vec1(dst),
+                 retype(brw_mask_reg(0), BRW_REGISTER_TYPE_UD),
+                 vec1(dst));
+
+         inst = brw_FBL(p, vec1(dst), vec1(dst));
 
          /* Quarter control has the effect of magically shifting the value of
           * this register so you'll get the first active channel relative to
diff --git a/src/mesa/drivers/dri/i965/brw_fs_generator.cpp b/src/mesa/drivers/dri/i965/brw_fs_generator.cpp
index 2f4ba7b..f2c49da 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_generator.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_generator.cpp
@@ -2041,7 +2041,7 @@ fs_generator::generate_code(const cfg_t *cfg, int dispatch_width)
          break;
 
       case SHADER_OPCODE_FIND_LIVE_CHANNEL:
-         brw_find_live_channel(p, dst);
+         brw_find_live_channel(p, dst, stage == MESA_SHADER_FRAGMENT);
          break;
 
       case SHADER_OPCODE_BROADCAST:
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_generator.cpp b/src/mesa/drivers/dri/i965/brw_vec4_generator.cpp
index 256abae..5ff9a3a 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4_generator.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4_generator.cpp
@@ -1863,7 +1863,7 @@ generate_code(struct brw_codegen *p,
          break;
 
       case SHADER_OPCODE_FIND_LIVE_CHANNEL:
-         brw_find_live_channel(p, dst);
+         brw_find_live_channel(p, dst, false);
          break;
 
       case SHADER_OPCODE_BROADCAST:
-- 
2.5.0.400.gff86faf



More information about the mesa-dev mailing list