Search code examples
pixel-shadercompute-shader

Is there a way to concurrently write to a UAV without race condition?


I have a compute shader which simulates some fluid as particle. Particles are read from a buffer. Each particle is handled in one thread. During the execution of the thread, one particle moves its uv position and adds to pixel of a UAV named Water . Therefore each thread leaves a trail of its movement on the Water texture.

_watTx[texID] += watAddition * cellArea.x;

The problem is there are lots of particles moving around and most often multiples are present at the same texID. It seems there is a race condition since every time I run the simulation the results are slightly different. Is there a way to enforce mutual exclusion so the writes do not happen at the same time and the results become predictable?


Solution

  • I found a way to resolve this issue. InterlockedAdd adds to the pixel in an atomic fashion. But it only works on int and unit UAVs.

    In my case the values are floating point but the range is quite limited (like 0 to 10). So the solution is to use an int UAV. We multiply the calculation result by a huge number (like 10000) and then write to the UAV:

    InterlockedAdd(_watTx[texID], (watAddition * cellArea.x * 10000));
    

    The results will have a 0.0001 precision which is perfectly fine in my case. After this in another pixel or compute shader we can multiply values from the int UAV by 0.0001 and write to the desired floating point render target.

    This process eliminates the concurrent write problem and the results are identical in each run.