Add -hack-atomic-flag-barrier option - #1652
Conversation
|
Can you link to some spec sections that say this. It's been a long time since I've looked at the OpenCL memory model. |
|
Here are the relevant specification sections covering both the OpenCL memory model requirements and why Vulkan SPIR-V under GLSL450 requires explicit 1. OpenCL SpecificationA. Atomic Memory Orders Govern Regular (Non-Atomic) MemoryIn the OpenCL C 3.0 Specification, Section 6.15.2 "Order and Consistency":
And for
B. Happens-Before & Visibility Across ThreadsIn the OpenCL API Specification, Section 3.3.4 "Memory Consistency Model":
2. Vulkan SPIR-V SpecificationA. Memory Semantics Definition in SPIR-VIn the SPIR-V Specification, Section 3.25 "Memory Semantics ":
B. Vulkan GLSL450 Memory Model and Cache CoherencyIn the Vulkan Specification, Appendix "Vulkan Environment for SPIR-V - Memory Model" and Section 15.6 "Shader Memory Access Ordering": Under the standard Vulkan GLSL450 memory model (
On GPU architectures with non-coherent L1 caches and store buffers (such as NVIDIA), atomic instructions bypass L1 and go directly to L2/device memory, whereas ordinary buffer loads/stores go through non-coherent per-SM L1 caches. In the GLSL450 model, drivers only insert the required cache flush/invalidate instructions (e.g., Therefore, to guarantee that non-atomic global/local memory modifications sequenced before an atomic release are visible to threads after a corresponding atomic acquire (as mandated by the OpenCL C memory model), an explicit |
bd53c01 to
8946e89
Compare
|
In Vulkan, it should be equivalent to write Or: The declared memory model doesn't change Vulkan's behaviour. It changes what synchronizations can be expressed and how some properties are expressed. Here are two litmus tests I wrote for the Vulkan memory model in Alloy: The model says this is always race free. Using fences This is also always race free. When the memory model is GLSL450, coherence takes the place of availability and visibility (and non-private). Workgroup is always coherent and storage buffers must be marked as coherent. Note: the non-atomic memory accesses could be in a different storage class as long as the atomics/fences include that storage class in their semantics. E.g. put x in sc1 and add semsc1 to the acq and rel instructions. So it don't really follow why we'd need both an ordered atomic and a fence. Are we not marking the right buffers as coherent? Do we not include the correct semantics on the atomic? Are you certain this is not just a driver bug? Am I misunderstanding your description of the problem? |
Under the SPIR-V and Vulkan memory model specifications, OpAtomic*
instructions with acquire/release semantics already establish
happens-before ordering for regular memory accesses across threads.
However, some drivers (e.g. under the GLSL450 memory model) fail to
properly enforce this ordering for atomic_flag operations without
explicit memory barriers.
To work around such driver issues, add a new compiler option
-hack-atomic-flag-barrier:
- In replaceAtomicFlagClear: emit an OpMemoryBarrier with Release
semantics immediately prior to OpAtomicStore when release ordering
is requested (memory_order_release, memory_order_seq_cst, or default).
- In replaceAtomicFlagTestAndSet:
- Emit an OpMemoryBarrier with Release semantics immediately prior
to OpAtomicExchange when release ordering is requested
(memory_order_release, memory_order_acq_rel, memory_order_seq_cst,
or default).
- Emit an OpMemoryBarrier with Acquire semantics immediately after
OpAtomicExchange when acquire ordering is requested
(memory_order_acquire, memory_order_acq_rel, memory_order_seq_cst,
or default).
- Do not emit OpMemoryBarrier when memory_order_relaxed is specified,
as Vulkan SPIR-V forbids OpMemoryBarrier with semantics 0 (None).
|
Thanks for the explanation and Alloy tests! You're completely right that ordered atomics already order regular memory per spec, making the extra barrier redundant. Since this seems to be a driver bug, I've moved the |
8946e89 to
4f4332c
Compare
Under the SPIR-V and Vulkan memory model specifications, OpAtomic*
instructions with acquire/release semantics already establish
happens-before ordering for regular memory accesses across threads.
However, some drivers (e.g. under the GLSL450 memory model) fail to
properly enforce this ordering for atomic_flag operations without
explicit memory barriers.
To work around such driver issues, add a new compiler option
-hack-atomic-flag-barrier:
semantics immediately prior to OpAtomicStore when release ordering
is requested (memory_order_release, memory_order_seq_cst, or default).
to OpAtomicExchange when release ordering is requested
(memory_order_release, memory_order_acq_rel, memory_order_seq_cst,
or default).
OpAtomicExchange when acquire ordering is requested
(memory_order_acquire, memory_order_acq_rel, memory_order_seq_cst,
or default).
as Vulkan SPIR-V forbids OpMemoryBarrier with semantics 0 (None).