We have an OpenGL solver. Given a list of many items, each has a coordinate and a float value. We run a compute shader of the size of those items that does the computation and adds the value to the existing values in the float image using the function imageAtomicAdd
and the float extension. This way, the addition is guaranteed just in case 2 items happen to have the same coordinate value simultaneously.
Now, we need to move it to WebGPU using js. I tried looking for an atomic add function on float texture/buffer but with limited success. So, the code currently is like this
outputBuffer[coords] += floatValue; // TODO: fix!!
As expected, it works but without guarantees. Some pixels are flickering depending on which thread worked first.
So, how can I do it safely? either using a function like atomicAdd
or something similar to CUDA's sync threads/barriers?
We solved it by representing the floats in integer format, then using atomicAdd
on the int values like this
@group(0) @binding(0) var<storage> data: array<f32>;
@group(0) @binding(1) var<storage, read_write> result: array<atomic<u32>>;
fn toFixed(value: f32) -> u32 {
return u32(values * 1e2); // to save 2 digits after the decimal point
}
fn toFloat(value: u32) -> f32 {
return f32(values) * 1e-2;
}
main() {
// to store values
atomicAdd(&result[index], toFixed(data[index]));
// to use stored values
let value = toFloat(result[index]);
}
Here is a longer answer if u32
is not enough to store the values by implementing atomicAdd
for u64
using 2 buffers to store the values