- RWByteAddressBuffer instead of RWStructuredBuffer
- Different creation flags for ComputeBuffer (though since its Unity the options are limited and opaque)
- Using a RenderTexture instead of a ComputeBuffer
- Using the globallycoherent prefix
- Clearing the buffer in the pixel shader then syncing with a DeviceMemoryBarrier() call
- Clearing the buffer in the pixel shader every other frame with a CPU set flag
- Using a different atomic (InterlockedMax())
- Using a different slot and/or binding calls
float4 frag (v2f i) : SV_Target
{
// sample the texture
float4 col = i.colour;
float c_norm = clamp(col.x, 0, 1); //one triangle is <=0 and the other is >=1
uint d_uint = (uint)c_norm;
uint d_uint_original = 0;
uint2 upos = i.screenpos * screenparams;
uint offset = (upos.y * screenparams.x) + upos.x;
InterlockedMin(depth[offset], d_uint, d_uint_original);
if (d_uint > d_uint_original)
{
clip(-1); //we havent updated the depth buffer (or at least shouldnt have) so don't write the pixel
}
return col;
}
With the declaration of the buffer being:
RWStructuredBuffer<uint> depth : register (u1);
And here is how the buffer is being bound and used:
// Use this for initialization
void Start () {
int length = Camera.main.pixelWidth * Camera.main.pixelHeight;
depthbufferdata = new uint[length];
for(int i = 0; i < length; i++)
{
depthbufferdata[i] = 0xFFFFFFFF;
}
depthbuffer = new ComputeBuffer(length, sizeof(uint));
}
// Update is called once per frame
void OnRenderObject () {
depthbuffer.SetData(depthbufferdata); // clears the mask. in my actual project this is done with a compute shader.
Graphics.SetRandomWriteTarget(1, depthbuffer);
material.SetVector("screenparams", Camera.main.pixelRect.size);
material.SetPass(0);
Graphics.DrawMeshNow(mesh, transform.localToWorldMatrix);
}