0
votes

I'm coming across deploying a Metal render loop as a chain of multiple KCS (kernel/compute) shaders and VFS (vertex/fragment) shaders:

texture -> [KCS -> VFS -> KCS -> VFS] --\
                                         --->[KCS -> KCS] --> presentable
texture -> [KCS -> VFS -> KCS -> VFS] --/

The output of one shader is the input to the next. The two sets of 4 alternating shaders are combined near the end, as shown.

If I'm thinking this through rightly, I'll need up to 10 disparate pipeline descriptors in order to make this happen, along with a lot of calls to completion handlers in which the next shader will be dispatched.

I also haven't indicated it, but the last call to presentable will also feed subregion of its output fed into a separate MTKView (via a vertex/fragment shader).

Any hints would be appreciated.

1

1 Answers

2
votes

You only need different descriptors if they would have different values. That is, if any of the KCS steps you show use the same compute shader function, then they typically can share a descriptor. (There are other properties of MTLComputePipelineDescriptor, but they're less commonly used.)

For the VFS steps, the descriptor is more complex and so they'd have to be equal across all properties to be shared.

Of course, you should be creating your pipeline state objects once in the lifetime of your app, if you can. Avoid creating them for every render loop.

You definitely don't want to use completion handlers to dispatch the next step. That will stall the pipeline horribly (make the CPU and GPU wait for each other, repeatedly). Just encode the steps in order into a command buffer. Any given draw or dispatch won't proceed until any previous draw/dispatch that might write to its inputs has completed.