About Argument Buffers

Improve your app’s performance by grouping your resources into an argument buffer.


An argument buffer is an opaque data representation of a group of resources that can be collectively assigned as graphics or compute function arguments. An argument buffer can contain multiple resources of various sizes and types, such as buffers, textures, samplers, and inlined constant data.

Specifying Argument Buffers in Metal Shading Language Functions

Argument buffers may contain the following:

  • Basic scalar data types, such as half and float.

  • Basic vector and matrix data types, such as half4 and float4x4.

  • Arrays and structures of basic data types.

  • Buffer pointers.

  • Texture data types and arrays of textures.

  • Sampler data types and arrays of samplers.

The following example shows an argument buffer structure named My_AB that specifies resources for a kernel function named my_kernel:

struct My_AB {
    texture2d<float, access::write> a;
    depth2d<float> b;
    sampler c;
    texture2d<float> d;
    device float4* e;
    texture2d<float> f;
    int g;
kernel void my_kernel(constant My_AB & my_AB [[buffer(0)]])
{ ... }

Encoding Resources into Argument Buffers

The Metal driver may perform certain optimizations that modify the physical memory layout of an argument buffer. The layout is unknown; you must use a MTLArgumentEncoder object to encode argument buffer resources into a destination MTLBuffer object. You can encode the following resources into argument buffers:

You can then set an encoded argument buffer as a graphics or compute function argument using any of the following MTLRenderCommandEncoder or MTLComputeCommandEncoder methods:

Benefits of Using Argument Buffers

Argument buffers can assign a group of resources all at once to a single index in the function argument table. The main benefit of using argument buffers is to reduce the overhead incurred by assigning the same multiple resources to individual indices of the same function argument table. This is particularly beneficial for resources that do not change from frame to frame, because they can be assigned to an argument buffer once and reused many times.

Encoding resources into argument buffers eliminates the need for the Metal driver to capture state and track residency when individual resources are assigned to the indices of a function’s argument table. Instead, argument buffers provide greater control over resource residency that you must explicitly declare before issuing draw or dispatch calls.

Using resource heaps is already a great way to reduce resource overhead. When you combine resource heaps with argument buffers, you can further reduce overhead by:

  • Encoding argument buffer resources before entering a draw or dispatch loop.

  • Allocating argument buffers from a resource heap, reducing the cost of tracking the residency of the argument buffer itself.

  • Managing argument buffer resources and resource heap residency outside of a draw or dispatch loop, further reducing the cost of tracking residency.

Finally, argument buffers allow resources to be indexed dynamically at function execution time by greatly increasing the limit on the number of resources that can be placed inside them.

Argument Buffer Tiers, Limits, and Capabilities

Argument buffer feature support is divided into two tiers: Tier 1 and Tier 2. You can query these tiers by accessing the argumentBuffersSupport property of a MTLDevice object.

Common Limits

For both tiers, the maximum number of argument buffer entries in each function argument table is 8.

For both tiers, the maximum number of unique samplers per app are 96 for iOS and tvOS, and at least 1024 for macOS; these limits are only applicable to samplers that have their supportArgumentBuffers property set to YES. Query the maxArgumentBufferSamplerCount to determine the exact maximum number of unique samplers per app for a given device.

A MTLSamplerState object is considered unique if the configuration of its originating MTLSamplerDescriptor properties is unique. For example, two samplers with equal minFilter values but different magFilter values are considered unique.

Tier 1 Limits

The following resource limits are defined as the maximum combined number of resources set within an argument buffer and set individually, per graphics or compute function. For example, if a kernel function uses 4 individual textures and one argument buffer with 8 textures, the total number of textures for that kernel function is 12.

In iOS and tvOS, the maximum entries in each function argument table are:

  • 31 buffers (on A11 and later, 96 buffers)

  • 31 textures* (on A11 and later, 96 textures)

  • 16 samplers

*Writable textures are not supported within an argument buffer.

In macOS, the maximum entries in each function argument table are:

  • 64 buffers

  • 128 textures

  • 16 samplers

Tier 2 Limits

Tier 2 argument buffers are supported by macOS devices with a discrete GPU and by the A13 GPU. The maximum per-app resources available at any given time are:

  • 500,000 buffers or textures

  • 2048 unique samplers

Resource Access

Tier 1 argument buffers must be immutable; the GPU cannot modify the contents of an argument buffer. Tier 1 argument buffers must also be CPU-accessible (the buffer must specify either a MTLStorageModeShared or MTLStorageModeManaged storage mode).

Tier 2 argument buffers can be mutable; the GPU and CPU can both modify the contents of an argument buffer at any time. However, the Metal driver may perform certain optimizations if you specify that neither the CPU nor the GPU will modify a buffer's contents between the time the buffer is set in a function's argument table and the time its associated command buffer completes execution. These types of argument buffers are considered immutable, and you can define them by setting the mutability property of an associated MTLPipelineBufferDescriptor object to MTLMutabilityImmutable.

Metal Shading Language Capabilities

Tier 1 argument buffers cannot be accessed through pointer indexing, nor can they include pointers to other argument buffers.

Tier 2 argument buffers can be accessed through pointer indexing, as shown in the following example:

kernel void my_kernel(constant My_AB_Resources *resourcesArray [[buffer(0)]]) {
    constant My_AB_Resources & resources = resourcesArray[3];

Tier 2 argument buffers can also access other argument buffers by including pointers to them, as shown in the following example:

struct My_AB_Textures {
    texture2d<float> diffuse;
    texture2d<float> specular;
struct My_AB_Material {
    device My_AB_Textures *textures;
fragment float4 my_fragment(device My_AB_Material & material)

Samplers cannot be copied from the thread address space to the device address space; therefore, argument buffer samplers can be copied only between argument buffers:

struct My_AB_Sampler {
    sampler sam0;
kernel void my_kernel(device My_AB_Sampler *source, device My_AB_Sampler *destination, sampler sam1) {
    constexpr sampler sam2;
    // device-to-device copy is allowed
    destination->sam0 = source->sam0;
    // thread-to-device copies are not allowed
    destination->sam0 = sam1;
    destination->sam0 = sam2;

See Also

Argument Buffers

Managing Groups of Resources with Argument Buffers

Create argument buffers to organize related resources.

Using Argument Buffers with Resource Heaps

Reduce CPU overhead by using arrays inside argument buffers and combining them with resource heaps.

Encoding Argument Buffers on the GPU

Use a compute pass to encode an argument buffer and access its arguments in a subsequent render pass.

Rendering Terrain Dynamically with Argument Buffers

Use argument buffers to render terrain in real time with a GPU-driven pipeline.

Indexing Argument Buffers

Assign resource indices within an argument buffer.

Tracking the Resource Residency of Argument Buffers

Optimize resource performance within an argument buffer.


A representation of an argument within an argument buffer.


An object used to encode data into an argument buffer.