Metal 2 Multi Indirect Draw

Viewed 372

Is there a way based on Metal 2 to do "Multi Indirect Draw" like "Direct X" 12 API "ExecuteIndirect"? Metal 2 has got some API to do single indirect draw, but multi indirect draw seems could not be found.

1 Answers

You can use MTLIndirectCommandBuffer to encode draw or dispatch commands either on CPU or on GPU.

You create an MTLIndirectCommandBuffer with an MTLIndirectCommandBufferDescriptor that has a max number of commands set, as well as types of commands and other properties, such as pipeline and buffer bindings inheritance. Keep in mind, that you can't mix and match commands of different "stages". Meaning, you can have two different types of render commands, but you can't have both render and compute commands in the same buffer.

After that, you have two ways to encode it.

First is doing it on CPU. You can request an MTLIndirectRenderCommand object from the ICB with an indirectRenderCommandAtIndex: call or a compute one, MTLIndirectComputeCommand with an indirectComputeCommandAtIndex: call. It's kinda like a command encoder, but for a single command.

Second way is doing it on a GPU. You can pass the indirect command buffer into a shader by using argument buffers. You would use an MTLArgumentEncoders setIndirectCommandBuffer:atIndex: method to write it there. After that, you can use an API similar to a CPU side API. You create a render_command or a compute_command from an index and command_buffer object that you have in your argument buffer in your shaders. This command struct has a bunch of methods to set buffers, pipeline states and encode draw or compute commands. You'd then dispatch a kernel with some threads that will use their position in grid to calculate an index into a command buffer and encode a command there.

Even though indirect commands look kinda like command encoders, it's good to keep in mind that a single command at an index only holds one actual command, so in a contrast from an encoder, any changes you make to the draw or compute command overwrite what was there previously.

After you have the commands encoded either on CPU or a GPU, you have to execute it. Depending on which types of command you have, you are going to call executeCommandsInBuffer:indirectBuffer:indirectBufferOffset: on either MTLRenderCommandEncoder or MTLComputeCommandEncoder.

That should cover the basics. For a more in-depth look, there are these two articles: Encoding Indirect Command Buffers on the CPU and Encoding Indirect Command Buffers on the GPU , as well as this Modern Rendering with Metal Sample that uses those ICBs quite heavily.

Related