Demonstrates how to encode an argument buffer with a compute pass and then access its arguments in a subsequent render pass.
- macOS 10.13+
- Xcode 11.0+
In the Argument Buffers with Arrays and Resource Heaps sample, 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.
The sample can run only on macOS 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 About 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
This argument buffer is backed by the
_source buffer and is accessed via the
source variable in the
source contains an array of references to textures loaded by the sample’s renderer.
After initialization, for each frame, the sample encodes data with the GPU into a separate argument buffer defined by the
This argument buffer is backed by the
_instance buffer and is accessed via the
instance variable in the
instance 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.
Create an Array of Argument Buffer Structures
The sample defines an
Instance structure into which a compute function,
update, encodes a vector and two textures.
Previous argument buffer samples used the
encoded 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
encoded by the total number of instances, which is defined by the value of the
Encode an Argument Buffer with a Compute Function
For each quad to be rendered, the sample executes the
update compute function to determine the quad’s position and textures. The compute pass executed by the sample iterates through the
instance array and encodes the correct data for each quad. The sample encodes data into
instance by setting
Instance values in the array element at the
instance 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
instance variable in both the vertex and fragment function’s signatures. The render pipeline uses
instance to index into the
instance array that was previously encoded by the
update compute function.
In the vertex function,
instance is defined as an argument with the
[[instance 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
instance variable to the fragment function, via the
Rasterizer structure and the
[[stage attribute qualifier. (In the fragment function,
instance is accessed via the
The fragment function samples from the two textures specified in the argument buffer and then chooses an output sample based on the value of
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.
In this sample, you learned how to encode resources into argument buffers with a graphics or compute function. In the Dynamic Terrain with Argument Buffers sample, you’ll learn how to combine several argument buffer techniques to render a dynamic terrain in real time.