Module: Mesa
Branch: main
Commit: fc0aaa81eed4ea0e6e6577e068511fae07773461
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=fc0aaa81eed4ea0e6e6577e068511fae07773461

Author: Kenneth Graunke <[email protected]>
Date:   Mon Aug 21 18:55:13 2023 -0700

nir: Reduce the scope of shared memory barriers

Originally written by Ian Romanick for the Intel backend, but ported
to the new nir_opt_barrier_modes() common optimization pass.  Ian's
original explanation and commit message follows:

Shared memory only exists within a workgroup, so synchronizing it beyond
workgroup scope is nonsense.

Basically every SPIR-V compiler generates operations like

    OpMemoryBarrier(/*Memory*/Device,
                    /*Semantics*/AcquireRelease | WorkgroupMemory)

This is suggested in numerous places, including
https://github.com/KhronosGroup/GLSL/blob/master/extensions/khr/GL_KHR_vulkan_glsl.txt.
Even Mesa's glsl_to_nir pass does this. This advice, which has been
copy-and-pasted everywhere, is contrary to issue 13 in the original
GL_ARB_compute_shader spec:

   "Since shared memory is only accessible to threads within a single
    work group, memoryBarrierShared() also only requires synchronization
    with other threads in the same work group."

Reviewed-by: Alyssa Rosenzweig <[email protected]>
Reviewed-by: Ian Romanick <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24842>

---

 src/compiler/nir/nir_opt_barriers.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/src/compiler/nir/nir_opt_barriers.c 
b/src/compiler/nir/nir_opt_barriers.c
index 56e5f49140e..1566576ec2e 100644
--- a/src/compiler/nir/nir_opt_barriers.c
+++ b/src/compiler/nir/nir_opt_barriers.c
@@ -184,6 +184,16 @@ nir_opt_barrier_modes_impl(nir_function_impl *impl)
          nir_intrinsic_set_memory_modes(barrier, new_modes);
          progress = true;
       }
+
+      /* Shared memory only exists within a workgroup, so synchronizing it
+       * beyond workgroup scope is nonsense.
+       */
+      if (nir_intrinsic_execution_scope(barrier) == SCOPE_NONE &&
+          new_modes == nir_var_mem_shared) {
+         nir_intrinsic_set_memory_scope(barrier,
+            MIN2(nir_intrinsic_memory_scope(barrier), SCOPE_WORKGROUP));
+         progress = true;
+      }
    }
 
    nir_instr_worklist_destroy(barriers);
@@ -193,7 +203,7 @@ nir_opt_barrier_modes_impl(nir_function_impl *impl)
 }
 
 /**
- * Reduce barriers to remove unnecessary modes.
+ * Reduce barriers to remove unnecessary modes and scope.
  *
  * This pass must be called before nir_lower_explicit_io lowers derefs!
  *
@@ -212,6 +222,9 @@ nir_opt_barrier_modes_impl(nir_function_impl *impl)
  * various shared memory operations.  Image reads and writes do also exist,
  * but they are all on one side of the barrier, so it is a no-op for image
  * access.  We can drop the image mode from the barrier in this case too.
+ *
+ * In addition, we can reduce the memory scope of shared-only barriers, as
+ * shared local memory only exists within a workgroup.
  */
 bool
 nir_opt_barrier_modes(nir_shader *shader)

Reply via email to