gloo gloo - 17 days ago 4
Swift Question

What is the proper method to use the results of one compute shader in the next compute shader

Suppose I dispatch two compute shaders A and B in metal. I don't want B to run until after A has completed. At the moment I am encoding each shader in their own command buffer and committing like so:

commandBufferA.commit()
commandBufferA.waitUntilCompleted()
commandBufferB.commit()


Is this the proper technique?

Answer

Calling waitUntilCompleted() on a command buffer is useful if you need to use the results of a kernel back on the CPU, but is unnecessary and inefficient if your intent is simply to use the result of a compute command (dispatch) in a subsequent compute command. If there is a data dependency between compute commands, the results written by the former are guaranteed to be visible to the latter, even within a single command buffer. So, you could structure it something like this:

let commandBuffer = commandQueue.makeCommandBuffer()
let commandEncoder = commandBuffer.makeComputeCommandEncoder()

commandEncoder.setComputePipelineState(pipelineStateA)
commandEncoder.setTexture(inputTexture, at: 0)
commandEncoder.setTexture(intermediateTexture, at: 1)
commandEncoder.dispatchThreadgroups(threadgroupCount, 
                                    threadsPerThreadgroup: threadgroupSize)

commandEncoder.setComputePipelineState(pipelineStateB)
commandEncoder.setTexture(intermediateTexture, at: 0)
commandEncoder.setTexture(outputTexture, at: 1)
commandEncoder.dispatchThreadgroups(threadgroupCount, 
                                    threadsPerThreadgroup: threadgroupSize)

commandEncoder.endEncoding()
commandBuffer.commit()

commandBuffer.waitUntilCompleted() // optional; only if you need to read the result on the CPU
Comments