Guides and Sample Code

Developer

Metal Best Practices Guide

Indirect Buffers

Best Practice: Use indirect buffers if your draw or dispatch call arguments are dynamically generated by the GPU.

Indirect buffers are MTLBuffer objects with a specific data layout representing draw or dispatch call arguments. The supported layouts are defined by the following structures:

Indirect buffers allow you to issue calls that depend on dynamic arguments that are unknown at the time of the call. These arguments can be dynamically generated after the call is issued, but they must always 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 to a post-tessellation vertex function.

Eliminate Unnecessary Data Transfers and Reduce Processor Idle Time

Without an indirect buffer, the GPU generates and writes the call arguments to a regular buffer. The CPU must wait until the GPU completes all of its work before it can read the arguments from the regular buffer and issue the call. The GPU must then wait until the CPU completes all of its work before it can execute the call. This inefficient sequence is shown in Figure 12-1.

Figure 12-1Issuing a call without an indirect buffer image: ../Art/CommandGeneration_RegularBuffer.pdf

With an indirect buffer, the CPU doesn’t need to wait for any values and can immediately issue a draw call that references an indirect buffer. After the CPU completes all of its work, the GPU can then generate the arguments, write them to the indirect buffer in one pass, and execute the call associated with them in another pass. This improved sequence is shown in Figure 12-2.

Figure 12-2Issuing a call with an indirect buffer image: ../Art/CommandGeneration_IndirectBuffer.pdf

An indirect buffer eliminates unnecessary data transfers between the CPU and the GPU, which results in reduced processor idle time. Use an indirect buffer if the CPU doesn’t need to access the dynamic arguments of a draw or dispatch call.