Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Binding Macros

wgsl-rs provides declarative macros for declaring GPU bindings. Each macro emits both the WGSL binding declaration and a Rust-side static so the same code works on CPU and GPU. To auto-generate wgpu bind group layouts and buffer descriptors from these bindings, see wgpu Linkage.

Overview

MacroWGSLRust staticAccess
uniform!@group(N) @binding(M) var<uniform> ...Uniform<T>get!(NAME)
storage!@group(N) @binding(M) var<storage, ...> ...Storage<T>get! / get_mut!
workgroup!var<workgroup> ...Workgroup<T>get! / get_mut!
texture!@group(N) @binding(M) var ...hidden __NAME + pub const NAMEby value
sampler!@group(N) @binding(M) var ...hidden __NAME + pub const NAMEby value
ptr!ptr<address_space, T>&mut T*p
discard!discard;thread-local flagdirect call

Declaration and Access

Binding macros are used at module scope inside a #[wgsl] module. They declare the WGSL binding and the Rust-side static simultaneously:

#![allow(unused)]
fn main() {
#[wgsl]
pub mod shader {
    use wgsl_rs::std::*;

    uniform!(group(0), binding(0), CAMERA: Camera);

    pub fn view() -> Mat4f {
        get!(CAMERA).view
    }
}
}

get! and get_mut!

  • get!(VAR) reads a uniform!, storage!, or workgroup! binding. It returns a guard that derefs to the value.
  • get!(VAR, T) reads with an explicit type, used inside generic/template entry points.
  • get_mut!(VAR) returns a mutable guard for storage! and workgroup! bindings.
#![allow(unused)]
fn main() {
pub fn add_delta() {
    let mut s = get_mut!(COUNTER);
    s.value += 1;
}
}

Slab Helpers

For packed slab buffers, use the slab_copy! macro. It is bidirectional — pass the slab as the source to read from a storage buffer into a local array, or pass the slab as the destination to write from a local array into a storage buffer:

#![allow(unused)]
fn main() {
slab_copy!(src, src_offset, dest, dest_offset, size)
}

Copies size elements from src[src_offset..] into dest[dest_offset..]. On the GPU this emits a WGSL for loop; on the CPU it is a simple element-by-element copy.

#![allow(unused)]
fn main() {
let mut raw = [0u32; 4];
slab_copy!(get!(SLAB), index, raw, 0, 4);
slab_copy!(raw, 0, get_mut!(SLAB), index, 4);
}