Contents

Encoding argument buffers on the GPU

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

Overview

In Using argument buffers with resource heaps, you learned how to combine argument buffers with arrays of resources and resource heaps.

In this sample, you’ll learn how to encode resources into argument buffers with a graphics or compute function. In particular, you’ll learn how to write data into an argument buffer from a compute pass and then read that data in a render pass. The sample renders a grid of multiple quad instances with two textures applied to each, where the textures slide from left to right within the quad and move from left to right between quads.

Getting started

The sample can run only on devices that support Tier 2 argument buffers. Tier 2 devices allow graphics or compute functions to encode data into an argument buffer, whereas Tier 1 devices only allow these functions to read data from an argument buffer. Additionally, Tier 2 devices can access more textures in an instanced draw call than Tier 1 devices. See Improving CPU performance by using argument buffers for more information about argument buffer tiers, limits, and capabilities.

This sample checks for Tier 2 argument buffer support when the renderer is initialized.

Encode data into argument buffers

During initialization, the sample encodes data with the CPU into an argument buffer defined by the SourceTextureArguments structure.

This argument buffer is backed by the _sourceTextures buffer and is accessed via the source_textures variable in the updateInstances function. source_textures is a pointer to an unbounded array of structures, each of which contains a reference to a texture.

[Image]

After initialization, for each frame, the sample encodes data with the GPU into a separate argument buffer defined by the InstanceArguments structure.

This argument buffer is backed by the _instanceParameters buffer and is accessed via the instance_params variable in the updateInstances, vertexShader, and fragmentShader functions. instance_params is an array of structures whose data is populated in a compute pass and then accessed in a render pass via an instanced draw call.

[Image]

Create an array of argument buffer structures

The sample defines an InstanceArguments structure into which a compute function, updateInstances, encodes a vector and two textures.

Previous argument buffer samples used the encodedLength property to directly determine the required size for the MTLBuffer that backs an argument buffer structure. However, this sample needs one instance of this structure for each quad rendered by a subsequent render pass. Therefore, the sample multiplies the value of encodedLength by the total number of instances, which is defined by the value of the AAPLNumInstances constant.

Encode an argument buffer with a compute function

For each quad to be rendered, the sample executes the updateInstances compute function to determine the quad’s position and textures. The compute pass executed by the sample iterates through the instance_params array and encodes the correct data for each quad. The sample encodes data into instance_params by setting InstanceArguments values in the array element at the instanceID index value.

Render instances with an argument buffer

The sample issues an instanced draw call to render all the quads while incurring a minimal amount of CPU overhead. Combining this technique with an argument buffer allows the sample to use a unique set of resources for each quad within the same draw call, where each instance draws a single quad.

The sample declares an instanceID variable in both the vertex and fragment function’s signatures. The render pipeline uses instanceID to index into the instance_params array that was previously encoded by the updateInstances compute function.

In the vertex function, instanceID is defined as an argument with the [[instance_id]] attribute qualifier.

The vertex function reads position data from the argument buffer to render the quad in the right place in the drawable.

The vertex function then passes the instanceID variable to the fragment function, via the RasterizerData structure and the [[stage_in]] attribute qualifier. (In the fragment function, instanceID is accessed via the in argument.)

The fragment function samples from the two textures specified in the argument buffer and then chooses an output sample based on the value of slideFactor.

The fragment function outputs the selected sample. The left texture slides in from the left and the right texture slides out to the right. After the right texture has completely slid off the quad, the sample assigns this texture as the left texture in the next compute pass. Thus, each texture moves from left to right across the grid of quads.

Next steps

In this sample, you learned how to encode resources into argument buffers with a graphics or compute function. In Rendering terrain dynamically with argument buffers, you’ll learn how to combine several argument buffer techniques to render a dynamic terrain in real time.

See Also

Argument buffers