- iOS 11.0+
- tvOS 11.0+
- macOS 10.13+
- Xcode 11.0+
An argument buffer represents a group of resources that can be collectively assigned as an argument to a graphics or compute function. You use argument buffers to reduce CPU overhead, simplify resource management, and implement GPU-driven pipelines.
In this sample, you’ll learn how to specify, encode, set, and access resources in an argument buffer. In particular, you’ll learn about the advantages of managing groups of resources in an argument buffer instead of individual resources. The sample renders a static quad using a texture, sampler, buffer, and constant encoded into an argument buffer.
The Xcode project contains schemes for running the sample on macOS, iOS, or tvOS. The default scheme is macOS, which runs the sample as is on your Mac.
CPU Overhead and Argument Buffers
Metal commands are efficient, incurring minimal CPU overhead when apps access the GPU. Each command does incur some overhead, however; to further reduce the amount, use these strategies:
Do more GPU work with fewer CPU commands.
Avoid repeating expensive CPU commands.
Metal’s argument buffer feature reduces the number and performance cost of CPU commands in your app’s critical path (for example, in your app’s render loop). An argument buffer allows you to group and encode multiple resources within a single buffer, instead of encoding each resource individually. By using argument buffers, you can shift a significant amount of CPU overhead from your app’s critical path to its initial setup.
Individual Resources versus Argument Buffers
Metal apps, particularly games, typically contain multiple 3D objects, each associated with a set of resources such as textures, samplers, buffers, and constants. To render each object, apps encode Metal commands that set these resources as arguments to a graphics function before issuing a draw call.
You set individual resources as arguments by calling
MTLRender methods such as
set for each resource.
Commands that set individual resources can become numerous and expensive, especially for large apps or games. Instead, you can group related resources into an argument buffer and then set that entire buffer as a single argument to a graphics function. This approach greatly reduces CPU overhead and still provides individual GPU access to your resources.
Argument buffers are represented as
MTLBuffer objects. Therefore, you set them as arguments by calling
MTLRender methods such as
set for each argument buffer.
Define Argument Buffers
Argument buffers are defined as custom structures in the Metal Shading Language. Each structure element represents an individual resource, declared as a texture, sampler, buffer, or constant data type. A structure element is also associated with an integer, declared with the
[[id(n)]] attribute qualifier, that specifies the index of the individual resource.
The argument buffer in this sample is declared as a
Fragment structure and this is its definition:
This argument buffer contains the following resources:
example, a 2D texture with an index of
example, a sampler with an index of
floatbuffer with an index of
uint32constant with an index of
This sample’s fragment function,
fragment, uses the argument buffer as a single parameter.
fragment parameter is a buffer of type
Fragment. When the sample sets a
MTLBuffer as an argument to the fragment function, the function interprets the data in the
fragment parameter as an argument buffer with a texture, sampler, buffer, and constant (as defined by the
Encode Resources into an Argument Buffer
Individual resources must be encoded into an argument buffer before the buffer is accessed by a function. This is accomplished by creating a
MTLArgument from a
MTLFunction that uses an argument buffer.
This sample creates a
MTLArgument from the
fragment function, which contains the
encoded property of
argument determines the size, in bytes, required to contain all the resources in the argument buffer. This sample uses that value to create a new buffer,
_fragment, with a
length parameter that matches the required size for the argument buffer.
This sample then calls the
set method to specify that
_fragment is an argument buffer that resources can be encoded into.
This sample encodes individual resources into the argument buffer by:
Calling specific methods for each resource type, such as
Texture: at Index:
Sampler State: at Index:
Buffer: offset: at Index
Matching the value of the
indexparameter to the value of the
[[id(n)]]attribute qualifier declared for each element of the
Constants are encoded a bit differently; constant data is embedded directly into the argument buffer, instead of residing in another object that the argument buffer points to. This sample calls the
constant method to retrieve the address in the argument buffer in which the constant resides. Then, the sample sets the actual value of the constant,
buffer, at the retrieved address.
Enable the GPU Memory of Resources in the Argument Buffer
Metal efficiently manages memory accessed by the GPU; before the GPU uses any resource, Metal ensures that the GPU has access to the resource’s memory. Setting resources individually, by calling
MTLRender methods such as
set, ensures that the resource’s memory is accessible to the GPU.
However, when resources are encoded into an argument buffer, setting the argument buffer doesn’t set each of its resources individually. Metal doesn’t inspect argument buffers to determine which resources are encoded in them (this expensive operation would negate the performance benefits of argument buffers). Therefore, Metal can’t determine what resource’s memory to make accessible to the GPU. Instead, you call the
use method to explicitly instruct a
MTLRender to make a specific resource’s memory accessible to the GPU.
Set Argument Buffers
This sample calls the
use method for the
_indirect resources encoded into the argument buffer. These calls specify
MTLResource values that further indicate which GPU operations are performed on each resource (the texture is sampled and the buffer is read in the GPU).
This sample sets only
_fragment as an argument to the fragment function; it doesn’t set the
buffer resources individually. This command allows the fragment function to access the argument buffer and its encoded resources.
Access the Resources in an Argument Buffer
Within a function, accessing resources encoded in an argument buffer is similar to accessing individual resources directly. The main difference is that the resources are accessed as elements of the argument buffer structure.
In this sample, argument buffer resources are accessed via the
fragment parameter of the
The sample uses all four resources in the argument buffer to produce the final color for each fragment.
In this sample, you learned how to specify, encode, set, and access resources in an argument buffer. In the Argument Buffers with Arrays and Resource Heaps sample, you’ll learn how to combine argument buffers with arrays of resources and resource heaps.