<Prev | Content | Next>

02. Basic Diagnostics

When you develop complex software, you inevitably run into bugs and performance issues. Though Xcode and Instruments can provide deep detail about what's going on, often some basic information is enough. In this episode I'm going to cover simple yet powerful tools that Xcode provides for Metal diagnostics.

Compile Time Settings

I assume that you compile your Metal files at the same time as your app. You also can do that at runtime, but it depends on the task and its nuances.

So, go to Metal Compiler - Build Options section and set there

  • Produce Debugging Information to Yes, include source code for Debug (it should be by default) - we'll need that in further episodes, but just check.
  • Math Mode to Safe. It turns off aggressive assumptions and approximations and forces precise math. Use it for computations that require high precision.
  • Ignore Warnings to No. Never ignore warnings - they often point to real problems.
  • Treat Warnings as Errors to Yes. It can be annoying, but it keeps your code much cleaner and more stable.

These settings surface issues such as:

  • unused variables: flag forgotten variables so you can use or remove them
  • uninitialised variables: prevent using garbage values
  • using deprecated API: highlight APIs that may behave incorrectly or stop working altogether

Because GPU debugging is far less flexible than CPU debugging, you should avoid fragile code as much as possible. Catching issues during editing and compile time makes future development much easier.

Run Diagnostics

Open the scheme Run settings and go to the Diagnostics tab. At the bottom you'll find the Metal group:

  • API Validation
  • Shader Validation
  • Show Graphics Overview
  • Log Graphics Overview

API Validation

This tool catches issues on the Metal API layer. It shows each issue and where it occurred, which can be invaluable when your code is complex, you're still learning, or you're simply tired and miss something.

Example 1: Wrong offset alignment. If you set the wrong alignment, the API validator catches it, points to the precise line, and explains the problem.

Example 2: Access encoder after endEncoding. In a complex call hierarchy you might pass an encoder around and forget that it's already been ended. The validator lets you know when that happens.

Example 3: Missing binding. It's easy to forget to bind data for your shader or kernel. The validator highlights that as well.

There are many more checks (index mismatches, binding the wrong resource to the wrong slot, and so on), but the goal here is to cover the principles rather than build a complete reference.

Shader Validation

This validator checks for state and memory errors such as out-of-bounds access or dereferencing a nil texture. Because the GPU side is notoriously difficult to debug, the validator is invaluable. I highly recommend keeping it enabled whenever you're developing the Metal layer of your app.

Example 4: Access violation. A bad index value or missing bounds check? The validator points you to the exact line in your shader where it failed.

Example 5: Nil texture. Passing a nil texture is technically valid, but it yields a zero sampling result, which isn't great. The validator logs the issue and points to the code where it happened, so you can trace it back on the CPU side.

Show Graphics Overview

This tool shows an overlay with nearly the same data you see in Xcode's Debug tab:

  • Chipset name
  • Screen resolution
  • Memory usage and availability
  • Enabled validators
  • Performance data: FPS, GPU time per frame, interval between frames
  • Performance plot (CPU vs GPU)

NOTE: This overlay works only when you run your app from Xcode.

Log Graphics Overview

This option outputs the same performance metrics to the console. You can feed that raw data into your own tooling if you need to.

Debug tab

Although the tool looks primitive, it still provides helpful information: not just FPS, but also the CPU versus GPU time. That makes it easier to estimate where performance issues originate.

Conclusion

  • Xcode provides a lot of basic diagnostic tools that surface quick insights and protect your code from simple bugs.
  • Use the most aggressive settings you can to catch issues early.
  • Metal API and shader validators can save huge amounts of time and frustration.
  • You don't need to build your own FPS HUD because Xcode already provides one.

<Prev | Content | Next>