[Mesa-dev] [PATCH 42/44] spirv: Rework barriers

Jason Ekstrand jason at jlekstrand.net
Tue Sep 5 15:54:45 UTC 2017


On Tue, Sep 5, 2017 at 8:33 AM, Connor Abbott <cwabbott0 at gmail.com> wrote:

> As a quick drive-by, yeah, I noticed this too, and it's going to
> require fixes to radv to not break things since none of the other NIR
> opcodes are hooked up (this will be needed for the NIR path in
> radeonsi too, since GLSL-to-NIR already uses those opcodes).
>

Thanks for pointing that out!  Dave, Bas, would either of you mind getting
those properly hooked up?  As a side-note, this patch also made me consider
re-working the NIR barrier intrinsics to be a bit more SPIR-V like.

--Jason


> On Tue, Sep 5, 2017 at 11:13 AM, Jason Ekstrand <jason at jlekstrand.net>
> wrote:
> > Our previous handling of barriers always used the big hammer and didn't
> > correctly emit memory barriers when specified along with a control
> > barrier.  This commit completely reworks the way we emit barriers to
> > make things both more precise and more correct.
> > ---
> >  src/compiler/spirv/spirv_to_nir.c | 132 ++++++++++++++++++++++++++++++
> ++------
> >  1 file changed, 114 insertions(+), 18 deletions(-)
> >
> > diff --git a/src/compiler/spirv/spirv_to_nir.c
> b/src/compiler/spirv/spirv_to_nir.c
> > index 8653685..6fb27cb 100644
> > --- a/src/compiler/spirv/spirv_to_nir.c
> > +++ b/src/compiler/spirv/spirv_to_nir.c
> > @@ -2570,36 +2570,132 @@ 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 */
> > +   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 */
> > +   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)
> >  {
> > -   nir_intrinsic_op intrinsic_op;
> >     switch (opcode) {
> >     case SpvOpEmitVertex:
> >     case SpvOpEmitStreamVertex:
> > -      intrinsic_op = nir_intrinsic_emit_vertex;
> > -      break;
> >     case SpvOpEndPrimitive:
> > -   case SpvOpEndStreamPrimitive:
> > -      intrinsic_op = nir_intrinsic_end_primitive;
> > -      break;
> > -   case SpvOpMemoryBarrier:
> > -      intrinsic_op = nir_intrinsic_memory_barrier;
> > -      break;
> > -   case SpvOpControlBarrier:
> > -      intrinsic_op = nir_intrinsic_barrier;
> > +   case SpvOpEndStreamPrimitive: {
> > +      nir_intrinsic_op intrinsic_op;
> > +      switch (opcode) {
> > +      case SpvOpEmitVertex:
> > +      case SpvOpEmitStreamVertex:
> > +         intrinsic_op = nir_intrinsic_emit_vertex;
> > +         break;
> > +      case SpvOpEndPrimitive:
> > +      case SpvOpEndStreamPrimitive:
> > +         intrinsic_op = nir_intrinsic_end_primitive;
> > +         break;
> > +      default:
> > +         unreachable("Invalid opcode");
> > +      }
> > +
> > +      nir_intrinsic_instr *intrin =
> > +         nir_intrinsic_instr_create(b->shader, intrinsic_op);
> > +
> > +      switch (opcode) {
> > +      case SpvOpEmitStreamVertex:
> > +      case SpvOpEndStreamPrimitive:
> > +         nir_intrinsic_set_stream_id(intrin, w[1]);
> > +         break;
> > +      default:
> > +         break;
> > +      }
> > +
> > +      nir_builder_instr_insert(&b->nb, &intrin->instr);
> >        break;
> > -   default:
> > -      unreachable("unknown barrier instruction");
> >     }
> >
> > -   nir_intrinsic_instr *intrin =
> > -      nir_intrinsic_instr_create(b->shader, intrinsic_op);
> > +   case SpvOpMemoryBarrier: {
> > +      SpvScope scope = vtn_constant_value(b, w[1])->values[0].u32[0];
> > +      SpvMemorySemanticsMask semantics =
> > +         vtn_constant_value(b, w[2])->values[0].u32[0];
> > +      vtn_emit_memory_barrier(b, scope, semantics);
> > +      return;
> > +   }
> > +
> > +   case SpvOpControlBarrier: {
> > +      SpvScope execution_scope =
> > +         vtn_constant_value(b, w[1])->values[0].u32[0];
> > +      if (execution_scope == SpvScopeWorkgroup)
> > +         vtn_emit_barrier(b, nir_intrinsic_barrier);
> >
> > -   if (opcode == SpvOpEmitStreamVertex || opcode ==
> SpvOpEndStreamPrimitive)
> > -      nir_intrinsic_set_stream_id(intrin, w[1]);
> > +      SpvScope memory_scope =
> > +         vtn_constant_value(b, w[2])->values[0].u32[0];
> > +      SpvMemorySemanticsMask memory_semantics =
> > +         vtn_constant_value(b, w[3])->values[0].u32[0];
> > +      vtn_emit_memory_barrier(b, memory_scope, memory_semantics);
> > +      break;
> > +   }
> >
> > -   nir_builder_instr_insert(&b->nb, &intrin->instr);
> > +   default:
> > +      unreachable("unknown barrier instruction");
> > +   }
> >  }
> >
> >  static unsigned
> > --
> > 2.5.0.400.gff86faf
> >
> > _______________________________________________
> > mesa-dev mailing list
> > mesa-dev at lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/mesa-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20170905/057cbc30/attachment-0001.html>


More information about the mesa-dev mailing list