Article

Optimizing Performance with the Shader Profiler

View the elapsed execution time of individual statements in your shader to understand where it spends the most time.

Overview

Using the Shader Profiler, you can prioritize your optimization efforts by reducing the time taken by your longest running shader statements. The shader profiler helps you optimize your shader by showing you how long each statement took to complete. On devices with a Family 4 or later GPU, a pie chart details which GPU activity your shader does most which provides additional hints about improving performance. With the Update Shaders feature, you can change your shader source live and quickly see how well your shader performs after the change.

Open the Shader Profiler

To use the shader profiler on your project, the .metallib file must contain source file information that allows for debugging. To properly set up the .metallib file:

  1. In Xcode, navigate to your project's build settings.

  2. Set the Produce debugging information setting for Debug to "Yes, include source code".

Use the shader profiler within a captured Metal frame. Most commonly, you capture a Metal frame by clicking the camera button on Xcode's debug bar as covered in Performing a GPU Capture from the Debug Bar.

From the captured frame, open the shader profiler using the steps in Figure 1:

  1. In the Debug navigator, choose View Frame By Performance.

  2. View your render pipelines populated in the list.

  3. Observe the amount of time each one took during the frame.

Figure 1

Viewing a frame by performance.

Screenshot showing Xcode's Debug navigator. On the top right, the "View frame in different ways" selection menu is annotated. On the left, the frame's render pipelines are listed, and on the right, their elapsed time in the frame.

Profile a Shader

Profile a shader using the follwoing steps, and as annotated in Figure 2:

  1. Expand the render pipeline.

  2. Select the shader you want to profile.

  3. View the shader source in the center pane with the function entry point highlighted.

  4. Examine the times and percentages column.

Figure 2

Profiling a shader.

On the left, a fragment shader is selected in the call list and its entry point signature is highlighted in the source code view displayed in the center pane. On the right, the times and percentages are displayed which indicate the performance of the fragment function and its statements.

Because profiling is for performance tuning, most often you'll inspect the render pipeline and shader that took the longest to complete.

In the times and percentages column, the time marking the function entry point is the shader's total elapsed time. Inside of the shader function, a percentage marks each statement and indicates what time (as a percent) of the elapsed time that statement took.

Interpret the GPU Activity Metrics

Next to the percentage of time taken, a pie chart details which activity the GPU is doing most during the statement.

Place your mouse pointer over the dot to bring up the pie chart, as shown in Figure 3:

Figure 3

GPU activity pie chart.

Screenshot showing the pie chart popup after hovering over the dot to the right of a percentage in the times column.

A high percentage in one GPU activity can indicate a performance bottleneck, and an opportunity for optimization. See the following recommendations based on state:

Table 1

Explanations for GPU activity.

GPU Activity

Explanation

ALU

Time spent in the GPU's arithmatic logic unit. Changing floats to half floats where you can afford it can offer one way to reduce time spent in the ALU.

Memory

Time spent waiting on the access of texture memory. You can relieve time spent in Memory by down-sampling textures. Alternatively, if you're not spending much time in Memory, you could have the opportunity to improve the detail of your textures.

Control Flow

Time spent in control structures, for example, a loop in your shader.

Synchronization

Time spent waiting on a required resource before execution could begin.

Update Shaders Live

After making a change to a shader you can apply those updates live using the Update Shaders button highlighted in Figure 4:

Figure 4

Using the Update Shaders feature.

Screenshot annotating the Update Shaders button. It's in the bottom-middle of the shader source in the center pane.

The Update Shaders button applies the source changes you make to the same captured Metal frame. The updates reflect as follows:

  • The application window is redrawn.

  • Elapsed time and percentage metrics are recalculated.

  • Attachments in the Assistant Editor are redrawn.

Because Updating Shaders maintains your view in the captured Metal frame, you can easily make successive changes to your shader source for iterative optimization.

See Also

Profiling and Metrics

GPU Activity Monitors

Use Xcode or macOS tools to view a high-level summary of the GPU activity of your app or a Mac.

Viewing Performance Metrics with GPU Counters

Ensure that properties related to an encoder's rendering are within the desired range.

Viewing Pipeline Statistics of a Draw

See relative percentages of where a given draw call spent its time across the GPU architecture.