Skip to content

Commit 11e21c6

Browse files
authored
Add a OpAtomicIIncrement function to arch (#839)
1 parent f780364 commit 11e21c6

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

crates/spirv-std/src/arch.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,29 @@ pub fn signed_max<T: SignedInteger>(a: T, b: T) -> T {
226226
unsafe { call_glsl_op_with_ints::<_, 42>(a, b) }
227227
}
228228

229+
/// Atomically increment an integer and return the old value.
230+
#[spirv_std_macros::gpu_only]
231+
#[doc(alias = "OpAtomicIIncrement")]
232+
pub unsafe fn atomic_i_increment<I: Integer, const SCOPE: u32, const SEMANTICS: u32>(
233+
ptr: &mut I,
234+
) -> I {
235+
let mut old = I::default();
236+
237+
asm! {
238+
"%u32 = OpTypeInt 32 0",
239+
"%scope = OpConstant %u32 {scope}",
240+
"%semantics = OpConstant %u32 {semantics}",
241+
"%old = OpAtomicIIncrement _ {ptr} %scope %semantics",
242+
"OpStore {old} %old",
243+
scope = const SCOPE,
244+
semantics = const SEMANTICS,
245+
ptr = in(reg) ptr,
246+
old = in(reg) &mut old,
247+
}
248+
249+
old
250+
}
251+
229252
/// Index into an array without bounds checking.
230253
///
231254
/// The main purpose of this trait is to work around the fact that the regular `get_unchecked*`

tests/ui/arch/atomic_i_increment.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// build-pass
2+
3+
use spirv_std::arch::IndexUnchecked;
4+
5+
#[spirv(compute(threads(64)))]
6+
pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &mut [u32]) {
7+
let reference = unsafe { buffer.index_unchecked_mut(0) };
8+
9+
let old = unsafe {
10+
spirv_std::arch::atomic_i_increment::<
11+
_,
12+
{ spirv_std::memory::Scope::Workgroup as u32 },
13+
{ spirv_std::memory::Semantics::NONE.bits() as u32 },
14+
>(reference)
15+
};
16+
assert!(old == 0);
17+
}

0 commit comments

Comments
 (0)