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    asm! {
42        "%u32 = OpTypeInt 32 0",
43        "%execution = OpConstant %u32 {execution}",
44        "%memory = OpConstant %u32 {memory}",
45        "%semantics = OpConstant %u32 {semantics}",
46        "OpControlBarrier %execution %memory %semantics",
47        execution = const EXECUTION,
48        memory = const MEMORY,
49        semantics = const SEMANTICS,
50    }
51}
52
53/// Control the order that memory accesses are observed.
54///
55/// Ensures that memory accesses issued before this instruction are observed
56/// before memory accesses issued after this instruction. This control is
57/// ensured only for memory accesses issued by this invocation and observed by
58/// another invocation executing within `MEMORY` scope. If the `vulkan` memory
59/// model is declared, this ordering only applies to memory accesses that
60/// use the `NonPrivatePointer` memory operand or `NonPrivateTexel`
61/// image operand.
62///
63/// `SEMANTICS` declares what kind of memory is being controlled and what kind
64/// of control to apply.
65///
66/// To execute both a memory barrier and a control barrier,
67/// see [`control_barrier`].
68#[spirv_std_macros::gpu_only]
69#[doc(alias = "OpMemoryBarrier")]
70#[inline]
71pub unsafe fn memory_barrier<
72    const MEMORY: u32,    // Scope
73    const SEMANTICS: u32, // Semantics
74>() {
75    asm! {
76        "%u32 = OpTypeInt 32 0",
77        "%memory = OpConstant %u32 {memory}",
78        "%semantics = OpConstant %u32 {semantics}",
79        "OpMemoryBarrier %memory %semantics",
80        memory = const MEMORY,
81        semantics = const SEMANTICS,
82    }
83}
84
85/// Blocks execution of all threads in a group until all group shared accesses have been completed.
86///
87/// This is an exact implementation of `GroupMemoryBarrier()`.
88///
89/// From <https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/groupmemorybarrier>
90#[spirv_std_macros::gpu_only]
91#[inline]
92pub unsafe fn workgroup_memory_barrier() {
93    memory_barrier::<
94        { crate::memory::Scope::Workgroup as u32 },
95        {
96            crate::memory::Semantics::WORKGROUP_MEMORY.bits()
97                | crate::memory::Semantics::ACQUIRE_RELEASE.bits()
98        },
99    >();
100}
101
102/// 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.
103///
104/// This is an exact implementation of `GroupMemoryBarrierWithGroupSync()`.
105///
106/// From <https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/groupmemorybarrierwithgroupsync>
107#[spirv_std_macros::gpu_only]
108#[inline]
109pub unsafe fn workgroup_memory_barrier_with_group_sync() {
110    control_barrier::<
111        { crate::memory::Scope::Workgroup as u32 },
112        { crate::memory::Scope::Workgroup as u32 },
113        {
114            crate::memory::Semantics::WORKGROUP_MEMORY.bits()
115                | crate::memory::Semantics::ACQUIRE_RELEASE.bits()
116        },
117    >();
118}
119
120/// Blocks execution of all threads in a group until all device memory accesses have been completed.
121///
122/// This is an exact implementation of `DeviceMemoryBarrier()`.
123///
124/// From <https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/devicememorybarrier>
125#[spirv_std_macros::gpu_only]
126#[inline]
127pub unsafe fn device_memory_barrier() {
128    memory_barrier::<
129        { crate::memory::Scope::Device as u32 },
130        {
131            crate::memory::Semantics::IMAGE_MEMORY.bits()
132                | crate::memory::Semantics::UNIFORM_MEMORY.bits()
133                | crate::memory::Semantics::ACQUIRE_RELEASE.bits()
134        },
135    >();
136}
137
138/// 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.
139///
140/// This is an exact implementation of `DeviceMemoryBarrierWithGroupSync()`.
141///
142/// From <https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/devicememorybarrierwithgroupsync>
143#[spirv_std_macros::gpu_only]
144#[inline]
145pub unsafe fn device_memory_barrier_with_group_sync() {
146    control_barrier::<
147        { crate::memory::Scope::Workgroup as u32 },
148        { crate::memory::Scope::Device as u32 },
149        {
150            crate::memory::Semantics::IMAGE_MEMORY.bits()
151                | crate::memory::Semantics::UNIFORM_MEMORY.bits()
152                | crate::memory::Semantics::ACQUIRE_RELEASE.bits()
153        },
154    >();
155}
156
157/// Blocks execution of all threads in a group until all memory accesses have been completed.
158///
159/// This is an exact implementation of `AllMemoryBarrier()`.
160///
161/// From <https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/allmemorybarrier>
162#[spirv_std_macros::gpu_only]
163#[inline]
164pub unsafe fn all_memory_barrier() {
165    memory_barrier::<
166        { crate::memory::Scope::Device as u32 },
167        {
168            crate::memory::Semantics::WORKGROUP_MEMORY.bits()
169                | crate::memory::Semantics::IMAGE_MEMORY.bits()
170                | crate::memory::Semantics::UNIFORM_MEMORY.bits()
171                | crate::memory::Semantics::ACQUIRE_RELEASE.bits()
172        },
173    >();
174}
175
176/// 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.
177///
178/// This is an exact implementation of `AllMemoryBarrierWithGroupSync()`.
179///
180/// From <https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/allmemorybarrierwithgroupsync>
181#[spirv_std_macros::gpu_only]
182#[inline]
183pub unsafe fn all_memory_barrier_with_group_sync() {
184    control_barrier::<
185        { crate::memory::Scope::Workgroup as u32 },
186        { crate::memory::Scope::Device as u32 },
187        {
188            crate::memory::Semantics::WORKGROUP_MEMORY.bits()
189                | crate::memory::Semantics::IMAGE_MEMORY.bits()
190                | crate::memory::Semantics::UNIFORM_MEMORY.bits()
191                | crate::memory::Semantics::ACQUIRE_RELEASE.bits()
192        },
193    >();
194}