[Mesa-dev] [PATCH 2/2] i965/fs: Add support for gl_HelperInvocation system value.

Matt Turner mattst88 at gmail.com
Fri Nov 13 18:05:36 PST 2015


---
This code generates

	mov(1)          f0<1>UW         g1.14<0,1,0>UW
	mov(8)          g2<1>UD         0x00000000UD
	(+f0) sel(8)    g3<1>D          g2<8,8,1>D      -1D

which I don't love because it uses the flag register, and likely uses
of gl_HelperInvocation will be in an if condition, in which case we
could have just used f0 directly.

Alternative implementation ideas:

  - Shift dispatch mask with a vector-immediate, and then
    resolve it to true/false with -(x & 1):

	shr(8)  tmp<1>UW  g1.14<1,8,0>UB  0x76543210V

  - Take advantage of the dispatch mask directly:

  	mov(8)  dst<1>D, 0D   { WE_all }
	mov(8)  dst<1>D, -1D

    But optimization passes would have to be made to understand
    that the first move in that sequence isn't dead...

Regardless, I couldn't make either of these other ideas work.

 src/mesa/drivers/dri/i965/brw_fs_nir.cpp | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
index c282f83..7cf32b5 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
@@ -250,6 +250,23 @@ emit_system_values_block(nir_block *block, void *void_visitor)
             *reg = *v->emit_cs_work_group_id_setup();
          break;
 
+      case nir_intrinsic_load_helper_invocation:
+         assert(v->stage == MESA_SHADER_FRAGMENT);
+         reg = &v->nir_system_values[SYSTEM_VALUE_HELPER_INVOCATION];
+         if (reg->file == BAD_FILE) {
+            const fs_builder abld =
+               v->bld.annotate("gl_HelperInvocation", NULL);
+
+            abld.emit(FS_OPCODE_MOV_DISPATCH_TO_FLAGS);
+            fs_reg zero = abld.vgrf(BRW_REGISTER_TYPE_D, 1);
+            fs_reg dst = abld.vgrf(BRW_REGISTER_TYPE_D, 1);
+            abld.MOV(zero, fs_reg(0));
+            set_predicate(BRW_PREDICATE_NORMAL,
+                          abld.SEL(dst, zero, fs_reg(-1)));
+            *reg = dst;
+         }
+         break;
+
       default:
          break;
       }
@@ -1703,6 +1720,7 @@ fs_visitor::nir_emit_fs_intrinsic(const fs_builder &bld,
       break;
    }
 
+   case nir_intrinsic_load_helper_invocation:
    case nir_intrinsic_load_sample_mask_in:
    case nir_intrinsic_load_sample_id: {
       gl_system_value sv = nir_system_value_from_intrinsic(instr->intrinsic);
-- 
2.4.9



More information about the mesa-dev mailing list