#[inline(always)]
pub fn atomic_add_i32(ptr: &mut i32, value: i32) -> i32 {
#[cfg(target_arch = "spirv")]
unsafe {
spirv_std::arch::atomic_i_add::<
i32,
{ spirv_std::memory::Scope::QueueFamily as u32 },
{ spirv_std::memory::Semantics::NONE.bits() },
>(ptr, value)
}
#[cfg(not(target_arch = "spirv"))]
{
use core::sync::atomic::{AtomicI32, Ordering};
let atomic = unsafe { &*(ptr as *mut i32 as *const AtomicI32) };
atomic.fetch_add(value, Ordering::Relaxed)
}
}
#[inline(always)]
pub fn atomic_add_u32(ptr: &mut u32, value: u32) -> u32 {
#[cfg(target_arch = "spirv")]
unsafe {
spirv_std::arch::atomic_i_add::<
u32,
{ spirv_std::memory::Scope::QueueFamily as u32 },
{ spirv_std::memory::Semantics::NONE.bits() },
>(ptr, value)
}
#[cfg(not(target_arch = "spirv"))]
{
use core::sync::atomic::{AtomicU32, Ordering};
let atomic = unsafe { &*(ptr as *mut u32 as *const AtomicU32) };
atomic.fetch_add(value, Ordering::Relaxed)
}
}
#[inline(always)]
pub fn atomic_max_u32(ptr: &mut u32, value: u32) -> u32 {
#[cfg(target_arch = "spirv")]
unsafe {
spirv_std::arch::atomic_u_max::<
u32,
{ spirv_std::memory::Scope::QueueFamily as u32 },
{ spirv_std::memory::Semantics::NONE.bits() },
>(ptr, value)
}
#[cfg(not(target_arch = "spirv"))]
{
use core::sync::atomic::{AtomicU32, Ordering};
let atomic = unsafe { &*(ptr as *mut u32 as *const AtomicU32) };
atomic.fetch_max(value, Ordering::Relaxed)
}
}
#[inline(always)]
pub fn atomic_min_u32(ptr: &mut u32, value: u32) -> u32 {
#[cfg(target_arch = "spirv")]
unsafe {
spirv_std::arch::atomic_u_min::<
u32,
{ spirv_std::memory::Scope::QueueFamily as u32 },
{ spirv_std::memory::Semantics::NONE.bits() },
>(ptr, value)
}
#[cfg(not(target_arch = "spirv"))]
{
use core::sync::atomic::{AtomicU32, Ordering};
let atomic = unsafe { &*(ptr as *mut u32 as *const AtomicU32) };
atomic.fetch_min(value, Ordering::Relaxed)
}
}
#[inline(always)]
pub fn atomic_load_u32(ptr: &mut u32) -> u32 {
#[cfg(target_arch = "spirv")]
unsafe {
spirv_std::arch::atomic_load::<
u32,
{ spirv_std::memory::Scope::QueueFamily as u32 },
{ spirv_std::memory::Semantics::NONE.bits() },
>(ptr)
}
#[cfg(not(target_arch = "spirv"))]
{
use core::sync::atomic::{AtomicU32, Ordering};
let atomic = unsafe { &*(ptr as *mut u32 as *const AtomicU32) };
atomic.load(Ordering::Relaxed)
}
}
#[inline(always)]
pub fn atomic_load_u32_shared(ptr: &u32) -> u32 {
#[cfg(target_arch = "spirv")]
unsafe {
spirv_std::arch::atomic_load::<
u32,
{ spirv_std::memory::Scope::QueueFamily as u32 },
{ spirv_std::memory::Semantics::NONE.bits() },
>(ptr)
}
#[cfg(not(target_arch = "spirv"))]
{
use core::sync::atomic::{AtomicU32, Ordering};
let atomic = unsafe { &*(ptr as *const u32 as *const AtomicU32) };
atomic.load(Ordering::Relaxed)
}
}
#[inline(always)]
pub fn atomic_exchange_u32(ptr: &mut u32, value: u32) -> u32 {
#[cfg(target_arch = "spirv")]
unsafe {
spirv_std::arch::atomic_exchange::<
u32,
{ spirv_std::memory::Scope::QueueFamily as u32 },
{ spirv_std::memory::Semantics::NONE.bits() },
>(ptr, value)
}
#[cfg(not(target_arch = "spirv"))]
{
use core::sync::atomic::{AtomicU32, Ordering};
let atomic = unsafe { &*(ptr as *mut u32 as *const AtomicU32) };
atomic.swap(value, Ordering::Relaxed)
}
}
#[inline(always)]
pub fn atomic_compare_exchange_u32(ptr: &mut u32, value: u32, comparator: u32) -> u32 {
#[cfg(target_arch = "spirv")]
unsafe {
spirv_std::arch::atomic_compare_exchange::<
u32,
{ spirv_std::memory::Scope::QueueFamily as u32 },
{ spirv_std::memory::Semantics::NONE.bits() },
{ spirv_std::memory::Semantics::NONE.bits() },
>(ptr, value, comparator)
}
#[cfg(not(target_arch = "spirv"))]
{
use core::sync::atomic::{AtomicU32, Ordering};
let atomic = unsafe { &*(ptr as *mut u32 as *const AtomicU32) };
match atomic.compare_exchange(comparator, value, Ordering::Relaxed, Ordering::Relaxed) {
Ok(old) => old,
Err(old) => old,
}
}
}
#[inline(always)]
pub fn atomic_or_u32(ptr: &mut u32, value: u32) -> u32 {
#[cfg(target_arch = "spirv")]
unsafe {
spirv_std::arch::atomic_or::<
u32,
{ spirv_std::memory::Scope::QueueFamily as u32 },
{ spirv_std::memory::Semantics::NONE.bits() },
>(ptr, value)
}
#[cfg(not(target_arch = "spirv"))]
{
use core::sync::atomic::{AtomicU32, Ordering};
let atomic = unsafe { &*(ptr as *mut u32 as *const AtomicU32) };
atomic.fetch_or(value, Ordering::Relaxed)
}
}
#[inline(always)]
pub fn atomic_and_u32(ptr: &mut u32, value: u32) -> u32 {
#[cfg(target_arch = "spirv")]
unsafe {
spirv_std::arch::atomic_and::<
u32,
{ spirv_std::memory::Scope::QueueFamily as u32 },
{ spirv_std::memory::Semantics::NONE.bits() },
>(ptr, value)
}
#[cfg(not(target_arch = "spirv"))]
{
use core::sync::atomic::{AtomicU32, Ordering};
let atomic = unsafe { &*(ptr as *mut u32 as *const AtomicU32) };
atomic.fetch_and(value, Ordering::Relaxed)
}
}
#[inline]
pub fn atomic_add_f32(ptr: &mut u32, value: f32) {
loop {
let old_bits = atomic_load_u32(ptr);
let new_val = f32::from_bits(old_bits) + value;
let new_bits = new_val.to_bits();
let prev = atomic_compare_exchange_u32(ptr, new_bits, old_bits);
if prev == old_bits {
break;
}
}
}
#[inline(always)]
pub fn atomic_add_u32_workgroup(ptr: &mut u32, value: u32) -> u32 {
#[cfg(target_arch = "spirv")]
unsafe {
spirv_std::arch::atomic_i_add::<
u32,
{ spirv_std::memory::Scope::Workgroup as u32 },
{ spirv_std::memory::Semantics::NONE.bits() },
>(ptr, value)
}
#[cfg(not(target_arch = "spirv"))]
{
use core::sync::atomic::{AtomicU32, Ordering};
let atomic = unsafe { &*(ptr as *mut u32 as *const AtomicU32) };
atomic.fetch_add(value, Ordering::Relaxed)
}
}
#[inline(always)]
pub fn atomic_max_u32_workgroup(ptr: &mut u32, value: u32) -> u32 {
#[cfg(target_arch = "spirv")]
unsafe {
spirv_std::arch::atomic_u_max::<
u32,
{ spirv_std::memory::Scope::Workgroup as u32 },
{ spirv_std::memory::Semantics::NONE.bits() },
>(ptr, value)
}
#[cfg(not(target_arch = "spirv"))]
{
use core::sync::atomic::{AtomicU32, Ordering};
let atomic = unsafe { &*(ptr as *mut u32 as *const AtomicU32) };
atomic.fetch_max(value, Ordering::Relaxed)
}
}
#[inline(always)]
pub fn atomic_store_u32_workgroup(ptr: &mut u32, value: u32) {
#[cfg(target_arch = "spirv")]
unsafe {
spirv_std::arch::atomic_exchange::<
u32,
{ spirv_std::memory::Scope::Workgroup as u32 },
{ spirv_std::memory::Semantics::NONE.bits() },
>(ptr, value);
}
#[cfg(not(target_arch = "spirv"))]
{
use core::sync::atomic::{AtomicU32, Ordering};
let atomic = unsafe { &*(ptr as *mut u32 as *const AtomicU32) };
atomic.store(value, Ordering::Relaxed);
}
}
#[inline(always)]
pub fn atomic_load_u32_workgroup(ptr: &mut u32) -> u32 {
#[cfg(target_arch = "spirv")]
unsafe {
spirv_std::arch::atomic_load::<
u32,
{ spirv_std::memory::Scope::Workgroup as u32 },
{ spirv_std::memory::Semantics::NONE.bits() },
>(ptr)
}
#[cfg(not(target_arch = "spirv"))]
{
use core::sync::atomic::{AtomicU32, Ordering};
let atomic = unsafe { &*(ptr as *mut u32 as *const AtomicU32) };
atomic.load(Ordering::Relaxed)
}
}