Search code examples
objective-cswiftmetal

Using multiple render pipelines in a single MTLRenderCommandEncoder: How to Synchronize MTLBuffer?


Central Issue
I have two render pipelines in one single render command encoder. The first pipeline writes to a buffer which is used in the second pipeline. This does not seem to work and I expect it to be a synchronization problem. When I use one separate render command encoder for each render pipeline I get the desired result. Can this be solved with one single render command encoder or do I need two separate encoders to synchronize the buffer?

Here is the more specific case:
The first pipeline is a non-rasterizing pipeline only running a vertex shader to output to a MTLBuffer storing MTLDrawPrimitivesIndirectArguments to use for the drawPrimitives call for the second pipeline, which looks like this:

// renderCommandEncoder is MTLRenderCommandEncoder
// firstPipelineState and secondPipelineState are two different MTLRenderPipelineState
// indirectArgumentsBuffer is a MTLBuffer containing MTLDrawPrimitivesIndirectArguments
// numberOfVertices is number of vertices suited for first pipeline

// first pipeline
renderCommandEncoder.setRenderPipelineState(firstPipelineState)
renderCommandEncoder.setVertexBuffer(indirectArgumentsBuffer, offset: 0, index: 0)
renderCommandEncoder.drawPrimitives(type: .point, vertexStart: 0, vertexCount: numberOfVertices)

// second pipeline
renderCommandEncoder.setRenderPipelineState(secondPipelineState)
renderCommandEncoder.setVertexBuffer(secondPipelineBuffer, offset: 0, index: 0)
renderCommandEncoder.drawPrimitives(type: .point, indirectBuffer: indirectArgumentsBuffer, indirectBufferOffset: 0)

renderCommandEncoder.endEncoding()

How can I make sure that the indirectArgumentsBuffer has been written to by the first pipeline when issuing a call to drawPrimitives for the second pipeline, which uses and needs the contents of indirectArgumentsBuffer?


Solution

  • I believe you need to use separate encoders. In this (somewhat dated) documentation about function writes, only atomic operations are synchronized for buffers shared between draw calls.