<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>