use core::mem;
#[spirv(buffer_load_intrinsic)]
#[inline(never)]
#[spirv_std_macros::gpu_only]
unsafe fn buffer_load_intrinsic<T>(
buffer: &[u32],
offset: u32,
) -> T {
buffer
.as_ptr()
.cast::<u8>()
.add(offset as usize)
.cast::<T>()
.read()
}
#[spirv(buffer_store_intrinsic)]
#[inline(never)]
#[spirv_std_macros::gpu_only]
unsafe fn buffer_store_intrinsic<T>(
buffer: &mut [u32],
offset: u32,
value: T,
) {
buffer
.as_mut_ptr()
.cast::<u8>()
.add(offset as usize)
.cast::<T>()
.write(value);
}
#[repr(transparent)]
pub struct ByteAddressableBuffer<'a> {
pub data: &'a mut [u32],
}
impl<'a> ByteAddressableBuffer<'a> {
#[inline]
pub fn new(data: &'a mut [u32]) -> Self {
Self { data }
}
pub unsafe fn load<T>(&self, byte_index: u32) -> T {
if byte_index + mem::size_of::<T>() as u32 > self.data.len() as u32 {
panic!("Index out of range");
}
buffer_load_intrinsic(self.data, byte_index)
}
pub unsafe fn load_unchecked<T>(&self, byte_index: u32) -> T {
buffer_load_intrinsic(self.data, byte_index)
}
pub unsafe fn store<T>(&mut self, byte_index: u32, value: T) {
if byte_index + mem::size_of::<T>() as u32 > self.data.len() as u32 {
panic!("Index out of range");
}
buffer_store_intrinsic(self.data, byte_index, value);
}
pub unsafe fn store_unchecked<T>(&mut self, byte_index: u32, value: T) {
buffer_store_intrinsic(self.data, byte_index, value);
}
}