Module: Mesa Branch: main Commit: 4f892ecc1e143c42a41d32450262e799d4d152af URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=4f892ecc1e143c42a41d32450262e799d4d152af
Author: Karol Herbst <kher...@redhat.com> Date: Tue Oct 24 19:34:10 2023 +0200 zink: emit MemoryAccess flags for coherent global load/stores Makes global load/stores coherent on a device level if requested by the shader. Signed-off-by: Karol Herbst <kher...@redhat.com> Acked-by: Mike Blumenkrantz <michael.blumenkra...@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25937> --- .../drivers/zink/nir_to_spirv/nir_to_spirv.c | 6 +++-- .../drivers/zink/nir_to_spirv/spirv_builder.c | 30 +++++++++++++++++----- .../drivers/zink/nir_to_spirv/spirv_builder.h | 4 +-- 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c index 3c8d2a53af3..c30426aba83 100644 --- a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c +++ b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c @@ -2539,6 +2539,7 @@ emit_load_push_const(struct ntv_context *ctx, nir_intrinsic_instr *intr) static void emit_load_global(struct ntv_context *ctx, nir_intrinsic_instr *intr) { + bool coherent = ctx->sinfo->have_vulkan_memory_model && nir_intrinsic_access(intr) & ACCESS_COHERENT; spirv_builder_emit_cap(&ctx->builder, SpvCapabilityPhysicalStorageBufferAddresses); SpvId dest_type = get_def_type(ctx, &intr->def, nir_type_uint); SpvId pointer_type = spirv_builder_type_pointer(&ctx->builder, @@ -2546,13 +2547,14 @@ emit_load_global(struct ntv_context *ctx, nir_intrinsic_instr *intr) dest_type); nir_alu_type atype; SpvId ptr = emit_bitcast(ctx, pointer_type, get_src(ctx, &intr->src[0], &atype)); - SpvId result = spirv_builder_emit_load_aligned(&ctx->builder, dest_type, ptr, intr->def.bit_size / 8); + SpvId result = spirv_builder_emit_load_aligned(&ctx->builder, dest_type, ptr, intr->def.bit_size / 8, coherent); store_def(ctx, &intr->def, result, nir_type_uint); } static void emit_store_global(struct ntv_context *ctx, nir_intrinsic_instr *intr) { + bool coherent = ctx->sinfo->have_vulkan_memory_model && nir_intrinsic_access(intr) & ACCESS_COHERENT; spirv_builder_emit_cap(&ctx->builder, SpvCapabilityPhysicalStorageBufferAddresses); unsigned bit_size = nir_src_bit_size(intr->src[0]); SpvId dest_type = get_uvec_type(ctx, bit_size, 1); @@ -2564,7 +2566,7 @@ emit_store_global(struct ntv_context *ctx, nir_intrinsic_instr *intr) if (atype != nir_type_uint) param = emit_bitcast(ctx, dest_type, param); SpvId ptr = emit_bitcast(ctx, pointer_type, get_src(ctx, &intr->src[1], &atype)); - spirv_builder_emit_store_aligned(&ctx->builder, ptr, param, bit_size / 8); + spirv_builder_emit_store_aligned(&ctx->builder, ptr, param, bit_size / 8, coherent); } static void diff --git a/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.c b/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.c index 68a55ee730c..60b14114415 100644 --- a/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.c +++ b/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.c @@ -470,9 +470,14 @@ spirv_builder_emit_load(struct spirv_builder *b, SpvId result_type, } SpvId -spirv_builder_emit_load_aligned(struct spirv_builder *b, SpvId result_type, SpvId pointer, unsigned alignment) +spirv_builder_emit_load_aligned(struct spirv_builder *b, SpvId result_type, SpvId pointer, unsigned alignment, bool coherent) { - return spirv_builder_emit_triop(b, SpvOpLoad, result_type, pointer, SpvMemoryAccessAlignedMask, alignment); + if (coherent) { + SpvId scope = spirv_builder_const_int(b, 32, SpvScopeDevice); + return spirv_builder_emit_quadop(b, SpvOpLoad, result_type, pointer, SpvMemoryAccessAlignedMask | SpvMemoryAccessNonPrivatePointerMask | SpvMemoryAccessMakePointerVisibleMask, alignment, scope); + } else { + return spirv_builder_emit_triop(b, SpvOpLoad, result_type, pointer, SpvMemoryAccessAlignedMask, alignment); + } } void @@ -485,14 +490,27 @@ spirv_builder_emit_store(struct spirv_builder *b, SpvId pointer, SpvId object) } void -spirv_builder_emit_store_aligned(struct spirv_builder *b, SpvId pointer, SpvId object, unsigned alignment) +spirv_builder_emit_store_aligned(struct spirv_builder *b, SpvId pointer, SpvId object, unsigned alignment, bool coherent) { - spirv_buffer_prepare(&b->instructions, b->mem_ctx, 5); - spirv_buffer_emit_word(&b->instructions, SpvOpStore | (5 << 16)); + unsigned size = 5; + SpvMemoryAccessMask mask = SpvMemoryAccessAlignedMask; + + if (coherent) { + mask |= SpvMemoryAccessNonPrivatePointerMask | SpvMemoryAccessMakePointerAvailableMask; + size++; + } + + spirv_buffer_prepare(&b->instructions, b->mem_ctx, size); + spirv_buffer_emit_word(&b->instructions, SpvOpStore | (size << 16)); spirv_buffer_emit_word(&b->instructions, pointer); spirv_buffer_emit_word(&b->instructions, object); - spirv_buffer_emit_word(&b->instructions, SpvMemoryAccessAlignedMask); + spirv_buffer_emit_word(&b->instructions, mask); spirv_buffer_emit_word(&b->instructions, alignment); + + if (coherent) { + SpvId scope = spirv_builder_const_int(b, 32, SpvScopeDevice); + spirv_buffer_emit_word(&b->instructions, scope); + } } void diff --git a/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.h b/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.h index dabf6f71440..2b9cac6fc2e 100644 --- a/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.h +++ b/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.h @@ -188,7 +188,7 @@ spirv_builder_emit_load(struct spirv_builder *b, SpvId result_type, SpvId pointer); SpvId -spirv_builder_emit_load_aligned(struct spirv_builder *b, SpvId result_type, SpvId pointer, unsigned alignment); +spirv_builder_emit_load_aligned(struct spirv_builder *b, SpvId result_type, SpvId pointer, unsigned alignment, bool coherent); void spirv_builder_emit_atomic_store(struct spirv_builder *b, SpvId pointer, SpvScope scope, SpvMemorySemanticsMask semantics, SpvId object); @@ -196,7 +196,7 @@ spirv_builder_emit_atomic_store(struct spirv_builder *b, SpvId pointer, SpvScope void spirv_builder_emit_store(struct spirv_builder *b, SpvId pointer, SpvId object); void -spirv_builder_emit_store_aligned(struct spirv_builder *b, SpvId pointer, SpvId object, unsigned alignment); +spirv_builder_emit_store_aligned(struct spirv_builder *b, SpvId pointer, SpvId object, unsigned alignment, bool coherent); SpvId spirv_builder_emit_access_chain(struct spirv_builder *b, SpvId result_type,