1#[inline(always)]
7pub fn atomic_add_i32(ptr: &mut i32, value: i32) -> i32 {
8 #[cfg(target_arch = "spirv")]
9 unsafe {
10 spirv_std::arch::atomic_i_add::<
11 i32,
12 { spirv_std::memory::Scope::QueueFamily as u32 },
13 { spirv_std::memory::Semantics::NONE.bits() },
14 >(ptr, value)
15 }
16 #[cfg(not(target_arch = "spirv"))]
17 {
18 use core::sync::atomic::{AtomicI32, Ordering};
19 let atomic = unsafe { &*(ptr as *mut i32 as *const AtomicI32) };
20 atomic.fetch_add(value, Ordering::Relaxed)
21 }
22}
23
24#[inline(always)]
26pub fn atomic_add_u32(ptr: &mut u32, value: u32) -> u32 {
27 #[cfg(target_arch = "spirv")]
28 unsafe {
29 spirv_std::arch::atomic_i_add::<
30 u32,
31 { spirv_std::memory::Scope::QueueFamily as u32 },
32 { spirv_std::memory::Semantics::NONE.bits() },
33 >(ptr, value)
34 }
35 #[cfg(not(target_arch = "spirv"))]
36 {
37 use core::sync::atomic::{AtomicU32, Ordering};
38 let atomic = unsafe { &*(ptr as *mut u32 as *const AtomicU32) };
39 atomic.fetch_add(value, Ordering::Relaxed)
40 }
41}
42
43#[inline(always)]
45pub fn atomic_max_u32(ptr: &mut u32, value: u32) -> u32 {
46 #[cfg(target_arch = "spirv")]
47 unsafe {
48 spirv_std::arch::atomic_u_max::<
49 u32,
50 { spirv_std::memory::Scope::QueueFamily as u32 },
51 { spirv_std::memory::Semantics::NONE.bits() },
52 >(ptr, value)
53 }
54 #[cfg(not(target_arch = "spirv"))]
55 {
56 use core::sync::atomic::{AtomicU32, Ordering};
57 let atomic = unsafe { &*(ptr as *mut u32 as *const AtomicU32) };
58 atomic.fetch_max(value, Ordering::Relaxed)
59 }
60}
61
62#[inline(always)]
64pub fn atomic_min_u32(ptr: &mut u32, value: u32) -> u32 {
65 #[cfg(target_arch = "spirv")]
66 unsafe {
67 spirv_std::arch::atomic_u_min::<
68 u32,
69 { spirv_std::memory::Scope::QueueFamily as u32 },
70 { spirv_std::memory::Semantics::NONE.bits() },
71 >(ptr, value)
72 }
73 #[cfg(not(target_arch = "spirv"))]
74 {
75 use core::sync::atomic::{AtomicU32, Ordering};
76 let atomic = unsafe { &*(ptr as *mut u32 as *const AtomicU32) };
77 atomic.fetch_min(value, Ordering::Relaxed)
78 }
79}
80
81#[inline(always)]
87pub fn atomic_load_u32(ptr: &mut u32) -> u32 {
88 #[cfg(target_arch = "spirv")]
89 unsafe {
90 spirv_std::arch::atomic_load::<
91 u32,
92 { spirv_std::memory::Scope::QueueFamily as u32 },
93 { spirv_std::memory::Semantics::NONE.bits() },
94 >(ptr)
95 }
96 #[cfg(not(target_arch = "spirv"))]
97 {
98 use core::sync::atomic::{AtomicU32, Ordering};
99 let atomic = unsafe { &*(ptr as *mut u32 as *const AtomicU32) };
100 atomic.load(Ordering::Relaxed)
101 }
102}
103
104#[inline(always)]
106pub fn atomic_load_u32_shared(ptr: &u32) -> u32 {
107 #[cfg(target_arch = "spirv")]
108 unsafe {
109 spirv_std::arch::atomic_load::<
110 u32,
111 { spirv_std::memory::Scope::QueueFamily as u32 },
112 { spirv_std::memory::Semantics::NONE.bits() },
113 >(ptr)
114 }
115 #[cfg(not(target_arch = "spirv"))]
116 {
117 use core::sync::atomic::{AtomicU32, Ordering};
118 let atomic = unsafe { &*(ptr as *const u32 as *const AtomicU32) };
119 atomic.load(Ordering::Relaxed)
120 }
121}
122
123#[inline(always)]
125pub fn atomic_exchange_u32(ptr: &mut u32, value: u32) -> u32 {
126 #[cfg(target_arch = "spirv")]
127 unsafe {
128 spirv_std::arch::atomic_exchange::<
129 u32,
130 { spirv_std::memory::Scope::QueueFamily as u32 },
131 { spirv_std::memory::Semantics::NONE.bits() },
132 >(ptr, value)
133 }
134 #[cfg(not(target_arch = "spirv"))]
135 {
136 use core::sync::atomic::{AtomicU32, Ordering};
137 let atomic = unsafe { &*(ptr as *mut u32 as *const AtomicU32) };
138 atomic.swap(value, Ordering::Relaxed)
139 }
140}
141
142#[inline(always)]
145pub fn atomic_compare_exchange_u32(ptr: &mut u32, value: u32, comparator: u32) -> u32 {
146 #[cfg(target_arch = "spirv")]
147 unsafe {
148 spirv_std::arch::atomic_compare_exchange::<
149 u32,
150 { spirv_std::memory::Scope::QueueFamily as u32 },
151 { spirv_std::memory::Semantics::NONE.bits() },
152 { spirv_std::memory::Semantics::NONE.bits() },
153 >(ptr, value, comparator)
154 }
155 #[cfg(not(target_arch = "spirv"))]
156 {
157 use core::sync::atomic::{AtomicU32, Ordering};
158 let atomic = unsafe { &*(ptr as *mut u32 as *const AtomicU32) };
159 match atomic.compare_exchange(comparator, value, Ordering::Relaxed, Ordering::Relaxed) {
160 Ok(old) => old,
161 Err(old) => old,
162 }
163 }
164}
165
166#[inline(always)]
168pub fn atomic_or_u32(ptr: &mut u32, value: u32) -> u32 {
169 #[cfg(target_arch = "spirv")]
170 unsafe {
171 spirv_std::arch::atomic_or::<
172 u32,
173 { spirv_std::memory::Scope::QueueFamily as u32 },
174 { spirv_std::memory::Semantics::NONE.bits() },
175 >(ptr, value)
176 }
177 #[cfg(not(target_arch = "spirv"))]
178 {
179 use core::sync::atomic::{AtomicU32, Ordering};
180 let atomic = unsafe { &*(ptr as *mut u32 as *const AtomicU32) };
181 atomic.fetch_or(value, Ordering::Relaxed)
182 }
183}
184
185#[inline(always)]
187pub fn atomic_and_u32(ptr: &mut u32, value: u32) -> u32 {
188 #[cfg(target_arch = "spirv")]
189 unsafe {
190 spirv_std::arch::atomic_and::<
191 u32,
192 { spirv_std::memory::Scope::QueueFamily as u32 },
193 { spirv_std::memory::Semantics::NONE.bits() },
194 >(ptr, value)
195 }
196 #[cfg(not(target_arch = "spirv"))]
197 {
198 use core::sync::atomic::{AtomicU32, Ordering};
199 let atomic = unsafe { &*(ptr as *mut u32 as *const AtomicU32) };
200 atomic.fetch_and(value, Ordering::Relaxed)
201 }
202}
203
204#[inline]
211pub fn atomic_add_f32(ptr: &mut u32, value: f32) {
212 loop {
213 let old_bits = atomic_load_u32(ptr);
214 let new_val = f32::from_bits(old_bits) + value;
215 let new_bits = new_val.to_bits();
216 let prev = atomic_compare_exchange_u32(ptr, new_bits, old_bits);
217 if prev == old_bits {
218 break;
219 }
220 }
221}
222
223#[inline(always)]
229pub fn atomic_add_u32_workgroup(ptr: &mut u32, value: u32) -> u32 {
230 #[cfg(target_arch = "spirv")]
231 unsafe {
232 spirv_std::arch::atomic_i_add::<
233 u32,
234 { spirv_std::memory::Scope::Workgroup as u32 },
235 { spirv_std::memory::Semantics::NONE.bits() },
236 >(ptr, value)
237 }
238 #[cfg(not(target_arch = "spirv"))]
239 {
240 use core::sync::atomic::{AtomicU32, Ordering};
241 let atomic = unsafe { &*(ptr as *mut u32 as *const AtomicU32) };
242 atomic.fetch_add(value, Ordering::Relaxed)
243 }
244}
245
246#[inline(always)]
248pub fn atomic_max_u32_workgroup(ptr: &mut u32, value: u32) -> u32 {
249 #[cfg(target_arch = "spirv")]
250 unsafe {
251 spirv_std::arch::atomic_u_max::<
252 u32,
253 { spirv_std::memory::Scope::Workgroup as u32 },
254 { spirv_std::memory::Semantics::NONE.bits() },
255 >(ptr, value)
256 }
257 #[cfg(not(target_arch = "spirv"))]
258 {
259 use core::sync::atomic::{AtomicU32, Ordering};
260 let atomic = unsafe { &*(ptr as *mut u32 as *const AtomicU32) };
261 atomic.fetch_max(value, Ordering::Relaxed)
262 }
263}
264
265#[inline(always)]
267pub fn atomic_store_u32_workgroup(ptr: &mut u32, value: u32) {
268 #[cfg(target_arch = "spirv")]
269 unsafe {
270 spirv_std::arch::atomic_exchange::<
271 u32,
272 { spirv_std::memory::Scope::Workgroup as u32 },
273 { spirv_std::memory::Semantics::NONE.bits() },
274 >(ptr, value);
275 }
276 #[cfg(not(target_arch = "spirv"))]
277 {
278 use core::sync::atomic::{AtomicU32, Ordering};
279 let atomic = unsafe { &*(ptr as *mut u32 as *const AtomicU32) };
280 atomic.store(value, Ordering::Relaxed);
281 }
282}
283
284#[inline(always)]
286pub fn atomic_load_u32_workgroup(ptr: &mut u32) -> u32 {
287 #[cfg(target_arch = "spirv")]
288 unsafe {
289 spirv_std::arch::atomic_load::<
290 u32,
291 { spirv_std::memory::Scope::Workgroup as u32 },
292 { spirv_std::memory::Semantics::NONE.bits() },
293 >(ptr)
294 }
295 #[cfg(not(target_arch = "spirv"))]
296 {
297 use core::sync::atomic::{AtomicU32, Ordering};
298 let atomic = unsafe { &*(ptr as *mut u32 as *const AtomicU32) };
299 atomic.load(Ordering::Relaxed)
300 }
301}