javascriptcompute-shaderwebgpu

Equivalent to float AtomicAdd in WebGPU


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?


Solution

  • 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