<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Tue, Sep 5, 2017 at 8:33 AM, Connor Abbott <span dir="ltr"><<a href="mailto:cwabbott0@gmail.com" target="_blank">cwabbott0@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">As a quick drive-by, yeah, I noticed this too, and it's going to<br>
require fixes to radv to not break things since none of the other NIR<br>
opcodes are hooked up (this will be needed for the NIR path in<br>
radeonsi too, since GLSL-to-NIR already uses those opcodes).<br><div><div class="h5"></div></div></blockquote><div><br></div><div>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.</div><div><br></div><div>--Jason<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="h5">
On Tue, Sep 5, 2017 at 11:13 AM, Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>> wrote:<br>
> Our previous handling of barriers always used the big hammer and didn't<br>
> correctly emit memory barriers when specified along with a control<br>
> barrier.  This commit completely reworks the way we emit barriers to<br>
> make things both more precise and more correct.<br>
> ---<br>
>  src/compiler/spirv/spirv_to_<wbr>nir.c | 132 ++++++++++++++++++++++++++++++<wbr>++------<br>
>  1 file changed, 114 insertions(+), 18 deletions(-)<br>
><br>
> diff --git a/src/compiler/spirv/spirv_to_<wbr>nir.c b/src/compiler/spirv/spirv_to_<wbr>nir.c<br>
> index 8653685..6fb27cb 100644<br>
> --- a/src/compiler/spirv/spirv_to_<wbr>nir.c<br>
> +++ b/src/compiler/spirv/spirv_to_<wbr>nir.c<br>
> @@ -2570,36 +2570,132 @@ vtn_handle_composite(struct vtn_builder *b, SpvOp opcode,<br>
>  }<br>
><br>
>  static void<br>
> +vtn_emit_barrier(struct vtn_builder *b, nir_intrinsic_op op)<br>
> +{<br>
> +   nir_intrinsic_instr *intrin = nir_intrinsic_instr_create(b-><wbr>shader, op);<br>
> +   nir_builder_instr_insert(&b-><wbr>nb, &intrin->instr);<br>
> +}<br>
> +<br>
> +static void<br>
> +vtn_emit_memory_barrier(<wbr>struct vtn_builder *b, SpvScope scope,<br>
> +                        SpvMemorySemanticsMask semantics)<br>
> +{<br>
> +   static const SpvMemorySemanticsMask all_memory_semantics =<br>
> +      SpvMemorySemanticsUniformMemor<wbr>yMask |<br>
> +      SpvMemorySemanticsWorkgroupMem<wbr>oryMask |<br>
> +      SpvMemorySemanticsAtomicCounte<wbr>rMemoryMask |<br>
> +      SpvMemorySemanticsImageMemoryM<wbr>ask;<br>
> +<br>
> +   /* If we're not actually doing a memory barrier, bail */<br>
> +   if (!(semantics & all_memory_semantics))<br>
> +      return;<br>
> +<br>
> +   /* GL and Vulkan don't have these */<br>
> +   assert(scope != SpvScopeCrossDevice);<br>
> +<br>
> +   if (scope == SpvScopeSubgroup)<br>
> +      return; /* Nothing to do here */<br>
> +<br>
> +   if (scope == SpvScopeWorkgroup) {<br>
> +      vtn_emit_barrier(b, nir_intrinsic_group_memory_<wbr>barrier);<br>
> +      return;<br>
> +   }<br>
> +<br>
> +   /* There's only two scopes thing left */<br>
> +   assert(scope == SpvScopeInvocation || scope == SpvScopeDevice);<br>
> +<br>
> +   if ((semantics & all_memory_semantics) == all_memory_semantics) {<br>
> +      vtn_emit_barrier(b, nir_intrinsic_memory_barrier);<br>
> +      return;<br>
> +   }<br>
> +<br>
> +   /* Issue a bunch of more specific barriers */<br>
> +   uint32_t bits = semantics;<br>
> +   while (bits) {<br>
> +      SpvMemorySemanticsMask semantic = 1 << u_bit_scan(&bits);<br>
> +      switch (semantic) {<br>
> +      case SpvMemorySemanticsUniformMemor<wbr>yMask:<br>
> +         vtn_emit_barrier(b, nir_intrinsic_memory_barrier_<wbr>buffer);<br>
> +         break;<br>
> +      case SpvMemorySemanticsWorkgroupMem<wbr>oryMask:<br>
> +         vtn_emit_barrier(b, nir_intrinsic_memory_barrier_<wbr>shared);<br>
> +         break;<br>
> +      case SpvMemorySemanticsAtomicCounte<wbr>rMemoryMask:<br>
> +         vtn_emit_barrier(b, nir_intrinsic_memory_barrier_<wbr>atomic_counter);<br>
> +         break;<br>
> +      case SpvMemorySemanticsImageMemoryM<wbr>ask:<br>
> +         vtn_emit_barrier(b, nir_intrinsic_memory_barrier_<wbr>image);<br>
> +         break;<br>
> +      default:<br>
> +         break;;<br>
> +      }<br>
> +   }<br>
> +}<br>
> +<br>
> +static void<br>
>  vtn_handle_barrier(struct vtn_builder *b, SpvOp opcode,<br>
>                     const uint32_t *w, unsigned count)<br>
>  {<br>
> -   nir_intrinsic_op intrinsic_op;<br>
>     switch (opcode) {<br>
>     case SpvOpEmitVertex:<br>
>     case SpvOpEmitStreamVertex:<br>
> -      intrinsic_op = nir_intrinsic_emit_vertex;<br>
> -      break;<br>
>     case SpvOpEndPrimitive:<br>
> -   case SpvOpEndStreamPrimitive:<br>
> -      intrinsic_op = nir_intrinsic_end_primitive;<br>
> -      break;<br>
> -   case SpvOpMemoryBarrier:<br>
> -      intrinsic_op = nir_intrinsic_memory_barrier;<br>
> -      break;<br>
> -   case SpvOpControlBarrier:<br>
> -      intrinsic_op = nir_intrinsic_barrier;<br>
> +   case SpvOpEndStreamPrimitive: {<br>
> +      nir_intrinsic_op intrinsic_op;<br>
> +      switch (opcode) {<br>
> +      case SpvOpEmitVertex:<br>
> +      case SpvOpEmitStreamVertex:<br>
> +         intrinsic_op = nir_intrinsic_emit_vertex;<br>
> +         break;<br>
> +      case SpvOpEndPrimitive:<br>
> +      case SpvOpEndStreamPrimitive:<br>
> +         intrinsic_op = nir_intrinsic_end_primitive;<br>
> +         break;<br>
> +      default:<br>
> +         unreachable("Invalid opcode");<br>
> +      }<br>
> +<br>
> +      nir_intrinsic_instr *intrin =<br>
> +         nir_intrinsic_instr_create(b-><wbr>shader, intrinsic_op);<br>
> +<br>
> +      switch (opcode) {<br>
> +      case SpvOpEmitStreamVertex:<br>
> +      case SpvOpEndStreamPrimitive:<br>
> +         nir_intrinsic_set_stream_id(<wbr>intrin, w[1]);<br>
> +         break;<br>
> +      default:<br>
> +         break;<br>
> +      }<br>
> +<br>
> +      nir_builder_instr_insert(&b-><wbr>nb, &intrin->instr);<br>
>        break;<br>
> -   default:<br>
> -      unreachable("unknown barrier instruction");<br>
>     }<br>
><br>
> -   nir_intrinsic_instr *intrin =<br>
> -      nir_intrinsic_instr_create(b-><wbr>shader, intrinsic_op);<br>
> +   case SpvOpMemoryBarrier: {<br>
> +      SpvScope scope = vtn_constant_value(b, w[1])->values[0].u32[0];<br>
> +      SpvMemorySemanticsMask semantics =<br>
> +         vtn_constant_value(b, w[2])->values[0].u32[0];<br>
> +      vtn_emit_memory_barrier(b, scope, semantics);<br>
> +      return;<br>
> +   }<br>
> +<br>
> +   case SpvOpControlBarrier: {<br>
> +      SpvScope execution_scope =<br>
> +         vtn_constant_value(b, w[1])->values[0].u32[0];<br>
> +      if (execution_scope == SpvScopeWorkgroup)<br>
> +         vtn_emit_barrier(b, nir_intrinsic_barrier);<br>
><br>
> -   if (opcode == SpvOpEmitStreamVertex || opcode == SpvOpEndStreamPrimitive)<br>
> -      nir_intrinsic_set_stream_id(<wbr>intrin, w[1]);<br>
> +      SpvScope memory_scope =<br>
> +         vtn_constant_value(b, w[2])->values[0].u32[0];<br>
> +      SpvMemorySemanticsMask memory_semantics =<br>
> +         vtn_constant_value(b, w[3])->values[0].u32[0];<br>
> +      vtn_emit_memory_barrier(b, memory_scope, memory_semantics);<br>
> +      break;<br>
> +   }<br>
><br>
> -   nir_builder_instr_insert(&b-><wbr>nb, &intrin->instr);<br>
> +   default:<br>
> +      unreachable("unknown barrier instruction");<br>
> +   }<br>
>  }<br>
><br>
>  static unsigned<br>
> --<br>
> 2.5.0.400.gff86faf<br>
><br>
</div></div>> ______________________________<wbr>_________________<br>
> mesa-dev mailing list<br>
> <a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
> <a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev" rel="noreferrer" target="_blank">https://lists.freedesktop.org/<wbr>mailman/listinfo/mesa-dev</a><br>
</blockquote></div><br></div></div>