#InterlockedAdd() only applying to first command on indirect buffer

1 messages · Page 1 of 1 (latest)

fluid maple
#

Hello. I'm currently trying to do GPU-driven culling on 6000.3.0f1 (URP, D3D12), and I have some troubles with atomic operations. For context, the indirect buffer holds multiple commands, and one compute dispatch is done per command/draw to cull their instances. The supplied drawID is confirmed to change for each dispatch via Renderdoc shader debugging, and atomic operations using that indexing work on another (non-indirect) structured buffer just fine. For the indirect buffer, only the atomic operations targeting the first command seem to be applied, even with other buffer flag combinations like IndirectArguments|Structured (if it even makes sense). The buffer contents are verified with GraphicsBuffer.GetData() before and after the dispatches, as well as Renderdoc. I'm kinda running out of options, and neither Google or ChatGPT have helped on this one, so here I am. 🙃
Here's the related code:

//=====================
//Setup
//=====================
this.indirectBuffer = new(Target.IndirectArguments,assetCount,IndirectDrawIndexedArgs.size);
...
this.cullShader.SetBuffer(cullKernel,"indirectBuffer",this.indirectBuffer);
//=====================
//Per-frame
//=====================
//Reset data to a saved state before culling.
this.indirectBuffer.SetData(this.indirectData);
...
for(var index = 0;index < this.indirectData.Length;index += 1){
    this.cullShader.SetInt("drawID",index);
    this.cullShader.Dispatch(cullKernel,Mathf.CeilToInt((float)this.indirectData[index].instanceCount / threadsX),(int)threadsY,(int)threadsZ);
}
...
//=====================
//Compute Shader
//=====================
struct IndirectCommand{
    uint indexCountPerInstance;
    int instanceCount;
    uint startIndex;
    uint baseVertexIndex;
    uint startInstance;
};
RWStructuredBuffer<IndirectCommand> indirectBuffer;
...
InterlockedAdd(indirectBuffer[drawID].instanceCount,-1);```
fluid maple
#

Huh. Something changed somehow and the issue appeared in RenderDoc. It looks like indexing into a buffer of structures doesn't work the way I thought it would.

#

Here's the indirect buffer after each dispatch (first one already culls all the instances so the count is 0).

#

The index seems to be fetching the next field rather than the next structure (even with a stride explicitly set at 20 bytes on buffer creation...). This is cursed...

#

So the solution is to index by drawID * fieldCount, I guess...

#

Hopefully it's gonna be helpful to someone else. I'll mark this as solved. 🙃