Is it possible to access textures atomically in WGSL? By atomically, I mean like specified in the "Atomic Operations" section of the documentation of OpenGL's GL_TEXTURE_*.
If not, will changing to GLSL work in WGPU?
Hi, recently I have been experimenting with WGPU and WGSL, specifically trying to create a cellular automata and storing it's data in a texture_storage_2d
.
I was having problems with the fact that accessing the texture asynchronously caused race conditions that made cells disappear (if two cells try to advance to the same point at the same time, they will overwrite one another)
I did some research and couldn't find any solution to my problem in the WGSL spec, but I found something similar in OpenGL and GLSL with OpenGL's GL_TEXTURE_* called atomic operations on textures (which exist AFAIK only for u32
or i32
in WGSL).
Is there something like GL_TEXTURE_*
in WGSL?
Or is there some alternative that I am not aware of?
And is changing to GLSL (while staying with WGPU) the only solution? Will it even work?
After doing some tests I confirmed two things:
This following snippet is paraphrased from my original code, it is not tested but should work.
@group(0) @binding(0) var texture: texture_storage_2d<rg32uint, read_write>;
struct Locks {
locks: array<array<atomic<u32>, 50>, 50>,
};
@group(0) @binding(1) var<storage, read_write> locks: Locks;
fn lock(location: vec2<u32>) -> bool {
let lock_ptr = &locks.locks[location.y][location.x];
let original_lock_value = atomicLoad(lock_ptr);
if (original_lock_value > 0u) {
return false;
}
return atomicAdd(lock_ptr, 1u) == original_lock_value;
}
fn unlock(location: vec2<u32>) {
atomicStore(&locks.locks[location.y][location.x], 0u);
}
Ideally, I'd use atomicCompareExchangeWeak
instead of that somewhat complex logic in lock
, but atomicCompareExchangeWeak
didn't seem to work on my machine so I created similar logic myself.
Just to clarify, reading from the texture should be possible at any time but writing to the texture at location
should be done only if lock(location)
returned true
.
Don't forget to call unlock
after every write and between shader calls to reset the locks :)