On Mon, Sep 10, 2018 at 8:05 PM Jason Ekstrand <ja...@jlekstrand.net> wrote: > > --- > src/compiler/spirv/spirv_to_nir.c | 170 ++++++++++++++++++------------ > 1 file changed, 103 insertions(+), 67 deletions(-) > > diff --git a/src/compiler/spirv/spirv_to_nir.c > b/src/compiler/spirv/spirv_to_nir.c > index 96224354057..3378641513c 100644 > --- a/src/compiler/spirv/spirv_to_nir.c > +++ b/src/compiler/spirv/spirv_to_nir.c > @@ -2314,6 +2314,79 @@ fill_common_atomic_sources(struct vtn_builder *b, > SpvOp opcode, > } > } > > +static void > +vtn_emit_barrier(struct vtn_builder *b, nir_intrinsic_op op) > +{ > + nir_intrinsic_instr *intrin = nir_intrinsic_instr_create(b->shader, op); > + nir_builder_instr_insert(&b->nb, &intrin->instr); > +} > + > +static void > +vtn_emit_memory_barrier(struct vtn_builder *b, SpvScope scope, > + SpvMemorySemanticsMask semantics) > +{ > + static const SpvMemorySemanticsMask all_memory_semantics = > + SpvMemorySemanticsUniformMemoryMask | > + SpvMemorySemanticsWorkgroupMemoryMask | > + SpvMemorySemanticsAtomicCounterMemoryMask | > + SpvMemorySemanticsImageMemoryMask | > + SpvMemorySemanticsOutputMemoryKHRMask | > + SpvMemorySemanticsMakeAvailableKHRMask | > + SpvMemorySemanticsMakeVisibleKHRMask; > + > + /* If we're not actually doing a memory barrier, bail */ > + if (!(semantics & all_memory_semantics)) > + return; > + > + /* GL and Vulkan don't have these */ > + vtn_assert(scope != SpvScopeCrossDevice); > + > + if (scope == SpvScopeSubgroup) > + return; /* Nothing to do here */
I don't think doing nothing here works for AMD, I think in some cases we can have some hardware reordering. +cc Marek to confirm. > + > + if (scope == SpvScopeWorkgroup) { > + vtn_emit_barrier(b, nir_intrinsic_group_memory_barrier); > + return; > + } > + > + /* There's only three scopes left */ > + vtn_assert(scope == SpvScopeInvocation || > + scope == SpvScopeDevice || > + scope == SpvScopeQueueFamilyKHR); > + > + if ((semantics & all_memory_semantics) == all_memory_semantics) { > + vtn_emit_barrier(b, nir_intrinsic_memory_barrier); > + return; > + } > + > + /* Issue a bunch of more specific barriers */ > + uint32_t bits = semantics; > + while (bits) { > + SpvMemorySemanticsMask semantic = 1 << u_bit_scan(&bits); > + switch (semantic) { > + case SpvMemorySemanticsUniformMemoryMask: > + vtn_emit_barrier(b, nir_intrinsic_memory_barrier_buffer); > + break; > + case SpvMemorySemanticsWorkgroupMemoryMask: > + vtn_emit_barrier(b, nir_intrinsic_memory_barrier_shared); > + break; > + case SpvMemorySemanticsAtomicCounterMemoryMask: > + vtn_emit_barrier(b, nir_intrinsic_memory_barrier_atomic_counter); > + break; > + case SpvMemorySemanticsImageMemoryMask: > + vtn_emit_barrier(b, nir_intrinsic_memory_barrier_image); > + break; > + case SpvMemorySemanticsOutputMemoryKHRMask: > + case SpvMemorySemanticsMakeAvailableKHRMask: > + case SpvMemorySemanticsMakeVisibleKHRMask: > + vtn_emit_barrier(b, nir_intrinsic_memory_barrier); > + return; > + default: > + break;; > + } > + } > +} > + > static nir_ssa_def * > get_image_coord(struct vtn_builder *b, uint32_t value) > { > @@ -2357,6 +2430,8 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode, > } > > struct vtn_image_pointer image; > + SpvScope scope = SpvScopeInvocation; > + SpvMemorySemanticsMask semantics = 0; > > switch (opcode) { > case SpvOpAtomicExchange: > @@ -2375,10 +2450,14 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode, > case SpvOpAtomicOr: > case SpvOpAtomicXor: > image = *vtn_value(b, w[3], vtn_value_type_image_pointer)->image; > + scope = vtn_constant_value(b, w[4])->values[0].u32[0]; > + semantics = vtn_constant_value(b, w[5])->values[0].u32[0]; > break; > > case SpvOpAtomicStore: > image = *vtn_value(b, w[1], vtn_value_type_image_pointer)->image; > + scope = vtn_constant_value(b, w[2])->values[0].u32[0]; > + semantics = vtn_constant_value(b, w[3])->values[0].u32[0]; > break; > > case SpvOpImageQuerySize: > @@ -2417,6 +2496,8 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode, > vtn_fail("Invalid image opcode"); > } > > + semantics |= SpvMemorySemanticsImageMemoryMask; > + > nir_intrinsic_op op; > switch (opcode) { > #define OP(S, N) case SpvOp##S: op = nir_intrinsic_image_deref_##N; break; > @@ -2493,6 +2574,9 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode, > vtn_fail("Invalid image opcode"); > } > > + if (opcode == SpvOpAtomicLoad) > + vtn_emit_memory_barrier(b, scope, semantics); > + > if (opcode != SpvOpImageWrite && opcode != SpvOpAtomicStore) { > struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_ssa); > struct vtn_type *type = vtn_value(b, w[1], vtn_value_type_type)->type; > @@ -2516,6 +2600,9 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode, > } else { > nir_builder_instr_insert(&b->nb, &intrin->instr); > } > + > + if (opcode == SpvOpAtomicStore) > + vtn_emit_memory_barrier(b, scope, semantics); > } > > static nir_intrinsic_op > @@ -2634,6 +2721,8 @@ vtn_handle_atomics(struct vtn_builder *b, SpvOp opcode, > { > struct vtn_pointer *ptr; > nir_intrinsic_instr *atomic; > + SpvScope scope; > + SpvMemorySemanticsMask semantics; > > switch (opcode) { > case SpvOpAtomicLoad: > @@ -2652,20 +2741,27 @@ vtn_handle_atomics(struct vtn_builder *b, SpvOp > opcode, > case SpvOpAtomicOr: > case SpvOpAtomicXor: > ptr = vtn_value(b, w[3], vtn_value_type_pointer)->pointer; > + scope = vtn_constant_value(b, w[4])->values[0].u32[0]; > + semantics = vtn_constant_value(b, w[5])->values[0].u32[0]; > break; > > case SpvOpAtomicStore: > ptr = vtn_value(b, w[1], vtn_value_type_pointer)->pointer; > + scope = vtn_constant_value(b, w[2])->values[0].u32[0]; > + semantics = vtn_constant_value(b, w[3])->values[0].u32[0]; > break; > > default: > vtn_fail("Invalid SPIR-V atomic"); > } > > - /* > - SpvScope scope = w[4]; > - SpvMemorySemanticsMask semantics = w[5]; > - */ > + if (ptr->mode == vtn_variable_mode_workgroup) > + semantics |= SpvMemorySemanticsWorkgroupMemoryMask; > + else > + semantics |= SpvMemorySemanticsUniformMemoryMask; > + > + if (opcode == SpvOpAtomicLoad) > + vtn_emit_memory_barrier(b, scope, semantics); > > /* uniform as "atomic counter uniform" */ > if (ptr->mode == vtn_variable_mode_uniform) { > @@ -2825,6 +2921,9 @@ vtn_handle_atomics(struct vtn_builder *b, SpvOp opcode, > } > > nir_builder_instr_insert(&b->nb, &atomic->instr); > + > + if (opcode != SpvOpAtomicStore) > + vtn_emit_memory_barrier(b, scope, semantics); > } > > static nir_alu_instr * > @@ -3129,69 +3228,6 @@ vtn_handle_composite(struct vtn_builder *b, SpvOp > opcode, > } > } > > -static void > -vtn_emit_barrier(struct vtn_builder *b, nir_intrinsic_op op) > -{ > - nir_intrinsic_instr *intrin = nir_intrinsic_instr_create(b->shader, op); > - nir_builder_instr_insert(&b->nb, &intrin->instr); > -} > - > -static void > -vtn_emit_memory_barrier(struct vtn_builder *b, SpvScope scope, > - SpvMemorySemanticsMask semantics) > -{ > - static const SpvMemorySemanticsMask all_memory_semantics = > - SpvMemorySemanticsUniformMemoryMask | > - SpvMemorySemanticsWorkgroupMemoryMask | > - SpvMemorySemanticsAtomicCounterMemoryMask | > - SpvMemorySemanticsImageMemoryMask; > - > - /* If we're not actually doing a memory barrier, bail */ > - if (!(semantics & all_memory_semantics)) > - return; > - > - /* GL and Vulkan don't have these */ > - vtn_assert(scope != SpvScopeCrossDevice); > - > - if (scope == SpvScopeSubgroup) > - return; /* Nothing to do here */ > - > - if (scope == SpvScopeWorkgroup) { > - vtn_emit_barrier(b, nir_intrinsic_group_memory_barrier); > - return; > - } > - > - /* There's only two scopes thing left */ > - vtn_assert(scope == SpvScopeInvocation || scope == SpvScopeDevice); > - > - if ((semantics & all_memory_semantics) == all_memory_semantics) { > - vtn_emit_barrier(b, nir_intrinsic_memory_barrier); > - return; > - } > - > - /* Issue a bunch of more specific barriers */ > - uint32_t bits = semantics; > - while (bits) { > - SpvMemorySemanticsMask semantic = 1 << u_bit_scan(&bits); > - switch (semantic) { > - case SpvMemorySemanticsUniformMemoryMask: > - vtn_emit_barrier(b, nir_intrinsic_memory_barrier_buffer); > - break; > - case SpvMemorySemanticsWorkgroupMemoryMask: > - vtn_emit_barrier(b, nir_intrinsic_memory_barrier_shared); > - break; > - case SpvMemorySemanticsAtomicCounterMemoryMask: > - vtn_emit_barrier(b, nir_intrinsic_memory_barrier_atomic_counter); > - break; > - case SpvMemorySemanticsImageMemoryMask: > - vtn_emit_barrier(b, nir_intrinsic_memory_barrier_image); > - break; > - default: > - break;; > - } > - } > -} > - > static void > vtn_handle_barrier(struct vtn_builder *b, SpvOp opcode, > const uint32_t *w, unsigned count) > -- > 2.17.1 > > _______________________________________________ > mesa-dev mailing list > mesa-dev@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/mesa-dev _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev