Synchronization
Synchronization builtins order memory accesses between invocations in a compute workgroup. They are only valid inside compute shaders; calling them from vertex or fragment stages is a WGSL error.
Barriers
| Function | WGSL Equivalent | Description |
|---|---|---|
workgroup_barrier() | workgroupBarrier | Sync all invocations in the workgroup at this point. |
storage_barrier() | storageBarrier | Memory barrier for storage! accesses across the workgroup. |
texture_barrier() | textureBarrier | Memory barrier for storage-texture writes. |
All three take no arguments and return unit. On the CPU they are no-ops — a single-threaded CPU dispatch has nothing to synchronize — but they still compile and execute, so the same shader can run in both worlds.
workgroupUniformLoad
workgroupUniformLoad<T>(&var: &T) -> T reads a workgroup variable such that
all invocations in the workgroup observe the same value. WGSL requires the
loaded address to be uniform across the workgroup.
wgsl-rs models this via the WorkgroupUniformLoad trait, implemented for the
types that are safe to load this way.
#![allow(unused)]
fn main() {
#[wgsl]
pub mod sync_example {
use wgsl_rs::std::*;
workgroup!(SHARED: [u32; 64]);
#[compute]
#[workgroup_size(64)]
pub fn cs(#[builtin(local_invocation_id)] lid: Vec3u) {
let idx = lid.x() as usize;
get_mut!(SHARED)[idx] = lid.x();
workgroup_barrier();
let partner = get!(SHARED)[((lid.x() + 1u32) % 64u32) as usize];
workgroup_barrier();
let uniform_first = workgroup_uniform_load(&SHARED);
}
}
}
When to use which
workgroup_barrier— gate control flow: ensure every invocation has reached a point before any proceeds.storage_barrier— gatestorage!reads/writes across invocations.texture_barrier— gate storage-texture writes before subsequent reads.workgroup_uniform_load— broadcast one uniform value to the whole workgroup (useful for divergent control flow convergence).