Article

Specifying Drawing and Dispatch Arguments Indirectly

Use indirect commands if you don't know your draw or dispatch call arguments when you encode the command.

Overview

An indirect command obtains its arguments from data stored in a MTLBuffer object, with a specific data layout for each kind of drawing or dispatch command. The supported layouts are defined by the following structures:

The arguments can be dynamically generated after the indirect command is encoded, but they must be available by the time their associated render or compute pass begins execution. Dynamic arguments are typically generated by the GPU; for example, a patch kernel can dynamically generate the arguments for a patch draw call.

Eliminate Unnecessary Data Transfers and Reduce Processor Idle Time

If you are using the GPU to calculate arguments for a future drawing or dispatch command, use an indirect command to encode the second call, and avoid accessing the arguments from the CPU for other reasons. Following this practice eliminates unnecessary transfers between the GPU and CPU and stalls between the CPU and GPU.

If you create this workflow using a direct call, the timeline looks something like the figure below. First, the CPU encodes a command buffer with a compute operation to calculate the arguments. After commiting this command buffer, the CPU must wait until the GPU completes the command. Then, the CPU reads the results, creates a new command buffer, encodes a second command using the calculated arguments, and commits it. You pay a performance penalty because the processor stalls in the middle of this workflow, and additional time is spent reading back the results.

Flow diagram showing the idle time caused by reading the data back on the CPU.

With indirect commands, the CPU can encode both commands in a single command buffer. After the CPU commits the command buffer, the GPU executes both passes, generating the arguments in the first pass, and executing the indirect call in the other. If your app needs to process this workflow repeatedly, it is easier for you to process work on one iteration on the GPU while you encode commands for the next iteration.

Flow diagram showing two commands encoded on the CPU followed by two commands executing on the GPU, with no idle time.

See Also

Drawing Geometric Primitives and Tessellated Patches Indirectly

- drawPrimitives:indirectBuffer:indirectBufferOffset:

Encodes a command to render a number of instances of primitives using vertex data in contiguous array elements, starting from a base instance.

Required.

- drawIndexedPrimitives:indexType:indexBuffer:indexBufferOffset:indirectBuffer:indirectBufferOffset:

Encodes a command to render a number of instances of primitives using index data in contiguous array elements, starting from the base vertex of a base instance.

Required.

- drawPatches:patchIndexBuffer:patchIndexBufferOffset:indirectBuffer:indirectBufferOffset:

Encodes a command to render a number of instances of tessellated patches, using an indirect buffer.

Required.

- drawIndexedPatches:patchIndexBuffer:patchIndexBufferOffset:controlPointIndexBuffer:controlPointIndexBufferOffset:indirectBuffer:indirectBufferOffset:

Encodes a command to render a number of instances of tessellated patches, using a control point index buffer and an indirect buffer.

Required.

MTLDrawIndexedPrimitivesIndirectArguments

The data layout required for drawing indexed primitives via indirect buffer calls.

MTLDrawPrimitivesIndirectArguments

The data layout required for drawing primitives via indirect buffer calls.

MTLDrawPatchIndirectArguments

The data layout required for drawing patches via indirect buffer calls.