Compute Buffer - passing data between shaders

I have data that needs to be shared between two compute shaders. I’d like to copy the data on the GPU rather than having to first move it to the CPU before transferring it back to the GPU.

The data is not used for rendering but the whole operation must run synchronously. How can data (RWStructuredBuffer) be transferred between shaders on the GPU.

// Simplified code example
float[] data1D = new float[dataSize];
cbuf1 = new ComputeBuffer(dataSize, sizeof(float), ComputeBufferType.Default);

// Assign buffer to shader1
kShader1MethodIdx = shader1.FindKernel(CSKShader1Method);
shader1.SetBuffer(kShader1MethodIdx, CSData1D, cbuf1);
// Execute shader 1
shader1.Dispatch(kShader1MethodIdx, threadGroupX + 1, threadGroupY + 1, 1);

// Copy data from GPU back to CPU (want to avoid this...)
cbuf1.GetData(data1D);

kShader2MethodIdx = shader2.FindKernel(CSKShader2Method);
// Assign buffer to shader2
shader2.SetBuffer(kShader2MethodIdx, CSData1D, cbuf1);

// Copy data from CPU back to GPU (want to avoid this...)
cbuf1.SetData(data1D);

// Execute shader 2
shader2.Dispatch(kShader2MethodIdx, threadGroupX + 1, threadGroupY + 1, 1);

Previously I’d tried to just assign the buffer to the send shader but the data did not seem to be available to the second shader without using the method described above.

My previous attempt at directly assigning the buffer to another shader has some bugs. So, the above is not necessary, you can simply assign the buffer to the second shaded.

1 Like

What was the bug you had when assigning the buffer to another shader? I’m experiencing the same issue where the second dispatched shader does not get the data of the first. I’m calling dispatch on the first one before setbuffer on the second, but still no dice. The value I get from accessing the output of the first buffer in the second shader is always 0.

Did you call GetData() after the first shader to confirm that you are actually getting the data you expect from the first shader?

I did, and I managed to get the data of the first shader in c#, but not in my other shader. I’ve tried moving the other shader into a kernel on the same shader, and rearranging the calls so dispatch on the second call is only called after setting the shared buffer, but still nothing which is really strange.

The data is definitely getting generated, as the first shader creates a texture and the second runs meshing algorithms using that texture. When I try and run the entire method, I can still see the first shader’s texture output even though the second just gives me a buffer with all default values where I reference the first’s buffer.

Edit: Looking into it, my second kernel doesn’t seem to be able to access other structuredbuffer data that is just set in C# and isn’t being written by a shader.

Once the buffer is set (uploaded to the GPU), you should be able to access it without sending to the CPU again. I was trying to find an example in my code (its been a while…) but maybe I just dispatch another kernal (method) in the same shader. Maybe that’s how I got round this issue.

Well a good night’s sleep seem to resolve everything, turns out for my second fix with moving over the stuff to one file and reordering the dispatches, I mistyped the method name in the ComputeShader.FindIndex method. It seems like in order to have access to buffer data in a subsequent buffer, the dispatch call for both shaders can only happen after the buffer is set onto each Kernel that will be using it. Not exactly sure if different compute shader files change this, but that is the solution I went with. Thanks for the advice sstrong!

1 Like