From 57c9d154ef8778c287f12bb28ad51756be4d81d1 Mon Sep 17 00:00:00 2001 From: = <=> Date: Mon, 25 Jul 2022 10:44:02 +0200 Subject: [PATCH 01/11] Added number trait for representing SPIR-V integers --- crates/spirv-std/src/number.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/spirv-std/src/number.rs b/crates/spirv-std/src/number.rs index 20a195da1e..f12745fd3e 100644 --- a/crates/spirv-std/src/number.rs +++ b/crates/spirv-std/src/number.rs @@ -1,6 +1,4 @@ -//! Traits and helper functions related to numbers. - -/// Abstract trait representing a SPIR-V integer or floating-point type. +/// Abstract trait representing a SPIR-V integer type. pub trait Number: crate::scalar::Scalar {} impl Number for u8 {} From 6437a063c9be2279d90d11413c44687f3dc28312 Mon Sep 17 00:00:00 2001 From: = <=> Date: Mon, 25 Jul 2022 10:45:04 +0200 Subject: [PATCH 02/11] Ported over old atomic functions from the atomics branch --- crates/spirv-std/src/arch.rs | 2 +- crates/spirv-std/src/arch/atomics.rs | 210 +++++++-------------------- 2 files changed, 53 insertions(+), 159 deletions(-) diff --git a/crates/spirv-std/src/arch.rs b/crates/spirv-std/src/arch.rs index 60fe0a563a..39234622df 100644 --- a/crates/spirv-std/src/arch.rs +++ b/crates/spirv-std/src/arch.rs @@ -11,7 +11,7 @@ use crate::{ #[cfg(target_arch = "spirv")] use core::arch::asm; -mod atomics; +pub mod atomics; mod barrier; mod demote_to_helper_invocation_ext; mod derivative; diff --git a/crates/spirv-std/src/arch/atomics.rs b/crates/spirv-std/src/arch/atomics.rs index bb0f75992e..2320b6df55 100644 --- a/crates/spirv-std/src/arch/atomics.rs +++ b/crates/spirv-std/src/arch/atomics.rs @@ -1,19 +1,21 @@ -#[cfg(target_arch = "spirv")] -use core::arch::asm; +//! SPIR-V Atomics +//! use crate::{ - float::Float, integer::{Integer, SignedInteger, UnsignedInteger}, number::Number, }; +#[cfg(target_arch = "spirv")] +use core::arch::asm; + /// Atomically load through `ptr` using the given `SEMANTICS`. All subparts of /// the value that is loaded are read atomically with respect to all other /// atomic accesses to it within `SCOPE`. #[spirv_std_macros::gpu_only] #[doc(alias = "OpAtomicLoad")] #[inline] -pub unsafe fn atomic_load(ptr: &N) -> N { +pub unsafe fn atomic_load(ptr: &N) -> N { let mut result = N::default(); asm! { @@ -37,10 +39,7 @@ pub unsafe fn atomic_load(ptr #[spirv_std_macros::gpu_only] #[doc(alias = "OpAtomicStore")] #[inline] -pub unsafe fn atomic_store( - ptr: &mut N, - value: N, -) { +pub unsafe fn atomic_store(ptr: &mut N, value: N) { asm! { "%u32 = OpTypeInt 32 0", "%scope = OpConstant %u32 {scope}", @@ -50,7 +49,7 @@ pub unsafe fn atomic_store( scope = const SCOPE, semantics = const SEMANTICS, ptr = in(reg) ptr, - value = in(reg) &value + value = in(reg) &value, } } @@ -65,7 +64,7 @@ pub unsafe fn atomic_store( #[spirv_std_macros::gpu_only] #[doc(alias = "OpAtomicExchange")] #[inline] -pub unsafe fn atomic_exchange( +pub unsafe fn atomic_exchange( ptr: &mut N, value: N, ) -> N { @@ -81,8 +80,8 @@ pub unsafe fn atomic_exchange scope = const SCOPE, semantics = const SEMANTICS, ptr = in(reg) ptr, + value = in(reg) &value, old = in(reg) &mut old, - value = in(reg) &value } old @@ -103,9 +102,9 @@ pub unsafe fn atomic_exchange #[inline] pub unsafe fn atomic_compare_exchange< I: Integer, - const SCOPE: u32, - const EQUAL: u32, - const UNEQUAL: u32, + const SCOPE: u8, + const EQUAL: u8, + const UNEQUAL: u8, >( ptr: &mut I, value: I, @@ -144,8 +143,7 @@ pub unsafe fn atomic_compare_exchange< /// The result is the original value. #[spirv_std_macros::gpu_only] #[doc(alias = "OpAtomicIIncrement")] -#[inline] -pub unsafe fn atomic_i_increment( +pub unsafe fn atomic_i_increment( ptr: &mut I, ) -> I { let mut old = I::default(); @@ -159,7 +157,7 @@ pub unsafe fn atomic_i_increment( +pub unsafe fn atomic_i_decrement( ptr: &mut I, ) -> I { let mut old = I::default(); @@ -185,12 +183,12 @@ pub unsafe fn atomic_i_decrement( +pub unsafe fn atomic_i_add( ptr: &mut I, value: I, ) -> I { @@ -224,7 +222,7 @@ pub unsafe fn atomic_i_add( semantics = const SEMANTICS, ptr = in(reg) ptr, old = in(reg) &mut old, - value = in(reg) &value + value = in(reg) &value, } old @@ -241,7 +239,7 @@ pub unsafe fn atomic_i_add( #[spirv_std_macros::gpu_only] #[doc(alias = "OpAtomicISub")] #[inline] -pub unsafe fn atomic_i_sub( +pub unsafe fn atomic_i_sub( ptr: &mut I, value: I, ) -> I { @@ -258,7 +256,7 @@ pub unsafe fn atomic_i_sub( semantics = const SEMANTICS, ptr = in(reg) ptr, old = in(reg) &mut old, - value = in(reg) &value + value = in(reg) &value, } old @@ -276,11 +274,11 @@ pub unsafe fn atomic_i_sub( #[spirv_std_macros::gpu_only] #[doc(alias = "OpAtomicSMin")] #[inline] -pub unsafe fn atomic_s_min( - ptr: &mut S, - value: S, -) -> S { - let mut old = S::default(); +pub unsafe fn atomic_s_min( + ptr: &mut I, + value: I, +) -> I { + let mut old = I::default(); asm! { "%u32 = OpTypeInt 32 0", @@ -293,7 +291,7 @@ pub unsafe fn atomic_s_min( - ptr: &mut U, - value: U, -) -> U { - let mut old = U::default(); +pub unsafe fn atomic_u_min( + ptr: &mut I, + value: I, +) -> I { + let mut old = I::default(); asm! { "%u32 = OpTypeInt 32 0", @@ -328,7 +326,7 @@ pub unsafe fn atomic_u_min( - ptr: &mut S, - value: S, -) -> S { - let mut old = S::default(); +pub unsafe fn atomic_s_max( + ptr: &mut I, + value: I, +) -> I { + let mut old = I::default(); asm! { "%u32 = OpTypeInt 32 0", @@ -363,7 +361,7 @@ pub unsafe fn atomic_s_max( - ptr: &mut U, - value: U, -) -> U { - let mut old = U::default(); +pub unsafe fn atomic_u_max( + ptr: &mut I, + value: I, +) -> I { + let mut old = I::default(); asm! { "%u32 = OpTypeInt 32 0", @@ -398,7 +396,7 @@ pub unsafe fn atomic_u_max( +pub unsafe fn atomic_and( ptr: &mut I, value: I, ) -> I { @@ -432,7 +430,7 @@ pub unsafe fn atomic_and( semantics = const SEMANTICS, ptr = in(reg) ptr, old = in(reg) &mut old, - value = in(reg) &value + value = in(reg) &value, } old @@ -449,7 +447,7 @@ pub unsafe fn atomic_and( #[spirv_std_macros::gpu_only] #[doc(alias = "OpAtomicOr")] #[inline] -pub unsafe fn atomic_or( +pub unsafe fn atomic_or( ptr: &mut I, value: I, ) -> I { @@ -466,7 +464,7 @@ pub unsafe fn atomic_or( semantics = const SEMANTICS, ptr = in(reg) ptr, old = in(reg) &mut old, - value = in(reg) &value + value = in(reg) &value, } old @@ -483,7 +481,7 @@ pub unsafe fn atomic_or( #[spirv_std_macros::gpu_only] #[doc(alias = "OpAtomicXor")] #[inline] -pub unsafe fn atomic_xor( +pub unsafe fn atomic_xor( ptr: &mut I, value: I, ) -> I { @@ -500,111 +498,7 @@ pub unsafe fn atomic_xor( semantics = const SEMANTICS, ptr = in(reg) ptr, old = in(reg) &mut old, - value = in(reg) &value - } - - old -} - -/// Perform the following steps atomically with respect to any other atomic -/// accesses within Scope to the same location: -/// -/// 1. Load through `ptr` to get an original value, -/// 2. Get a new value by finding the smallest signed integer of original value -/// and `value`, and -/// 3. Store the new value back through `ptr`. -/// -/// The result is the original value. -#[spirv_std_macros::gpu_only] -#[doc(alias = "OpAtomicFMinEXT")] -#[inline] -pub unsafe fn atomic_f_min( - ptr: &mut F, - value: F, -) -> F { - let mut old = F::default(); - - asm! { - "%u32 = OpTypeInt 32 0", - "%scope = OpConstant %u32 {scope}", - "%semantics = OpConstant %u32 {semantics}", - "%value = OpLoad _ {value}", - "%old = OpAtomicFMinEXT _ {ptr} %scope %semantics %value", - "OpStore {old} %old", - scope = const SCOPE, - semantics = const SEMANTICS, - ptr = in(reg) ptr, - old = in(reg) &mut old, - value = in(reg) &value - } - - old -} - -/// Perform the following steps atomically with respect to any other atomic -/// accesses within Scope to the same location: -/// -/// 1. Load through `ptr` to get an original value, -/// 2. Get a new value by finding the largest signed integer of original value -/// and `value`, and -/// 3. Store the new value back through `ptr`. -/// -/// The result is the original value. -#[spirv_std_macros::gpu_only] -#[doc(alias = "OpAtomicFMaxEXT")] -#[inline] -pub unsafe fn atomic_f_max( - ptr: &mut F, - value: F, -) -> F { - let mut old = F::default(); - - asm! { - "%u32 = OpTypeInt 32 0", - "%scope = OpConstant %u32 {scope}", - "%semantics = OpConstant %u32 {semantics}", - "%value = OpLoad _ {value}", - "%old = OpAtomicFMaxEXT _ {ptr} %scope %semantics %value", - "OpStore {old} %old", - scope = const SCOPE, - semantics = const SEMANTICS, - ptr = in(reg) ptr, - old = in(reg) &mut old, - value = in(reg) &value - } - - old -} - -/// Perform the following steps atomically with respect to any other atomic -/// accesses within `SCOPE` to the same location: -/// -/// 1) load through `ptr` to get an original value, -/// 2) get a new value by integer addition of original value and `value`, and -/// 3) store the new value back through `ptr`. -/// -/// The result is the Original Value. -#[spirv_std_macros::gpu_only] -#[doc(alias = "OpAtomicFAddEXT")] -#[inline] -pub unsafe fn atomic_f_add( - ptr: &mut F, - value: F, -) -> F { - let mut old = F::default(); - - asm! { - "%u32 = OpTypeInt 32 0", - "%scope = OpConstant %u32 {scope}", - "%semantics = OpConstant %u32 {semantics}", - "%value = OpLoad _ {value}", - "%old = OpAtomicFMaxEXT _ {ptr} %scope %semantics %value", - "OpStore {old} %old", - scope = const SCOPE, - semantics = const SEMANTICS, - ptr = in(reg) ptr, - old = in(reg) &mut old, - value = in(reg) &value + value = in(reg) &value, } old From 5b5fba3150484e1d9e4b35a298d17186ee876267 Mon Sep 17 00:00:00 2001 From: = <=> Date: Mon, 25 Jul 2022 10:52:49 +0200 Subject: [PATCH 03/11] Added documentation to the numerical type --- crates/spirv-std/src/number.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/spirv-std/src/number.rs b/crates/spirv-std/src/number.rs index f12745fd3e..59b332c84b 100644 --- a/crates/spirv-std/src/number.rs +++ b/crates/spirv-std/src/number.rs @@ -1,4 +1,7 @@ -/// Abstract trait representing a SPIR-V integer type. +//! SPIR-V Numerical Type +//! +//! Used to represent either an integer type or floating-point type. +/// Abstract trait representing a SPIR-V numerical type. pub trait Number: crate::scalar::Scalar {} impl Number for u8 {} From 66ce79966e56e7ccd48f8fc7835e35cbc5b9715e Mon Sep 17 00:00:00 2001 From: = <=> Date: Mon, 25 Jul 2022 12:17:42 +0200 Subject: [PATCH 04/11] Ported exsisting build-pass tests --- tests/ui/arch/atomics/atomic_and.rs | 19 +++++++++++++++++ .../arch/atomics/atomic_compare_exchange.rs | 20 ++++++++++++++++++ tests/ui/arch/atomics/atomic_exchange.rs | 19 +++++++++++++++++ tests/ui/arch/atomics/atomic_i_add | 19 +++++++++++++++++ tests/ui/arch/atomics/atomic_i_decrement.rs | 21 +++++++++++++++++++ .../arch/{ => atomics}/atomic_i_increment.rs | 12 +++++++---- tests/ui/arch/atomics/atomic_i_sub.rs | 19 +++++++++++++++++ tests/ui/arch/atomics/atomic_load.rs | 19 +++++++++++++++++ tests/ui/arch/atomics/atomic_or.rs | 19 +++++++++++++++++ tests/ui/arch/atomics/atomic_s_max.rs | 19 +++++++++++++++++ tests/ui/arch/atomics/atomic_s_min.rs | 19 +++++++++++++++++ tests/ui/arch/atomics/atomic_store.rs | 19 +++++++++++++++++ tests/ui/arch/atomics/atomic_u_max.rs | 19 +++++++++++++++++ tests/ui/arch/atomics/atomic_u_min.rs | 19 +++++++++++++++++ tests/ui/arch/atomics/atomic_xor.rs | 19 +++++++++++++++++ 15 files changed, 277 insertions(+), 4 deletions(-) create mode 100644 tests/ui/arch/atomics/atomic_and.rs create mode 100644 tests/ui/arch/atomics/atomic_compare_exchange.rs create mode 100644 tests/ui/arch/atomics/atomic_exchange.rs create mode 100644 tests/ui/arch/atomics/atomic_i_add create mode 100644 tests/ui/arch/atomics/atomic_i_decrement.rs rename tests/ui/arch/{ => atomics}/atomic_i_increment.rs (58%) create mode 100644 tests/ui/arch/atomics/atomic_i_sub.rs create mode 100644 tests/ui/arch/atomics/atomic_load.rs create mode 100644 tests/ui/arch/atomics/atomic_or.rs create mode 100644 tests/ui/arch/atomics/atomic_s_max.rs create mode 100644 tests/ui/arch/atomics/atomic_s_min.rs create mode 100644 tests/ui/arch/atomics/atomic_store.rs create mode 100644 tests/ui/arch/atomics/atomic_u_max.rs create mode 100644 tests/ui/arch/atomics/atomic_u_min.rs create mode 100644 tests/ui/arch/atomics/atomic_xor.rs diff --git a/tests/ui/arch/atomics/atomic_and.rs b/tests/ui/arch/atomics/atomic_and.rs new file mode 100644 index 0000000000..26dfb7acd1 --- /dev/null +++ b/tests/ui/arch/atomics/atomic_and.rs @@ -0,0 +1,19 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] +use spirv_std::{ + arch::IndexUnchecked, + memory::{Scope, Semantics}, +}; + +#[spirv(compute(threads(64)))] +pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &mut [u32]) { + let old = unsafe { + spirv_std::arch::atomic_and::< + _, + { Scope::Workgroup as u8 }, + { Semantics::UNIFORM_MEMORY.bits() as u8 }, + >(&mut *buffer.index_unchecked_mut(0), 5) + }; +} diff --git a/tests/ui/arch/atomics/atomic_compare_exchange.rs b/tests/ui/arch/atomics/atomic_compare_exchange.rs new file mode 100644 index 0000000000..b6751c7166 --- /dev/null +++ b/tests/ui/arch/atomics/atomic_compare_exchange.rs @@ -0,0 +1,20 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] +use spirv_std::{ + arch::IndexUnchecked, + memory::{Scope, Semantics}, +}; + +#[spirv(compute(threads(64)))] +pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &mut [u32]) { + unsafe { + let old = spirv_std::arch::atomic_compare_exchange::< + _, + { Scope::CrossDevice as u8 }, + { Semantics::UNIFORM_MEMORY.bits() as u8 }, + { Semantics::UNIFORM_MEMORY.bits() as u8 }, + >(&mut *buffer.index_unchecked_mut(0), 5, 10); + } +} diff --git a/tests/ui/arch/atomics/atomic_exchange.rs b/tests/ui/arch/atomics/atomic_exchange.rs new file mode 100644 index 0000000000..6c24d0e160 --- /dev/null +++ b/tests/ui/arch/atomics/atomic_exchange.rs @@ -0,0 +1,19 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] +use spirv_std::{ + arch::IndexUnchecked, + memory::{Scope, Semantics}, +}; + +#[spirv(compute(threads(64)))] +pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &mut [u32]) { + unsafe { + let old = spirv_std::arch::atomic_exchange::< + _, + { Scope::CrossDevice as u8 }, + { Semantics::UNIFORM_MEMORY.bits() as u8 }, + >(&mut *buffer.index_unchecked_mut(0), 5); + } +} diff --git a/tests/ui/arch/atomics/atomic_i_add b/tests/ui/arch/atomics/atomic_i_add new file mode 100644 index 0000000000..9b75858ed5 --- /dev/null +++ b/tests/ui/arch/atomics/atomic_i_add @@ -0,0 +1,19 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] +use spirv_std::{ + arch::IndexUnchecked, + memory::{Scope, Semantics}, +}; + +#[spirv(compute(threads(64)))] +pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &mut [u32]) { + let old = unsafe { + spirv_std::arch::atomic_i_add::< + _, + { Scope::Workgroup as u8 }, + { Semantics::UNIFORM_MEMORY.bits() as u8 }, + >(&mut *buffer.index_unchecked_mut(0), 5) + }; +} diff --git a/tests/ui/arch/atomics/atomic_i_decrement.rs b/tests/ui/arch/atomics/atomic_i_decrement.rs new file mode 100644 index 0000000000..fd4f099978 --- /dev/null +++ b/tests/ui/arch/atomics/atomic_i_decrement.rs @@ -0,0 +1,21 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] +use spirv_std::{ + arch::IndexUnchecked, + memory::{Scope, Semantics}, +}; + +#[spirv(compute(threads(64)))] +pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &mut [u32]) { + let reference = unsafe { buffer.index_unchecked_mut(0) }; + + let old = unsafe { + spirv_std::arch::atomic_i_decrement::< + _, + { Scope::Workgroup as u8 }, + { Semantics::NONE.bits() as u8 }, + >(reference) + }; +} diff --git a/tests/ui/arch/atomic_i_increment.rs b/tests/ui/arch/atomics/atomic_i_increment.rs similarity index 58% rename from tests/ui/arch/atomic_i_increment.rs rename to tests/ui/arch/atomics/atomic_i_increment.rs index 3866324823..142b2a0291 100644 --- a/tests/ui/arch/atomic_i_increment.rs +++ b/tests/ui/arch/atomics/atomic_i_increment.rs @@ -1,6 +1,11 @@ // build-pass -use spirv_std::arch::IndexUnchecked; +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] +use spirv_std::{ + arch::IndexUnchecked, + memory::{Scope, Semantics}, +}; #[spirv(compute(threads(64)))] pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &mut [u32]) { @@ -9,9 +14,8 @@ pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &m let old = unsafe { spirv_std::arch::atomic_i_increment::< _, - { spirv_std::memory::Scope::Workgroup as u32 }, - { spirv_std::memory::Semantics::NONE.bits() as u32 }, + { Scope::Workgroup as u8 }, + { Semantics::NONE.bits() as u8 }, >(reference) }; - assert!(old == 0); } diff --git a/tests/ui/arch/atomics/atomic_i_sub.rs b/tests/ui/arch/atomics/atomic_i_sub.rs new file mode 100644 index 0000000000..a3be6a4a82 --- /dev/null +++ b/tests/ui/arch/atomics/atomic_i_sub.rs @@ -0,0 +1,19 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] +use spirv_std::{ + arch::IndexUnchecked, + memory::{Scope, Semantics}, +}; + +#[spirv(compute(threads(64)))] +pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &mut [u32]) { + let old = unsafe { + spirv_std::arch::atomic_i_sub::< + _, + { Scope::Workgroup as u8 }, + { Semantics::UNIFORM_MEMORY.bits() as u8 }, + >(&mut *buffer.index_unchecked_mut(0), 5) + }; +} diff --git a/tests/ui/arch/atomics/atomic_load.rs b/tests/ui/arch/atomics/atomic_load.rs new file mode 100644 index 0000000000..d6a9e56e57 --- /dev/null +++ b/tests/ui/arch/atomics/atomic_load.rs @@ -0,0 +1,19 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] +use spirv_std::{ + arch::IndexUnchecked, + memory::{Scope, Semantics}, +}; + +#[spirv(compute(threads(64)))] +pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &mut [u32]) { + unsafe { + let output = spirv_std::arch::atomic_load::< + _, + { Scope::CrossDevice as u8 }, + { Semantics::UNIFORM_MEMORY.bits() as u8 }, + >(&mut *buffer.index_unchecked_mut(0)); + } +} diff --git a/tests/ui/arch/atomics/atomic_or.rs b/tests/ui/arch/atomics/atomic_or.rs new file mode 100644 index 0000000000..a3b6cf813a --- /dev/null +++ b/tests/ui/arch/atomics/atomic_or.rs @@ -0,0 +1,19 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] +use spirv_std::{ + arch::IndexUnchecked, + memory::{Scope, Semantics}, +}; + +#[spirv(compute(threads(64)))] +pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &mut [u32]) { + let old = unsafe { + spirv_std::arch::atomic_or::< + _, + { Scope::Workgroup as u8 }, + { Semantics::UNIFORM_MEMORY.bits() as u8 }, + >(&mut *buffer.index_unchecked_mut(0), 5) + }; +} diff --git a/tests/ui/arch/atomics/atomic_s_max.rs b/tests/ui/arch/atomics/atomic_s_max.rs new file mode 100644 index 0000000000..def6c76bda --- /dev/null +++ b/tests/ui/arch/atomics/atomic_s_max.rs @@ -0,0 +1,19 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] +use spirv_std::{ + arch::IndexUnchecked, + memory::{Scope, Semantics}, +}; + +#[spirv(compute(threads(64)))] +pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &mut [i32]) { + let old = unsafe { + spirv_std::arch::atomic_s_max::< + _, + { Scope::Workgroup as u8 }, + { Semantics::UNIFORM_MEMORY.bits() as u8 }, + >(&mut *buffer.index_unchecked_mut(0), 5) + }; +} diff --git a/tests/ui/arch/atomics/atomic_s_min.rs b/tests/ui/arch/atomics/atomic_s_min.rs new file mode 100644 index 0000000000..fc6c2b402a --- /dev/null +++ b/tests/ui/arch/atomics/atomic_s_min.rs @@ -0,0 +1,19 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] +use spirv_std::{ + arch::IndexUnchecked, + memory::{Scope, Semantics}, +}; + +#[spirv(compute(threads(64)))] +pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &mut [i32]) { + let old = unsafe { + spirv_std::arch::atomic_s_min::< + _, + { Scope::Workgroup as u8 }, + { Semantics::UNIFORM_MEMORY.bits() as u8 }, + >(&mut *buffer.index_unchecked_mut(0), 5) + }; +} diff --git a/tests/ui/arch/atomics/atomic_store.rs b/tests/ui/arch/atomics/atomic_store.rs new file mode 100644 index 0000000000..e5ec22dbc5 --- /dev/null +++ b/tests/ui/arch/atomics/atomic_store.rs @@ -0,0 +1,19 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] +use spirv_std::{ + arch::IndexUnchecked, + memory::{Scope, Semantics}, +}; + +#[spirv(compute(threads(64)))] +pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &mut [u32]) { + let old = unsafe { + spirv_std::arch::atomic_store::< + _, + { Scope::Workgroup as u8 }, + { Semantics::UNIFORM_MEMORY.bits() as u8 }, + >(&mut *buffer.index_unchecked_mut(0), 5) + }; +} diff --git a/tests/ui/arch/atomics/atomic_u_max.rs b/tests/ui/arch/atomics/atomic_u_max.rs new file mode 100644 index 0000000000..add3122451 --- /dev/null +++ b/tests/ui/arch/atomics/atomic_u_max.rs @@ -0,0 +1,19 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] +use spirv_std::{ + arch::IndexUnchecked, + memory::{Scope, Semantics}, +}; + +#[spirv(compute(threads(64)))] +pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &mut [u32]) { + let old = unsafe { + spirv_std::arch::atomic_u_max::< + _, + { Scope::Workgroup as u8 }, + { Semantics::UNIFORM_MEMORY.bits() as u8 }, + >(&mut *buffer.index_unchecked_mut(0), 5) + }; +} diff --git a/tests/ui/arch/atomics/atomic_u_min.rs b/tests/ui/arch/atomics/atomic_u_min.rs new file mode 100644 index 0000000000..daa8c4dce1 --- /dev/null +++ b/tests/ui/arch/atomics/atomic_u_min.rs @@ -0,0 +1,19 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] +use spirv_std::{ + arch::IndexUnchecked, + memory::{Scope, Semantics}, +}; + +#[spirv(compute(threads(64)))] +pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &mut [u32]) { + let old = unsafe { + spirv_std::arch::atomic_u_min::< + _, + { Scope::Workgroup as u8 }, + { Semantics::UNIFORM_MEMORY.bits() as u8 }, + >(&mut *buffer.index_unchecked_mut(0), 5) + }; +} diff --git a/tests/ui/arch/atomics/atomic_xor.rs b/tests/ui/arch/atomics/atomic_xor.rs new file mode 100644 index 0000000000..33e183ac58 --- /dev/null +++ b/tests/ui/arch/atomics/atomic_xor.rs @@ -0,0 +1,19 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] +use spirv_std::{ + arch::IndexUnchecked, + memory::{Scope, Semantics}, +}; + +#[spirv(compute(threads(64)))] +pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &mut [u32]) { + let old = unsafe { + spirv_std::arch::atomic_xor::< + _, + { Scope::Workgroup as u8 }, + { Semantics::UNIFORM_MEMORY.bits() as u8 }, + >(&mut *buffer.index_unchecked_mut(0), 5) + }; +} From abd59cb6c5304f41bbf5e673e3a4e9c03b9a42a2 Mon Sep 17 00:00:00 2001 From: = <=> Date: Mon, 25 Jul 2022 15:27:41 +0200 Subject: [PATCH 05/11] Added AtomicFlagClear and AtomicTestAndSet functions --- crates/spirv-std/src/arch/atomics.rs | 58 +++++++++++++++++++ tests/ui/arch/atomics/atomic_flag_clear.rs | 25 ++++++++ .../arch/atomics/atomic_flag_test_and_set.rs | 25 ++++++++ 3 files changed, 108 insertions(+) create mode 100644 tests/ui/arch/atomics/atomic_flag_clear.rs create mode 100644 tests/ui/arch/atomics/atomic_flag_test_and_set.rs diff --git a/crates/spirv-std/src/arch/atomics.rs b/crates/spirv-std/src/arch/atomics.rs index 2320b6df55..a9c130921b 100644 --- a/crates/spirv-std/src/arch/atomics.rs +++ b/crates/spirv-std/src/arch/atomics.rs @@ -503,3 +503,61 @@ pub unsafe fn atomic_xor( old } + +/// Atomically sets the flag value pointed to by Pointer to the set state. +/// Pointer must be a pointer to a 32-bit integer type representing an atomic flag. +/// The instruction’s result is true if the flag was in the set state or false if the flag was in the clear state immediately before the operation. +/// **Important:** Kernel capabilities have to be set beforehand. +/// +/// Result Type must be a Boolean type. +/// The resulting values are undefined if an atomic flag is modified by an instruction other than OpAtomicFlagTestAndSet or OpAtomicFlagClear. +#[spirv_std_macros::gpu_only] +#[doc(alias = "OpAtomicFlagTestAndSet")] +#[inline] +pub unsafe fn atomic_flag_test_and_set( + ptr: &mut I, +) -> bool { + let mut old: bool = false; + + asm! { + "%bool = OpTypeBool", + "%u32 = OpTypeInt 32 0", + "%scope = OpConstant %u32 {scope}", + "%semantics = OpConstant %u32 {semantics}", + "%old = OpAtomicFlagTestAndSet %bool {ptr} %scope %semantics", + "OpStore {old} %old", + scope = const SCOPE, + semantics = const SEMANTICS, + ptr = in(reg) ptr, + old = in(reg) &mut old, + } + + old +} + +/// Atomically sets the flag value pointed to by Pointer to the clear state. +/// +/// Pointer must be a pointer to a 32-bit integer type representing an atomic flag. +/// **Important:** Memory Semantics must not be Acquire or AcquireRelease +/// +/// The resulting values are undefined if an atomic flag is modified by an instruction other than OpAtomicFlagTestAndSet or OpAtomicFlagClear. +#[spirv_std_macros::gpu_only] +#[doc(alias = "OpAtomicFlagClear")] +#[inline] +pub unsafe fn atomic_flag_clear(ptr: &mut I) { + // Ensure the memory semantic is not Acquire or AcquireRelease + assert!( + SEMANTICS + != (crate::memory::Semantics::ACQUIRE.bits() as u8 + | crate::memory::Semantics::ACQUIRE_RELEASE.bits() as u8) + ); + asm! { + "%u32 = OpTypeInt 32 0", + "%semantics = OpConstant %u32 {semantics}", + "%scope = OpConstant %u32 {scope}", + "OpAtomicFlagClear {ptr} %scope %semantics", + scope = const SCOPE, + semantics = const SEMANTICS, + ptr = in(reg) ptr, + } +} diff --git a/tests/ui/arch/atomics/atomic_flag_clear.rs b/tests/ui/arch/atomics/atomic_flag_clear.rs new file mode 100644 index 0000000000..53fb83643c --- /dev/null +++ b/tests/ui/arch/atomics/atomic_flag_clear.rs @@ -0,0 +1,25 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] +use spirv_std::{ + arch::IndexUnchecked, + memory::{Scope, Semantics}, +}; + +#[cfg(target_arch = "spirv")] +use core::arch::asm; + +#[spirv(compute(threads(64)))] +pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &mut [u32]) { + // Ensure kernel capabilities. + unsafe { asm!("OpCapability Kernel") }; + + let old = unsafe { + spirv_std::arch::atomic_flag_clear::< + _, + { Scope::Workgroup as u8 }, + { Semantics::UNIFORM_MEMORY.bits() as u8 }, + >(&mut *buffer.index_unchecked_mut(0)) + }; +} diff --git a/tests/ui/arch/atomics/atomic_flag_test_and_set.rs b/tests/ui/arch/atomics/atomic_flag_test_and_set.rs new file mode 100644 index 0000000000..9b15399e3a --- /dev/null +++ b/tests/ui/arch/atomics/atomic_flag_test_and_set.rs @@ -0,0 +1,25 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] +use spirv_std::{ + arch::IndexUnchecked, + memory::{Scope, Semantics}, +}; + +#[cfg(target_arch = "spirv")] +use core::arch::asm; + +#[spirv(compute(threads(64)))] +pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &mut [u32]) { + // Ensure kernel capabilities. + unsafe { asm!("OpCapability Kernel") }; + + let old = unsafe { + spirv_std::arch::atomic_flag_test_and_set::< + _, + { Scope::Workgroup as u8 }, + { Semantics::UNIFORM_MEMORY.bits() as u8 }, + >(&mut *buffer.index_unchecked_mut(0)) + }; +} From a827ac66419ab96181d3bbc04d27d99054fc66f7 Mon Sep 17 00:00:00 2001 From: = <=> Date: Tue, 26 Jul 2022 10:24:32 +0200 Subject: [PATCH 06/11] Added missing file extension for unit test --- tests/ui/arch/atomics/{atomic_i_add => atomic_i_add.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/ui/arch/atomics/{atomic_i_add => atomic_i_add.rs} (100%) diff --git a/tests/ui/arch/atomics/atomic_i_add b/tests/ui/arch/atomics/atomic_i_add.rs similarity index 100% rename from tests/ui/arch/atomics/atomic_i_add rename to tests/ui/arch/atomics/atomic_i_add.rs From dce204902280e2ae00db0db7ec110f1fee175340 Mon Sep 17 00:00:00 2001 From: = <=> Date: Tue, 9 Aug 2022 14:03:21 +0200 Subject: [PATCH 07/11] Added spacing between comments --- crates/spirv-std/src/number.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/spirv-std/src/number.rs b/crates/spirv-std/src/number.rs index 59b332c84b..113d85ec43 100644 --- a/crates/spirv-std/src/number.rs +++ b/crates/spirv-std/src/number.rs @@ -1,6 +1,7 @@ //! SPIR-V Numerical Type //! //! Used to represent either an integer type or floating-point type. + /// Abstract trait representing a SPIR-V numerical type. pub trait Number: crate::scalar::Scalar {} From eafe155fb5a0bf277ad6d0d5ea8cabd2a2e8c1cf Mon Sep 17 00:00:00 2001 From: = <=> Date: Tue, 9 Aug 2022 14:12:04 +0200 Subject: [PATCH 08/11] Removed additional pub --- crates/spirv-std/src/arch.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/spirv-std/src/arch.rs b/crates/spirv-std/src/arch.rs index 39234622df..60fe0a563a 100644 --- a/crates/spirv-std/src/arch.rs +++ b/crates/spirv-std/src/arch.rs @@ -11,7 +11,7 @@ use crate::{ #[cfg(target_arch = "spirv")] use core::arch::asm; -pub mod atomics; +mod atomics; mod barrier; mod demote_to_helper_invocation_ext; mod derivative; From 7aca3a1f5fd3b8f2d3fe166f04f1143cda984ceb Mon Sep 17 00:00:00 2001 From: = <=> Date: Tue, 9 Aug 2022 14:28:15 +0200 Subject: [PATCH 09/11] Changed u8 back to u32 --- crates/spirv-std/src/arch/atomics.rs | 47 ++++++++++--------- tests/ui/arch/atomics/atomic_and.rs | 4 +- .../arch/atomics/atomic_compare_exchange.rs | 6 +-- tests/ui/arch/atomics/atomic_exchange.rs | 4 +- tests/ui/arch/atomics/atomic_flag_clear.rs | 4 +- .../arch/atomics/atomic_flag_test_and_set.rs | 4 +- tests/ui/arch/atomics/atomic_i_add.rs | 4 +- tests/ui/arch/atomics/atomic_i_decrement.rs | 4 +- tests/ui/arch/atomics/atomic_i_increment.rs | 4 +- tests/ui/arch/atomics/atomic_i_sub.rs | 4 +- tests/ui/arch/atomics/atomic_load.rs | 4 +- tests/ui/arch/atomics/atomic_or.rs | 4 +- tests/ui/arch/atomics/atomic_s_max.rs | 4 +- tests/ui/arch/atomics/atomic_s_min.rs | 4 +- tests/ui/arch/atomics/atomic_store.rs | 4 +- tests/ui/arch/atomics/atomic_u_max.rs | 4 +- tests/ui/arch/atomics/atomic_u_min.rs | 4 +- tests/ui/arch/atomics/atomic_xor.rs | 4 +- 18 files changed, 60 insertions(+), 57 deletions(-) diff --git a/crates/spirv-std/src/arch/atomics.rs b/crates/spirv-std/src/arch/atomics.rs index a9c130921b..0262816488 100644 --- a/crates/spirv-std/src/arch/atomics.rs +++ b/crates/spirv-std/src/arch/atomics.rs @@ -15,7 +15,7 @@ use core::arch::asm; #[spirv_std_macros::gpu_only] #[doc(alias = "OpAtomicLoad")] #[inline] -pub unsafe fn atomic_load(ptr: &N) -> N { +pub unsafe fn atomic_load(ptr: &N) -> N { let mut result = N::default(); asm! { @@ -39,7 +39,10 @@ pub unsafe fn atomic_load(ptr: #[spirv_std_macros::gpu_only] #[doc(alias = "OpAtomicStore")] #[inline] -pub unsafe fn atomic_store(ptr: &mut N, value: N) { +pub unsafe fn atomic_store( + ptr: &mut N, + value: N, +) { asm! { "%u32 = OpTypeInt 32 0", "%scope = OpConstant %u32 {scope}", @@ -64,7 +67,7 @@ pub unsafe fn atomic_store(ptr: #[spirv_std_macros::gpu_only] #[doc(alias = "OpAtomicExchange")] #[inline] -pub unsafe fn atomic_exchange( +pub unsafe fn atomic_exchange( ptr: &mut N, value: N, ) -> N { @@ -102,9 +105,9 @@ pub unsafe fn atomic_exchange( #[inline] pub unsafe fn atomic_compare_exchange< I: Integer, - const SCOPE: u8, - const EQUAL: u8, - const UNEQUAL: u8, + const SCOPE: u32, + const EQUAL: u32, + const UNEQUAL: u32, >( ptr: &mut I, value: I, @@ -143,7 +146,7 @@ pub unsafe fn atomic_compare_exchange< /// The result is the original value. #[spirv_std_macros::gpu_only] #[doc(alias = "OpAtomicIIncrement")] -pub unsafe fn atomic_i_increment( +pub unsafe fn atomic_i_increment( ptr: &mut I, ) -> I { let mut old = I::default(); @@ -174,7 +177,7 @@ pub unsafe fn atomic_i_increment( +pub unsafe fn atomic_i_decrement( ptr: &mut I, ) -> I { let mut old = I::default(); @@ -183,7 +186,7 @@ pub unsafe fn atomic_i_decrement( +pub unsafe fn atomic_i_add( ptr: &mut I, value: I, ) -> I { @@ -239,7 +242,7 @@ pub unsafe fn atomic_i_add( #[spirv_std_macros::gpu_only] #[doc(alias = "OpAtomicISub")] #[inline] -pub unsafe fn atomic_i_sub( +pub unsafe fn atomic_i_sub( ptr: &mut I, value: I, ) -> I { @@ -274,7 +277,7 @@ pub unsafe fn atomic_i_sub( #[spirv_std_macros::gpu_only] #[doc(alias = "OpAtomicSMin")] #[inline] -pub unsafe fn atomic_s_min( +pub unsafe fn atomic_s_min( ptr: &mut I, value: I, ) -> I { @@ -309,7 +312,7 @@ pub unsafe fn atomic_s_min( +pub unsafe fn atomic_u_min( ptr: &mut I, value: I, ) -> I { @@ -344,7 +347,7 @@ pub unsafe fn atomic_u_min( +pub unsafe fn atomic_s_max( ptr: &mut I, value: I, ) -> I { @@ -379,7 +382,7 @@ pub unsafe fn atomic_s_max( +pub unsafe fn atomic_u_max( ptr: &mut I, value: I, ) -> I { @@ -413,7 +416,7 @@ pub unsafe fn atomic_u_max( +pub unsafe fn atomic_and( ptr: &mut I, value: I, ) -> I { @@ -447,7 +450,7 @@ pub unsafe fn atomic_and( #[spirv_std_macros::gpu_only] #[doc(alias = "OpAtomicOr")] #[inline] -pub unsafe fn atomic_or( +pub unsafe fn atomic_or( ptr: &mut I, value: I, ) -> I { @@ -481,7 +484,7 @@ pub unsafe fn atomic_or( #[spirv_std_macros::gpu_only] #[doc(alias = "OpAtomicXor")] #[inline] -pub unsafe fn atomic_xor( +pub unsafe fn atomic_xor( ptr: &mut I, value: I, ) -> I { @@ -514,7 +517,7 @@ pub unsafe fn atomic_xor( #[spirv_std_macros::gpu_only] #[doc(alias = "OpAtomicFlagTestAndSet")] #[inline] -pub unsafe fn atomic_flag_test_and_set( +pub unsafe fn atomic_flag_test_and_set( ptr: &mut I, ) -> bool { let mut old: bool = false; @@ -544,12 +547,12 @@ pub unsafe fn atomic_flag_test_and_set(ptr: &mut I) { +pub unsafe fn atomic_flag_clear(ptr: &mut I) { // Ensure the memory semantic is not Acquire or AcquireRelease assert!( SEMANTICS - != (crate::memory::Semantics::ACQUIRE.bits() as u8 - | crate::memory::Semantics::ACQUIRE_RELEASE.bits() as u8) + != (crate::memory::Semantics::ACQUIRE.bits() as u32 + | crate::memory::Semantics::ACQUIRE_RELEASE.bits() as u32) ); asm! { "%u32 = OpTypeInt 32 0", diff --git a/tests/ui/arch/atomics/atomic_and.rs b/tests/ui/arch/atomics/atomic_and.rs index 26dfb7acd1..fa63843418 100644 --- a/tests/ui/arch/atomics/atomic_and.rs +++ b/tests/ui/arch/atomics/atomic_and.rs @@ -12,8 +12,8 @@ pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &m let old = unsafe { spirv_std::arch::atomic_and::< _, - { Scope::Workgroup as u8 }, - { Semantics::UNIFORM_MEMORY.bits() as u8 }, + { Scope::Workgroup as u32 }, + { Semantics::UNIFORM_MEMORY.bits() as u32 }, >(&mut *buffer.index_unchecked_mut(0), 5) }; } diff --git a/tests/ui/arch/atomics/atomic_compare_exchange.rs b/tests/ui/arch/atomics/atomic_compare_exchange.rs index b6751c7166..bcdb976119 100644 --- a/tests/ui/arch/atomics/atomic_compare_exchange.rs +++ b/tests/ui/arch/atomics/atomic_compare_exchange.rs @@ -12,9 +12,9 @@ pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &m unsafe { let old = spirv_std::arch::atomic_compare_exchange::< _, - { Scope::CrossDevice as u8 }, - { Semantics::UNIFORM_MEMORY.bits() as u8 }, - { Semantics::UNIFORM_MEMORY.bits() as u8 }, + { Scope::CrossDevice as u32 }, + { Semantics::UNIFORM_MEMORY.bits() as u32 }, + { Semantics::UNIFORM_MEMORY.bits() as u32 }, >(&mut *buffer.index_unchecked_mut(0), 5, 10); } } diff --git a/tests/ui/arch/atomics/atomic_exchange.rs b/tests/ui/arch/atomics/atomic_exchange.rs index 6c24d0e160..966e4e726c 100644 --- a/tests/ui/arch/atomics/atomic_exchange.rs +++ b/tests/ui/arch/atomics/atomic_exchange.rs @@ -12,8 +12,8 @@ pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &m unsafe { let old = spirv_std::arch::atomic_exchange::< _, - { Scope::CrossDevice as u8 }, - { Semantics::UNIFORM_MEMORY.bits() as u8 }, + { Scope::CrossDevice as u32 }, + { Semantics::UNIFORM_MEMORY.bits() as u32 }, >(&mut *buffer.index_unchecked_mut(0), 5); } } diff --git a/tests/ui/arch/atomics/atomic_flag_clear.rs b/tests/ui/arch/atomics/atomic_flag_clear.rs index 53fb83643c..f8f10e8102 100644 --- a/tests/ui/arch/atomics/atomic_flag_clear.rs +++ b/tests/ui/arch/atomics/atomic_flag_clear.rs @@ -18,8 +18,8 @@ pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &m let old = unsafe { spirv_std::arch::atomic_flag_clear::< _, - { Scope::Workgroup as u8 }, - { Semantics::UNIFORM_MEMORY.bits() as u8 }, + { Scope::Workgroup as u32 }, + { Semantics::UNIFORM_MEMORY.bits() as u32 }, >(&mut *buffer.index_unchecked_mut(0)) }; } diff --git a/tests/ui/arch/atomics/atomic_flag_test_and_set.rs b/tests/ui/arch/atomics/atomic_flag_test_and_set.rs index 9b15399e3a..8d3ab6765f 100644 --- a/tests/ui/arch/atomics/atomic_flag_test_and_set.rs +++ b/tests/ui/arch/atomics/atomic_flag_test_and_set.rs @@ -18,8 +18,8 @@ pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &m let old = unsafe { spirv_std::arch::atomic_flag_test_and_set::< _, - { Scope::Workgroup as u8 }, - { Semantics::UNIFORM_MEMORY.bits() as u8 }, + { Scope::Workgroup as u32 }, + { Semantics::UNIFORM_MEMORY.bits() as u32 }, >(&mut *buffer.index_unchecked_mut(0)) }; } diff --git a/tests/ui/arch/atomics/atomic_i_add.rs b/tests/ui/arch/atomics/atomic_i_add.rs index 9b75858ed5..c4ee131c11 100644 --- a/tests/ui/arch/atomics/atomic_i_add.rs +++ b/tests/ui/arch/atomics/atomic_i_add.rs @@ -12,8 +12,8 @@ pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &m let old = unsafe { spirv_std::arch::atomic_i_add::< _, - { Scope::Workgroup as u8 }, - { Semantics::UNIFORM_MEMORY.bits() as u8 }, + { Scope::Workgroup as u32 }, + { Semantics::UNIFORM_MEMORY.bits() as u32 }, >(&mut *buffer.index_unchecked_mut(0), 5) }; } diff --git a/tests/ui/arch/atomics/atomic_i_decrement.rs b/tests/ui/arch/atomics/atomic_i_decrement.rs index fd4f099978..f1ca905375 100644 --- a/tests/ui/arch/atomics/atomic_i_decrement.rs +++ b/tests/ui/arch/atomics/atomic_i_decrement.rs @@ -14,8 +14,8 @@ pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &m let old = unsafe { spirv_std::arch::atomic_i_decrement::< _, - { Scope::Workgroup as u8 }, - { Semantics::NONE.bits() as u8 }, + { Scope::Workgroup as u32 }, + { Semantics::NONE.bits() as u32 }, >(reference) }; } diff --git a/tests/ui/arch/atomics/atomic_i_increment.rs b/tests/ui/arch/atomics/atomic_i_increment.rs index 142b2a0291..ec3fca8317 100644 --- a/tests/ui/arch/atomics/atomic_i_increment.rs +++ b/tests/ui/arch/atomics/atomic_i_increment.rs @@ -14,8 +14,8 @@ pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &m let old = unsafe { spirv_std::arch::atomic_i_increment::< _, - { Scope::Workgroup as u8 }, - { Semantics::NONE.bits() as u8 }, + { Scope::Workgroup as u32 }, + { Semantics::NONE.bits() as u32 }, >(reference) }; } diff --git a/tests/ui/arch/atomics/atomic_i_sub.rs b/tests/ui/arch/atomics/atomic_i_sub.rs index a3be6a4a82..7ea97f4046 100644 --- a/tests/ui/arch/atomics/atomic_i_sub.rs +++ b/tests/ui/arch/atomics/atomic_i_sub.rs @@ -12,8 +12,8 @@ pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &m let old = unsafe { spirv_std::arch::atomic_i_sub::< _, - { Scope::Workgroup as u8 }, - { Semantics::UNIFORM_MEMORY.bits() as u8 }, + { Scope::Workgroup as u32 }, + { Semantics::UNIFORM_MEMORY.bits() as u32 }, >(&mut *buffer.index_unchecked_mut(0), 5) }; } diff --git a/tests/ui/arch/atomics/atomic_load.rs b/tests/ui/arch/atomics/atomic_load.rs index d6a9e56e57..fd1b1781f9 100644 --- a/tests/ui/arch/atomics/atomic_load.rs +++ b/tests/ui/arch/atomics/atomic_load.rs @@ -12,8 +12,8 @@ pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &m unsafe { let output = spirv_std::arch::atomic_load::< _, - { Scope::CrossDevice as u8 }, - { Semantics::UNIFORM_MEMORY.bits() as u8 }, + { Scope::CrossDevice as u32 }, + { Semantics::UNIFORM_MEMORY.bits() as u32 }, >(&mut *buffer.index_unchecked_mut(0)); } } diff --git a/tests/ui/arch/atomics/atomic_or.rs b/tests/ui/arch/atomics/atomic_or.rs index a3b6cf813a..7d226dc82a 100644 --- a/tests/ui/arch/atomics/atomic_or.rs +++ b/tests/ui/arch/atomics/atomic_or.rs @@ -12,8 +12,8 @@ pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &m let old = unsafe { spirv_std::arch::atomic_or::< _, - { Scope::Workgroup as u8 }, - { Semantics::UNIFORM_MEMORY.bits() as u8 }, + { Scope::Workgroup as u32 }, + { Semantics::UNIFORM_MEMORY.bits() as u32 }, >(&mut *buffer.index_unchecked_mut(0), 5) }; } diff --git a/tests/ui/arch/atomics/atomic_s_max.rs b/tests/ui/arch/atomics/atomic_s_max.rs index def6c76bda..f4451cd54e 100644 --- a/tests/ui/arch/atomics/atomic_s_max.rs +++ b/tests/ui/arch/atomics/atomic_s_max.rs @@ -12,8 +12,8 @@ pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &m let old = unsafe { spirv_std::arch::atomic_s_max::< _, - { Scope::Workgroup as u8 }, - { Semantics::UNIFORM_MEMORY.bits() as u8 }, + { Scope::Workgroup as u32 }, + { Semantics::UNIFORM_MEMORY.bits() as u32 }, >(&mut *buffer.index_unchecked_mut(0), 5) }; } diff --git a/tests/ui/arch/atomics/atomic_s_min.rs b/tests/ui/arch/atomics/atomic_s_min.rs index fc6c2b402a..38fceb78fa 100644 --- a/tests/ui/arch/atomics/atomic_s_min.rs +++ b/tests/ui/arch/atomics/atomic_s_min.rs @@ -12,8 +12,8 @@ pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &m let old = unsafe { spirv_std::arch::atomic_s_min::< _, - { Scope::Workgroup as u8 }, - { Semantics::UNIFORM_MEMORY.bits() as u8 }, + { Scope::Workgroup as u32 }, + { Semantics::UNIFORM_MEMORY.bits() as u32 }, >(&mut *buffer.index_unchecked_mut(0), 5) }; } diff --git a/tests/ui/arch/atomics/atomic_store.rs b/tests/ui/arch/atomics/atomic_store.rs index e5ec22dbc5..8e44bf17f1 100644 --- a/tests/ui/arch/atomics/atomic_store.rs +++ b/tests/ui/arch/atomics/atomic_store.rs @@ -12,8 +12,8 @@ pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &m let old = unsafe { spirv_std::arch::atomic_store::< _, - { Scope::Workgroup as u8 }, - { Semantics::UNIFORM_MEMORY.bits() as u8 }, + { Scope::Workgroup as u32 }, + { Semantics::UNIFORM_MEMORY.bits() as u32 }, >(&mut *buffer.index_unchecked_mut(0), 5) }; } diff --git a/tests/ui/arch/atomics/atomic_u_max.rs b/tests/ui/arch/atomics/atomic_u_max.rs index add3122451..62cbd8c0f8 100644 --- a/tests/ui/arch/atomics/atomic_u_max.rs +++ b/tests/ui/arch/atomics/atomic_u_max.rs @@ -12,8 +12,8 @@ pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &m let old = unsafe { spirv_std::arch::atomic_u_max::< _, - { Scope::Workgroup as u8 }, - { Semantics::UNIFORM_MEMORY.bits() as u8 }, + { Scope::Workgroup as u32 }, + { Semantics::UNIFORM_MEMORY.bits() as u32 }, >(&mut *buffer.index_unchecked_mut(0), 5) }; } diff --git a/tests/ui/arch/atomics/atomic_u_min.rs b/tests/ui/arch/atomics/atomic_u_min.rs index daa8c4dce1..0297fa3a9d 100644 --- a/tests/ui/arch/atomics/atomic_u_min.rs +++ b/tests/ui/arch/atomics/atomic_u_min.rs @@ -12,8 +12,8 @@ pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &m let old = unsafe { spirv_std::arch::atomic_u_min::< _, - { Scope::Workgroup as u8 }, - { Semantics::UNIFORM_MEMORY.bits() as u8 }, + { Scope::Workgroup as u32 }, + { Semantics::UNIFORM_MEMORY.bits() as u32 }, >(&mut *buffer.index_unchecked_mut(0), 5) }; } diff --git a/tests/ui/arch/atomics/atomic_xor.rs b/tests/ui/arch/atomics/atomic_xor.rs index 33e183ac58..526fa068ed 100644 --- a/tests/ui/arch/atomics/atomic_xor.rs +++ b/tests/ui/arch/atomics/atomic_xor.rs @@ -12,8 +12,8 @@ pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &m let old = unsafe { spirv_std::arch::atomic_xor::< _, - { Scope::Workgroup as u8 }, - { Semantics::UNIFORM_MEMORY.bits() as u8 }, + { Scope::Workgroup as u32 }, + { Semantics::UNIFORM_MEMORY.bits() as u32 }, >(&mut *buffer.index_unchecked_mut(0), 5) }; } From 44e37252e650017b1fbb3f71bc016098ed647196 Mon Sep 17 00:00:00 2001 From: = <=> Date: Tue, 9 Aug 2022 14:38:41 +0200 Subject: [PATCH 10/11] Added atomic flags. Small refactor --- crates/spirv-std/src/arch/atomics.rs | 189 +++++++++++++++++++++------ 1 file changed, 146 insertions(+), 43 deletions(-) diff --git a/crates/spirv-std/src/arch/atomics.rs b/crates/spirv-std/src/arch/atomics.rs index 0262816488..6ffab9ca35 100644 --- a/crates/spirv-std/src/arch/atomics.rs +++ b/crates/spirv-std/src/arch/atomics.rs @@ -1,14 +1,12 @@ -//! SPIR-V Atomics -//! +#[cfg(target_arch = "spirv")] +use core::arch::asm; use crate::{ + float::Float, integer::{Integer, SignedInteger, UnsignedInteger}, number::Number, }; -#[cfg(target_arch = "spirv")] -use core::arch::asm; - /// Atomically load through `ptr` using the given `SEMANTICS`. All subparts of /// the value that is loaded are read atomically with respect to all other /// atomic accesses to it within `SCOPE`. @@ -52,7 +50,7 @@ pub unsafe fn atomic_store( scope = const SCOPE, semantics = const SEMANTICS, ptr = in(reg) ptr, - value = in(reg) &value, + value = in(reg) &value } } @@ -83,8 +81,8 @@ pub unsafe fn atomic_exchange scope = const SCOPE, semantics = const SEMANTICS, ptr = in(reg) ptr, - value = in(reg) &value, old = in(reg) &mut old, + value = in(reg) &value } old @@ -146,6 +144,7 @@ pub unsafe fn atomic_compare_exchange< /// The result is the original value. #[spirv_std_macros::gpu_only] #[doc(alias = "OpAtomicIIncrement")] +#[inline] pub unsafe fn atomic_i_increment( ptr: &mut I, ) -> I { @@ -160,7 +159,7 @@ pub unsafe fn atomic_i_increment( semantics = const SEMANTICS, ptr = in(reg) ptr, old = in(reg) &mut old, - value = in(reg) &value, + value = in(reg) &value } old @@ -259,7 +258,7 @@ pub unsafe fn atomic_i_sub( semantics = const SEMANTICS, ptr = in(reg) ptr, old = in(reg) &mut old, - value = in(reg) &value, + value = in(reg) &value } old @@ -277,11 +276,11 @@ pub unsafe fn atomic_i_sub( #[spirv_std_macros::gpu_only] #[doc(alias = "OpAtomicSMin")] #[inline] -pub unsafe fn atomic_s_min( - ptr: &mut I, - value: I, -) -> I { - let mut old = I::default(); +pub unsafe fn atomic_s_min( + ptr: &mut S, + value: S, +) -> S { + let mut old = S::default(); asm! { "%u32 = OpTypeInt 32 0", @@ -294,7 +293,7 @@ pub unsafe fn atomic_s_min( - ptr: &mut I, - value: I, -) -> I { - let mut old = I::default(); +pub unsafe fn atomic_u_min( + ptr: &mut U, + value: U, +) -> U { + let mut old = U::default(); asm! { "%u32 = OpTypeInt 32 0", @@ -329,7 +328,7 @@ pub unsafe fn atomic_u_min( - ptr: &mut I, - value: I, -) -> I { - let mut old = I::default(); +pub unsafe fn atomic_s_max( + ptr: &mut S, + value: S, +) -> S { + let mut old = S::default(); asm! { "%u32 = OpTypeInt 32 0", @@ -364,7 +363,7 @@ pub unsafe fn atomic_s_max( - ptr: &mut I, - value: I, -) -> I { - let mut old = I::default(); +pub unsafe fn atomic_u_max( + ptr: &mut U, + value: U, +) -> U { + let mut old = U::default(); asm! { "%u32 = OpTypeInt 32 0", @@ -399,7 +398,7 @@ pub unsafe fn atomic_u_max( semantics = const SEMANTICS, ptr = in(reg) ptr, old = in(reg) &mut old, - value = in(reg) &value, + value = in(reg) &value } old @@ -467,7 +466,7 @@ pub unsafe fn atomic_or( semantics = const SEMANTICS, ptr = in(reg) ptr, old = in(reg) &mut old, - value = in(reg) &value, + value = in(reg) &value } old @@ -501,7 +500,7 @@ pub unsafe fn atomic_xor( semantics = const SEMANTICS, ptr = in(reg) ptr, old = in(reg) &mut old, - value = in(reg) &value, + value = in(reg) &value } old @@ -517,7 +516,7 @@ pub unsafe fn atomic_xor( #[spirv_std_macros::gpu_only] #[doc(alias = "OpAtomicFlagTestAndSet")] #[inline] -pub unsafe fn atomic_flag_test_and_set( +pub unsafe fn atomic_flag_test_and_set( ptr: &mut I, ) -> bool { let mut old: bool = false; @@ -532,7 +531,7 @@ pub unsafe fn atomic_flag_test_and_set(ptr: &mut I) { +pub unsafe fn atomic_flag_clear(ptr: &mut I) { // Ensure the memory semantic is not Acquire or AcquireRelease assert!( SEMANTICS - != (crate::memory::Semantics::ACQUIRE.bits() as u32 - | crate::memory::Semantics::ACQUIRE_RELEASE.bits() as u32) + != (crate::memory::Semantics::ACQUIRE.bits() as u8 + | crate::memory::Semantics::ACQUIRE_RELEASE.bits() as u8) ); asm! { "%u32 = OpTypeInt 32 0", @@ -561,6 +560,110 @@ pub unsafe fn atomic_flag_clear( + ptr: &mut F, + value: F, +) -> F { + let mut old = F::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%scope = OpConstant %u32 {scope}", + "%semantics = OpConstant %u32 {semantics}", + "%value = OpLoad _ {value}", + "%old = OpAtomicFMinEXT _ {ptr} %scope %semantics %value", + "OpStore {old} %old", + scope = const SCOPE, + semantics = const SEMANTICS, ptr = in(reg) ptr, + old = in(reg) &mut old, + value = in(reg) &value + } + + old +} + +/// Perform the following steps atomically with respect to any other atomic +/// accesses within Scope to the same location: +/// +/// 1. Load through `ptr` to get an original value, +/// 2. Get a new value by finding the largest signed integer of original value +/// and `value`, and +/// 3. Store the new value back through `ptr`. +/// +/// The result is the original value. +#[spirv_std_macros::gpu_only] +#[doc(alias = "OpAtomicFMaxEXT")] +#[inline] +pub unsafe fn atomic_f_max( + ptr: &mut F, + value: F, +) -> F { + let mut old = F::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%scope = OpConstant %u32 {scope}", + "%semantics = OpConstant %u32 {semantics}", + "%value = OpLoad _ {value}", + "%old = OpAtomicFMaxEXT _ {ptr} %scope %semantics %value", + "OpStore {old} %old", + scope = const SCOPE, + semantics = const SEMANTICS, + ptr = in(reg) ptr, + old = in(reg) &mut old, + value = in(reg) &value } + + old +} + +/// Perform the following steps atomically with respect to any other atomic +/// accesses within `SCOPE` to the same location: +/// +/// 1) load through `ptr` to get an original value, +/// 2) get a new value by integer addition of original value and `value`, and +/// 3) store the new value back through `ptr`. +/// +/// The result is the Original Value. +#[spirv_std_macros::gpu_only] +#[doc(alias = "OpAtomicFAddEXT")] +#[inline] +pub unsafe fn atomic_f_add( + ptr: &mut F, + value: F, +) -> F { + let mut old = F::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%scope = OpConstant %u32 {scope}", + "%semantics = OpConstant %u32 {semantics}", + "%value = OpLoad _ {value}", + "%old = OpAtomicFMaxEXT _ {ptr} %scope %semantics %value", + "OpStore {old} %old", + scope = const SCOPE, + semantics = const SEMANTICS, + ptr = in(reg) ptr, + old = in(reg) &mut old, + value = in(reg) &value + } + + old } From 1dee7bd7646a32bb1430c71d8985286aa658750b Mon Sep 17 00:00:00 2001 From: = <=> Date: Tue, 9 Aug 2022 14:41:24 +0200 Subject: [PATCH 11/11] Changed parameter type from u8 to u32 --- crates/spirv-std/src/arch/atomics.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/spirv-std/src/arch/atomics.rs b/crates/spirv-std/src/arch/atomics.rs index 6ffab9ca35..88f51eb683 100644 --- a/crates/spirv-std/src/arch/atomics.rs +++ b/crates/spirv-std/src/arch/atomics.rs @@ -516,7 +516,7 @@ pub unsafe fn atomic_xor( #[spirv_std_macros::gpu_only] #[doc(alias = "OpAtomicFlagTestAndSet")] #[inline] -pub unsafe fn atomic_flag_test_and_set( +pub unsafe fn atomic_flag_test_and_set( ptr: &mut I, ) -> bool { let mut old: bool = false; @@ -546,12 +546,12 @@ pub unsafe fn atomic_flag_test_and_set(ptr: &mut I) { +pub unsafe fn atomic_flag_clear(ptr: &mut I) { // Ensure the memory semantic is not Acquire or AcquireRelease assert!( SEMANTICS - != (crate::memory::Semantics::ACQUIRE.bits() as u8 - | crate::memory::Semantics::ACQUIRE_RELEASE.bits() as u8) + != (crate::memory::Semantics::ACQUIRE.bits() as u32 + | crate::memory::Semantics::ACQUIRE_RELEASE.bits() as u32) ); asm! { "%u32 = OpTypeInt 32 0",