[Mesa-dev] [PATCH 7/7] i965/fs: Fix readInvocationARB and readFirstInvocationARB

Jason Ekstrand jason at jlekstrand.net
Mon Aug 28 14:51:33 UTC 2017


The readInvocationARB built-in maps fairly nicely to our BROADCAST
opcode.  However, the current implementation isn't quite right.  This
commit fixes three different issues:

 1) It was blindly taking component 0 of the index value even if that
    channel is disabled.  We need emit_uniformize() to fix this.

 2) It didn't handle invalid index values particularly gracefully.
    These can actually cause assertion failures in the compiler because
    we may try to access out-of-bounds on a register.  This commit
    solves this by using invocation & (dispatch_width - 1).

 3) Neither readInvocationARB nor readFirstInvocationARB properly
    handled 64-bit types because they manually stomped the destination
    type to D regardless of bit-size.
---
 src/intel/compiler/brw_fs_nir.cpp | 22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/src/intel/compiler/brw_fs_nir.cpp b/src/intel/compiler/brw_fs_nir.cpp
index a882979..f5ace4f 100644
--- a/src/intel/compiler/brw_fs_nir.cpp
+++ b/src/intel/compiler/brw_fs_nir.cpp
@@ -4240,21 +4240,29 @@ fs_visitor::nir_emit_intrinsic(const fs_builder &bld, nir_intrinsic_instr *instr
 
    case nir_intrinsic_read_invocation: {
       const fs_reg value = get_nir_src(instr->src[0]);
-      const fs_reg invocation = get_nir_src(instr->src[1]);
+      const fs_reg invocation = get_nir_src_imm(instr->src[1]);
       fs_reg tmp = bld.vgrf(value.type);
 
-      bld.exec_all().emit(SHADER_OPCODE_BROADCAST, tmp, value,
-                          component(invocation, 0));
+      /* Get rid of invalid values.  Letting them wrap around seems fine. */
+      fs_reg idx;
+      if (invocation.file == BRW_IMMEDIATE_VALUE) {
+         idx = brw_imm_ud(invocation.ud & (dispatch_width - 1));
+      } else {
+         idx = fs_reg(VGRF, alloc.allocate(1), BRW_REGISTER_TYPE_UD);
+         bld.group(1, 0).exec_all().AND(idx, bld.emit_uniformize(invocation),
+                                             brw_imm_ud(dispatch_width - 1));
+         idx = component(idx, 0);
+      }
 
-      bld.MOV(retype(dest, BRW_REGISTER_TYPE_D),
-              fs_reg(component(tmp, 0)));
+      bld.exec_all().emit(SHADER_OPCODE_BROADCAST, tmp, value, idx);
+
+      bld.MOV(retype(dest, value.type), fs_reg(component(tmp, 0)));
       break;
    }
 
    case nir_intrinsic_read_first_invocation: {
       const fs_reg value = get_nir_src(instr->src[0]);
-      bld.MOV(retype(dest, BRW_REGISTER_TYPE_D),
-              bld.emit_uniformize(value));
+      bld.MOV(retype(dest, value.type), bld.emit_uniformize(value));
       break;
    }
 
-- 
2.5.0.400.gff86faf



More information about the mesa-dev mailing list