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 <alyssa@rosenzweig.io>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24842>
This commit is contained in:
Kenneth Graunke
2023-08-21 18:55:13 -07:00
committed by Marge Bot
parent 7dd897e1cd
commit fc0aaa81ee
+14 -1
View File
@@ -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)