I have an application that uses two compute shaders. Shader #1
produces data x
and stores it in A
, bound as an Append Buffer. Shader #2
runs on all of x
from A
, bound as a consume buffer.
I would like to extend this by adding Shader #3
, which runs on all of x
in A
, producing y
into a new buffer B
- but I still want Shader #2
to run on x
as before.
That is, I want to run an operation on all elements of an append/consume buffer, but without 'consuming' them.
If I understand correctly, consuming an element just decreases a hidden counter, so I should be able to consume a buffer many times by storing the count when full, and resetting it between the shader invocations that consume from it.
The problem is that my platform - Unity - has only one method for this (SetCounterValue()
) which requires me to pass in the new counter value. That is, I need to get the counter value to CPU memory before re-setting it, which will force a synchronisation between the GPU/CPU and reduce performance.
Is it possible to set the counter value of a consume buffer entirely on the GPU?
If not, is it possible to iterate over a consume buffer without using consume?
(It has occured to me to just bind the buffer as a regular UAV resource and iterate that way, but the documentation is ambiguous as to whether this is supported. E.g. does "these resources do not use resource variables." refer to the resource itself, or the view?)
The normal way to do this (from what I understand, and I'm definitely no DirectCompute expert!) is to have two buffers - your data buffer, created in Unity as
ComputeBufferType.Default
buffer and declared in your shader asRWStrucutedBuffer<YourStruct>
, and your index buffer, created in Unity asComputeBufferType.Append
and declared in your shader asConsumeStrucutredBuffer<uint>
orAppendStructuredBuffer<uint>
.The index buffer is a list of index references into your main buffer, and specifies which elements are inactive.
You'd also add an int to your data struct called 'isAlive' or something.
Then you'd create three shaders:
if(isAlive < 1) return
before you do the bulk of your work.indexBuffer[932] = 932
etc. (index list is initialised asAppendStructuredBuffer<uint>
)isAlive = true
. (index list is initialised asConsumeStrucutredBuffer<uint>
.You could also, in your simulation shader, declare your index buffer as an Append buffer and, if certain conditions are met, 'kill' your simulation index by setting isAlive = false and appending its index to the index buffer.