Discover how Metal executes commands on a GPU.
To get the GPU to perform work on your behalf, you send commands to it. A command performs the drawing, parallel computation, or resource management work your app requires. The relationship between Metal apps and a GPU is that of a client-server pattern:
Your Metal app is the client.
The GPU is the server.
You make requests by sending commands to the GPU.
After processing the commands, the GPU can notify your app when it's ready for more work.
To send commands to a GPU, you add them to a command buffer using a command encoder object. You add the command buffer to a command queue and then commit the command buffer when you're ready for Metal to execute the command buffer's commands. The order that you place commands in command buffers, enqueue and commit command buffers, is important because it effects the perceived order in which Metal promises to execute your commands.
The following sections cover the steps to set up a working command structure, ordered in the way you create objects to interact with Metal.
Make Initialization-Time Objects
You create some Metal objects at initialization and normally keep them around indefinitely. Those are the command queue, and pipeline objects. You create them once because they're expensive to set up, but once initialized, they're fast to reuse.
Make a Command Queue
To make a command queue, call the device's
Because you typically reuse the command queue, make a strong reference to it. You use the command queue to hold command buffers, as seen here:
Make One or More Pipeline Objects
A pipeline object tells Metal how to process your commands. The pipeline object encapsulates functions that you write in the Metal shading language. Here's how pipelines fit into your Metal workflow:
You write Metal shader functions that process your data.
Create a pipeline object that contains your shaders.
When you're ready to use it, enable the pipeline.
Make draw, compute, or blit calls.
Metal doesn't perform your draw, compute, or blit calls immediately; instead, you use an encoder object to insert commands that encapsulate those calls into your command buffer. After you commit the command buffer, Metal sends it to the GPU and uses the active pipeline object to process its commands.
Issue Commands to the GPU
With your command queue and pipeline(s) set up, it's time for you to issue commands to the GPU. Here's the process you follow:
Create a command buffer.
Fill the buffer with commands.
Commit the command buffer to the GPU.
If you're performing animation as part of a rendering loop, you do this for every frame of the animation. You also follow this process to execute one-off image processing, or machine learning tasks.
The following subsections walk you through these steps in detail.
Create a Command Buffer
Create a command buffer by calling
command on the command queue:
For single-threaded apps, you create a single command buffer. Figure 4 shows the relationship between commands and their command buffer:
Add Commands to the Command Buffer
When you call task-specific functions on an encoder object–like draws, compute or blit operations–the encoder places commands corresponding to those calls in the command buffer. The encoder encodes the commands to include everything the GPU needs to process the task at runtime. Figure 5 shows the workflow:
You encode actual commands with concrete subclasses of
MTLCommand, depending on your task:
MTLRenderto issue render commands.
MTLComputeto issue parallel computation commands.
MTLBlitto issue resource management commands.
Commit a Command Buffer
To enable your commands to run, you commit the command buffer to the GPU:
Committing a command buffer doesn't run its commands immediately. Instead, Metal schedules the buffer's commands to run only after you commit prior command buffers that are waiting in the queue. If you haven't explicitly enqueued a command buffer, Metal does that for you once you commit the buffer.
You don't reuse a buffer after it's committed, but you can opt into notification of its scheduling, completion, or query its
The promise upheld by Metal is that the perceived order in which commands are executed is the same as the way you ordered them. While Metal might reorder some of your commands before processing them, this normally only occurs when there's a performance gain and no other perceivable impact.