Can a compute shader incrementally change a texture?

I’m trying to use a compute shader to modify a 3D render texture. I want to keep the existing contents, but additively paint into the texture in a specific location. However, while I could use a compute shader to fill everything with a constant colour, I couldn’t get it to do any modifications on top of existing state. I’ve been banging my head against this for a while and can’t find any useful documentation on the subject.

My compute shader:

#pragma kernel CSMain

Texture3D<float4> texIn;
RWTexture3D<float4> texOut;

float3 boundsDimensions;
float3 boundsCenter;

float3 paintCenter;
float paintRadius;
float paintMult;
float paintPower;
float4 paintColor;

[numthreads(8,8,8)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
    float3 texSize;
    texIn.GetDimensions(texSize.x, texSize.y, texSize.z);

    float3 unitsPerTexel = (boundsDimensions/texSize);
    float3 diff = (id.xyz*unitsPerTexel + boundsCenter - paintCenter);
    float dist = length(diff);

    float amount = saturate(1-dist/paintRadius);
    amount = pow(amount,paintPower) * paintMult;
     
    float4 finalPaint = saturate(texIn[id.xyz] + amount * paintColor);

    texOut[id.xyz] = finalPaint;
}

The calling code:

        ComputeShader paintShader = Resources.Load<ComputeShader>("ComputeShaders/PaintSphere");
      
        paintShader.SetTexture(0, "texIn", paintVolume.Volume);
        paintShader.SetTexture(0, "texOut", paintVolume.Volume);

        paintShader.SetVector("boundsDimensions", paintVolume.BoundsSize);
        paintShader.SetVector("boundsCenter", paintVolume.BoundsCenter);
        paintShader.SetVector("paintCenter", transform.InverseTransformPoint(worldPosition));
        paintShader.SetFloat("paintRadius", radius);
        paintShader.SetFloat("paintMult", mult);
        paintShader.SetFloat("paintPower", power);
        paintShader.SetVector("paintColor", color);

        paintShader.Dispatch(0, paintVolume.Volume.width / 8, paintVolume.Volume.height / 8, paintVolume.Volume.volumeDepth / 8);

…And, for good measure, the render texture creation:

            volume = new RenderTexture(volumeDimensions, volumeDimensions, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
            volume.isVolume = true;
            volume.volumeDepth = volumeDimensions;
            volume.enableRandomWrite = true;

As far as I can tell, the questionable bit is that I’m feeding the same texture into the shader as both an input and an output variable. However, I don’t know another way to approach this. Does anyone know what I’m doing wrong, or what I could do as an alternative approach?

I was able to work around this by using two render textures and swapping between them; a bit circuitous, but it seems to get the job done. Some strange issues when I try to do too many paint events at once, though. I haven’t been able to sort them out, but I suspect they have to do with execution order or possibly some sort of concurrency issue. It’d be much better if I could change the texture in-place with some sort of additive scheme…