spirv_std/arch/
barrier.rs

1#[cfg(target_arch = "spirv")]
2use core::arch::asm;
3
4/// Wait for other invocations of this module to reach the current point
5/// of execution.
6///
7/// All invocations of this module within Execution scope reach this point of
8/// execution before any invocation proceeds beyond it.
9///
10/// When Execution is [`crate::memory::Scope::Workgroup`] or larger, behavior is
11/// undefined unless all invocations within Execution execute the same dynamic
12/// instance of this instruction. When Execution is Subgroup or Invocation, the
13/// behavior of this instruction in non-uniform control flow is defined by the
14/// client API.
15///
16/// If [`crate::memory::Semantics`] is not [`crate::memory::Semantics::NONE`],
17/// this instruction also serves as an [`memory_barrier`] function call, and
18/// also performs and adheres to the description and semantics of an
19/// [`memory_barrier`] function with the same `MEMORY` and `SEMANTICS` operands.
20/// This allows atomically specifying both a control barrier and a memory
21/// barrier (that is, without needing two instructions). If
22/// [`crate::memory::Semantics`] is [`crate::memory::Semantics::NONE`], `MEMORY`
23/// is ignored.
24///
25/// Before SPIRV-V version 1.3, it is only valid to use this instruction with
26/// `TessellationControl`, `GLCompute`, or `Kernel` execution models. There is
27/// no such restriction starting with version 1.3.
28///
29/// If used with the `TessellationControl` execution model, it also implicitly
30/// synchronizes the `output` storage class: Writes to `output` variables
31/// performed by any invocation executed prior to a [`control_barrier`] are
32/// visible to any other invocation proceeding beyond that [`control_barrier`].
33#[spirv_std_macros::gpu_only]
34#[doc(alias = "OpControlBarrier")]
35#[inline]
36pub unsafe fn control_barrier<
37    const EXECUTION: u32, // Scope
38    const MEMORY: u32,    // Scope
39    const SEMANTICS: u32, // Semantics
40>() {
41    unsafe {
42        asm! {
43            "%u32 = OpTypeInt 32 0",
44            "%execution = OpConstant %u32 {execution}",
45            "%memory = OpConstant %u32 {memory}",
46            "%semantics = OpConstant %u32 {semantics}",
47            "OpControlBarrier %execution %memory %semantics",
48            execution = const EXECUTION,
49            memory = const MEMORY,
50            semantics = const SEMANTICS,
51        }
52    }
53}
54
55/// Control the order that memory accesses are observed.
56///
57/// Ensures that memory accesses issued before this instruction are observed
58/// before memory accesses issued after this instruction. This control is
59/// ensured only for memory accesses issued by this invocation and observed by
60/// another invocation executing within `MEMORY` scope. If the `vulkan` memory
61/// model is declared, this ordering only applies to memory accesses that
62/// use the `NonPrivatePointer` memory operand or `NonPrivateTexel`
63/// image operand.
64///
65/// `SEMANTICS` declares what kind of memory is being controlled and what kind
66/// of control to apply.
67///
68/// To execute both a memory barrier and a control barrier,
69/// see [`control_barrier`].
70#[spirv_std_macros::gpu_only]
71#[doc(alias = "OpMemoryBarrier")]
72#[inline]
73pub unsafe fn memory_barrier<
74    const MEMORY: u32,    // Scope
75    const SEMANTICS: u32, // Semantics
76>() {
77    unsafe {
78        asm! {
79            "%u32 = OpTypeInt 32 0",
80            "%memory = OpConstant %u32 {memory}",
81            "%semantics = OpConstant %u32 {semantics}",
82            "OpMemoryBarrier %memory %semantics",
83            memory = const MEMORY,
84            semantics = const SEMANTICS,
85        }
86    }
87}
88
89/// Blocks execution of all threads in a group until all group shared accesses have been completed.
90///
91/// This is an exact implementation of `GroupMemoryBarrier()`.
92///
93/// From <https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/groupmemorybarrier>
94#[spirv_std_macros::gpu_only]
95#[inline]
96pub unsafe fn workgroup_memory_barrier() {
97    unsafe {
98        memory_barrier::<
99            { crate::memory::Scope::Workgroup as u32 },
100            {
101                crate::memory::Semantics::WORKGROUP_MEMORY.bits()
102                    | crate::memory::Semantics::ACQUIRE_RELEASE.bits()
103            },
104        >();
105    }
106}
107
108/// Blocks execution of all threads in a group until all group shared accesses have been completed and all threads in the group have reached this call.
109///
110/// This is an exact implementation of `GroupMemoryBarrierWithGroupSync()`.
111///
112/// From <https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/groupmemorybarrierwithgroupsync>
113#[spirv_std_macros::gpu_only]
114#[inline]
115pub unsafe fn workgroup_memory_barrier_with_group_sync() {
116    unsafe {
117        control_barrier::<
118            { crate::memory::Scope::Workgroup as u32 },
119            { crate::memory::Scope::Workgroup as u32 },
120            {
121                crate::memory::Semantics::WORKGROUP_MEMORY.bits()
122                    | crate::memory::Semantics::ACQUIRE_RELEASE.bits()
123            },
124        >();
125    }
126}
127
128/// Blocks execution of all threads in a group until all device memory accesses have been completed.
129///
130/// This is an exact implementation of `DeviceMemoryBarrier()`.
131///
132/// From <https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/devicememorybarrier>
133#[spirv_std_macros::gpu_only]
134#[inline]
135pub unsafe fn device_memory_barrier() {
136    unsafe {
137        memory_barrier::<
138            { crate::memory::Scope::Device as u32 },
139            {
140                crate::memory::Semantics::IMAGE_MEMORY.bits()
141                    | crate::memory::Semantics::UNIFORM_MEMORY.bits()
142                    | crate::memory::Semantics::ACQUIRE_RELEASE.bits()
143            },
144        >();
145    }
146}
147
148/// Blocks execution of all threads in a group until all device memory accesses have been completed and all threads in the group have reached this call.
149///
150/// This is an exact implementation of `DeviceMemoryBarrierWithGroupSync()`.
151///
152/// From <https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/devicememorybarrierwithgroupsync>
153#[spirv_std_macros::gpu_only]
154#[inline]
155pub unsafe fn device_memory_barrier_with_group_sync() {
156    unsafe {
157        control_barrier::<
158            { crate::memory::Scope::Workgroup as u32 },
159            { crate::memory::Scope::Device as u32 },
160            {
161                crate::memory::Semantics::IMAGE_MEMORY.bits()
162                    | crate::memory::Semantics::UNIFORM_MEMORY.bits()
163                    | crate::memory::Semantics::ACQUIRE_RELEASE.bits()
164            },
165        >();
166    }
167}
168
169/// Blocks execution of all threads in a group until all memory accesses have been completed.
170///
171/// This is an exact implementation of `AllMemoryBarrier()`.
172///
173/// From <https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/allmemorybarrier>
174#[spirv_std_macros::gpu_only]
175#[inline]
176pub unsafe fn all_memory_barrier() {
177    unsafe {
178        memory_barrier::<
179            { crate::memory::Scope::Device as u32 },
180            {
181                crate::memory::Semantics::WORKGROUP_MEMORY.bits()
182                    | crate::memory::Semantics::IMAGE_MEMORY.bits()
183                    | crate::memory::Semantics::UNIFORM_MEMORY.bits()
184                    | crate::memory::Semantics::ACQUIRE_RELEASE.bits()
185            },
186        >();
187    }
188}
189
190/// Blocks execution of all threads in a group until all memory accesses have been completed and all threads in the group have reached this call.
191///
192/// This is an exact implementation of `AllMemoryBarrierWithGroupSync()`.
193///
194/// From <https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/allmemorybarrierwithgroupsync>
195#[spirv_std_macros::gpu_only]
196#[inline]
197pub unsafe fn all_memory_barrier_with_group_sync() {
198    unsafe {
199        control_barrier::<
200            { crate::memory::Scope::Workgroup as u32 },
201            { crate::memory::Scope::Device as u32 },
202            {
203                crate::memory::Semantics::WORKGROUP_MEMORY.bits()
204                    | crate::memory::Semantics::IMAGE_MEMORY.bits()
205                    | crate::memory::Semantics::UNIFORM_MEMORY.bits()
206                    | crate::memory::Semantics::ACQUIRE_RELEASE.bits()
207            },
208        >();
209    }
210}