glsl: Implement use_scoped_barrier option for lowering memory barriers
When the option is enabled, lower memory barriers to the unified nir_intrinsic_scoped_barrier. The translation of the following is based on https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_gl_spirv.txt - memoryBarrier() - memoryBarrierBuffer() - memoryBarrierImage() - memoryBarrierShared() - groupMemoryBarrier() Also use scoped barrier for the memory counterparts of the GLSL (control) barrier() when the option is enabled. The execution part of a (control) barrier() remains using the old intrinsic. For memoryBarrierAtomicCounter() there's no corresponding nir_var_atomic_counter mode. Since atomic counters are lowered to SSBOs, use the nir_var_mem_ssbo mode in the scoped barrier instead. Reviewed-by: Faith Ekstrand <faith.ekstrand@collabora.com> Acked-by: Rob Clark <robclark@freedesktop.org> Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/3339>
This commit is contained in:
@@ -1085,7 +1085,9 @@ nir_visitor::visit(ir_call *ir)
|
|||||||
op = nir_intrinsic_image_deref_atomic_dec_wrap;
|
op = nir_intrinsic_image_deref_atomic_dec_wrap;
|
||||||
break;
|
break;
|
||||||
case ir_intrinsic_memory_barrier:
|
case ir_intrinsic_memory_barrier:
|
||||||
op = nir_intrinsic_memory_barrier;
|
op = shader->options->use_scoped_barrier
|
||||||
|
? nir_intrinsic_scoped_barrier
|
||||||
|
: nir_intrinsic_memory_barrier;
|
||||||
break;
|
break;
|
||||||
case ir_intrinsic_image_size:
|
case ir_intrinsic_image_size:
|
||||||
op = nir_intrinsic_image_deref_size;
|
op = nir_intrinsic_image_deref_size;
|
||||||
@@ -1106,19 +1108,29 @@ nir_visitor::visit(ir_call *ir)
|
|||||||
op = nir_intrinsic_end_invocation_interlock;
|
op = nir_intrinsic_end_invocation_interlock;
|
||||||
break;
|
break;
|
||||||
case ir_intrinsic_group_memory_barrier:
|
case ir_intrinsic_group_memory_barrier:
|
||||||
op = nir_intrinsic_group_memory_barrier;
|
op = shader->options->use_scoped_barrier
|
||||||
|
? nir_intrinsic_scoped_barrier
|
||||||
|
: nir_intrinsic_group_memory_barrier;
|
||||||
break;
|
break;
|
||||||
case ir_intrinsic_memory_barrier_atomic_counter:
|
case ir_intrinsic_memory_barrier_atomic_counter:
|
||||||
op = nir_intrinsic_memory_barrier_atomic_counter;
|
op = shader->options->use_scoped_barrier
|
||||||
|
? nir_intrinsic_scoped_barrier
|
||||||
|
: nir_intrinsic_memory_barrier_atomic_counter;
|
||||||
break;
|
break;
|
||||||
case ir_intrinsic_memory_barrier_buffer:
|
case ir_intrinsic_memory_barrier_buffer:
|
||||||
op = nir_intrinsic_memory_barrier_buffer;
|
op = shader->options->use_scoped_barrier
|
||||||
|
? nir_intrinsic_scoped_barrier
|
||||||
|
: nir_intrinsic_memory_barrier_buffer;
|
||||||
break;
|
break;
|
||||||
case ir_intrinsic_memory_barrier_image:
|
case ir_intrinsic_memory_barrier_image:
|
||||||
op = nir_intrinsic_memory_barrier_image;
|
op = shader->options->use_scoped_barrier
|
||||||
|
? nir_intrinsic_scoped_barrier
|
||||||
|
: nir_intrinsic_memory_barrier_image;
|
||||||
break;
|
break;
|
||||||
case ir_intrinsic_memory_barrier_shared:
|
case ir_intrinsic_memory_barrier_shared:
|
||||||
op = nir_intrinsic_memory_barrier_shared;
|
op = shader->options->use_scoped_barrier
|
||||||
|
? nir_intrinsic_scoped_barrier
|
||||||
|
: nir_intrinsic_memory_barrier_shared;
|
||||||
break;
|
break;
|
||||||
case ir_intrinsic_shared_load:
|
case ir_intrinsic_shared_load:
|
||||||
op = nir_intrinsic_load_shared;
|
op = nir_intrinsic_load_shared;
|
||||||
@@ -1437,6 +1449,62 @@ nir_visitor::visit(ir_call *ir)
|
|||||||
case nir_intrinsic_memory_barrier_shared:
|
case nir_intrinsic_memory_barrier_shared:
|
||||||
nir_builder_instr_insert(&b, &instr->instr);
|
nir_builder_instr_insert(&b, &instr->instr);
|
||||||
break;
|
break;
|
||||||
|
case nir_intrinsic_scoped_barrier: {
|
||||||
|
/* The nir_intrinsic_scoped_barrier follows the general
|
||||||
|
* semantics of SPIR-V memory barriers, so this and other memory
|
||||||
|
* barriers use the mapping based on GLSL->SPIR-V from
|
||||||
|
*
|
||||||
|
* https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_gl_spirv.txt
|
||||||
|
*/
|
||||||
|
nir_scope scope;
|
||||||
|
unsigned modes;
|
||||||
|
switch (ir->callee->intrinsic_id) {
|
||||||
|
case ir_intrinsic_memory_barrier:
|
||||||
|
scope = NIR_SCOPE_DEVICE;
|
||||||
|
modes = nir_var_image |
|
||||||
|
nir_var_mem_ssbo |
|
||||||
|
nir_var_mem_shared |
|
||||||
|
nir_var_mem_global;
|
||||||
|
break;
|
||||||
|
case ir_intrinsic_memory_barrier_buffer:
|
||||||
|
scope = NIR_SCOPE_DEVICE;
|
||||||
|
modes = nir_var_mem_ssbo |
|
||||||
|
nir_var_mem_global;
|
||||||
|
break;
|
||||||
|
case ir_intrinsic_memory_barrier_image:
|
||||||
|
scope = NIR_SCOPE_DEVICE;
|
||||||
|
modes = nir_var_image;
|
||||||
|
break;
|
||||||
|
case ir_intrinsic_memory_barrier_shared:
|
||||||
|
/* Both ARB_gl_spirv and glslang lower this to Device scope, so
|
||||||
|
* follow their lead. Note GL_KHR_vulkan_glsl also does
|
||||||
|
* something similar.
|
||||||
|
*/
|
||||||
|
scope = NIR_SCOPE_DEVICE;
|
||||||
|
modes = nir_var_mem_shared;
|
||||||
|
break;
|
||||||
|
case ir_intrinsic_group_memory_barrier:
|
||||||
|
scope = NIR_SCOPE_WORKGROUP;
|
||||||
|
modes = nir_var_image |
|
||||||
|
nir_var_mem_ssbo |
|
||||||
|
nir_var_mem_shared |
|
||||||
|
nir_var_mem_global;
|
||||||
|
break;
|
||||||
|
case ir_intrinsic_memory_barrier_atomic_counter:
|
||||||
|
/* There's no nir_var_atomic_counter, but since atomic counters are lowered
|
||||||
|
* to SSBOs, we use nir_var_mem_ssbo instead.
|
||||||
|
*/
|
||||||
|
scope = NIR_SCOPE_DEVICE;
|
||||||
|
modes = nir_var_mem_ssbo;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
unreachable("invalid intrinsic id for memory barrier");
|
||||||
|
}
|
||||||
|
|
||||||
|
nir_scoped_memory_barrier(&b, scope, NIR_MEMORY_ACQ_REL,
|
||||||
|
(nir_variable_mode)modes);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case nir_intrinsic_shader_clock:
|
case nir_intrinsic_shader_clock:
|
||||||
nir_ssa_dest_init(&instr->instr, &instr->dest, 2, 32, NULL);
|
nir_ssa_dest_init(&instr->instr, &instr->dest, 2, 32, NULL);
|
||||||
nir_intrinsic_set_memory_scope(instr, NIR_SCOPE_SUBGROUP);
|
nir_intrinsic_set_memory_scope(instr, NIR_SCOPE_SUBGROUP);
|
||||||
@@ -2693,10 +2761,20 @@ nir_visitor::visit(ir_dereference_array *ir)
|
|||||||
void
|
void
|
||||||
nir_visitor::visit(ir_barrier *)
|
nir_visitor::visit(ir_barrier *)
|
||||||
{
|
{
|
||||||
if (shader->info.stage == MESA_SHADER_COMPUTE)
|
if (shader->options->use_scoped_barrier) {
|
||||||
nir_memory_barrier_shared(&b);
|
if (shader->info.stage == MESA_SHADER_COMPUTE) {
|
||||||
else if (shader->info.stage == MESA_SHADER_TESS_CTRL)
|
nir_scoped_memory_barrier(&b, NIR_SCOPE_WORKGROUP, NIR_MEMORY_ACQ_REL,
|
||||||
nir_memory_barrier_tcs_patch(&b);
|
nir_var_mem_shared);
|
||||||
|
} else if (shader->info.stage == MESA_SHADER_TESS_CTRL) {
|
||||||
|
nir_scoped_memory_barrier(&b, NIR_SCOPE_WORKGROUP, NIR_MEMORY_ACQ_REL,
|
||||||
|
nir_var_shader_out);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (shader->info.stage == MESA_SHADER_COMPUTE)
|
||||||
|
nir_memory_barrier_shared(&b);
|
||||||
|
else if (shader->info.stage == MESA_SHADER_TESS_CTRL)
|
||||||
|
nir_memory_barrier_tcs_patch(&b);
|
||||||
|
}
|
||||||
|
|
||||||
nir_control_barrier(&b);
|
nir_control_barrier(&b);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user