Reputation: 2590
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?
Upvotes: 4
Views: 1060
Reputation: 31782
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
Upvotes: 7