Slab Read/Write
Demonstrates wgsl-rs macros for reading from and writing to u32 “slabs”. The slab can be any indexable item such as an array, RuntimeArray, or storage pointer. The slab_copy! macro expands to an element-wise copy loop in WGSL.
Rust Source
#![allow(unused)]
fn main() {
#[wgsl]
pub mod slab_read_write {
//! `wgsl-rs` includes macros for reading to and from u32 "slabs".
//!
//! The slab can be any indexable item such as an array, RuntimeArray,
//! storage pointer, etc.
use wgsl_rs::std::*;
pub struct Data {
pub one: f32,
pub two: u32,
pub three_four: Vec2f,
}
impl Data {
/// `Data`'s slab size.
///
/// This is the number of u32 slots it occupies in a u32 slab.
pub const SLAB_SIZE: usize = 4;
/// Returns an array container to hold ephemeral data read from a slab.
pub fn array_container() -> [u32; Self::SLAB_SIZE] {
[0, 0, 0, 0]
}
/// Convert an array into `Data`.
pub fn from_array(arr: [u32; Self::SLAB_SIZE]) -> Self {
Self {
one: bitcast_f32(arr[0]),
two: arr[1],
three_four: vec2f(bitcast_f32(arr[2]), bitcast_f32(arr[3])),
}
}
/// Convert `Data` into an array.
pub fn to_array(data: Self) -> [u32; Self::SLAB_SIZE] {
[
bitcast_u32(data.one),
data.two,
bitcast_u32(data.three_four.x()),
bitcast_u32(data.three_four.y()),
]
}
}
storage!(group(0), binding(0), read_write, SLAB: RuntimeArray<u32>);
#[compute]
#[workgroup_size(8)]
pub fn slab_example(#[builtin(local_invocation_index)] local_idx: u32) {
let index = local_idx;
// Create our `Data` struct from extracted data from the slab
let mut data: Data;
{
// Extract the u32 data from the slab
let mut array_data = Data::array_container();
slab_copy!(get!(SLAB), index, array_data, 0, Data::SLAB_SIZE);
data = Data::from_array(array_data);
}
// Modify it
data.three_four.x = 123.0;
// Write the modified `Data` struct back to the slab
let out_array = Data::to_array(data);
slab_copy!(out_array, 0, get_mut!(SLAB), index, Data::SLAB_SIZE);
}
}
}
Generated WGSL
struct Data {
one: f32,
two: u32,
three_four: vec2f
}
const Data__1SLAB_SIZE: u32 = 4;
fn Data__1array_container() -> array<u32, Data__1SLAB_SIZE> {
return array(0, 0, 0, 0);
}
fn Data__1from_array(arr: array<u32, Data__1SLAB_SIZE>) -> Data {
return Data(bitcast<f32>(arr[0]), arr[1], vec2f(bitcast<f32>(arr[2]), bitcast<f32>(arr[3])));
}
fn Data__1to_array(data: Data) -> array<u32, Data__1SLAB_SIZE> {
return array(bitcast<u32>(data.one), data.two, bitcast<u32>(data.three_four.x), bitcast<u32>(data.three_four.y));
}
@group(0) @binding(0) var<storage, read_write> SLAB: array<u32>;
@compute @workgroup_size(8) fn slab_example(@builtin(local_invocation_index) local_idx: u32) {
let index = local_idx;
var data: Data;
{
var array_data = Data__1array_container();
for (var _i: u32 = 0u; _i < Data__1SLAB_SIZE; _i++) {
array_data[0 + _i] = SLAB[index + _i];
}
data = Data__1from_array(array_data);
}
data.three_four.x = 123.0;
let out_array = Data__1to_array(data);
for (var _i: u32 = 0u; _i < Data__1SLAB_SIZE; _i++) {
SLAB[index + _i] = out_array[0 + _i];
}
}
Notes
slab_copy!(src, src_offset, dest, dest_offset, size)is bidirectional: pass the slab assrcto read, or asdestto write.Self::SLAB_SIZE(an associated const) is mangled toData__1SLAB_SIZEin WGSL (the_1is the bijective mangle escaping the underscore inSLAB_SIZE).