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

Reply via email to