# Setup Xcode for GPU Frame Capture

Xcode needs to be able to attach to a process to be able to instrument and
profile it.

As you are working on Impeller, it is easiest to set up an Xcode project just to
bring Impeller artifacts up-to-date, launch the required test binary, enable
Metal validation layer, and either capture a GPU frame or instrument the test
case with Instruments.

If you are already somewhat familiar with Xcode, none of this is new. If not,
follow along.

# Set Up an Xcode Project for Instrumentation

In Xcode, `File -> New -> Project…`, select an empty project.

![alt_text](https://raw.githubusercontent.com/flutter/assets-for-api-docs//5da33067f5cfc7f177d9c460d618397aad9082ca/assets/engine/impeller/xcode_frame_capture/image1.avif "image_tooltip")

Call it whatever you want, you are not going to check this into version control
and the targets are going to be specific to your workflow.

![alt_text](https://raw.githubusercontent.com/flutter/assets-for-api-docs//5da33067f5cfc7f177d9c460d618397aad9082ca/assets/engine/impeller/xcode_frame_capture/image2.avif "image_tooltip")

Save it outside the source tree. Since you are not going to check this in, you
don’t want to accidentally delete it via a `git clean -fdx` when regenerating
the licenses (ask me how I know).

Create a new `External Build System` target in the empty project by clicking on
the `+` icon at the bottom.

![alt_text](https://raw.githubusercontent.com/flutter/assets-for-api-docs//5da33067f5cfc7f177d9c460d618397aad9082ca/assets/engine/impeller/xcode_frame_capture/image3.avif "image_tooltip")

Click through the defaults (it wants you to use `make`) to create the target, we
are going to be modifying it later.

![alt_text](https://raw.githubusercontent.com/flutter/assets-for-api-docs//5da33067f5cfc7f177d9c460d618397aad9082ca/assets/engine/impeller/xcode_frame_capture/image4.avif "image_tooltip")

Select the target you just created from the sidebar and in the `Info` tab, fill
in the command you would use to bring the target up-to-date. In the example, I
am building the Impeller unit-tests.

![alt_text](https://raw.githubusercontent.com/flutter/assets-for-api-docs//5da33067f5cfc7f177d9c460d618397aad9082ca/assets/engine/impeller/xcode_frame_capture/image5.avif "image_tooltip")

If you wanted to instrument multiple targets and switch between them, you would
add them here.

Xcode still doesn’t know how to launch the executables generated by the targets
however. You need to specify a Run Scheme for that. We’ll do that next.

Click the default scheme for the target.

![alt_text](https://raw.githubusercontent.com/flutter/assets-for-api-docs//5da33067f5cfc7f177d9c460d618397aad9082ca/assets/engine/impeller/xcode_frame_capture/image6.avif "image_tooltip")

In the Pop-Up, click `Edit Scheme`.

![alt_text](https://raw.githubusercontent.com/flutter/assets-for-api-docs//5da33067f5cfc7f177d9c460d618397aad9082ca/assets/engine/impeller/xcode_frame_capture/image7.avif "image_tooltip")

In the Info tab, select the executable you want to launch after the target has
been updated by clicking on `Other…`.

![alt_text](https://raw.githubusercontent.com/flutter/assets-for-api-docs//5da33067f5cfc7f177d9c460d618397aad9082ca/assets/engine/impeller/xcode_frame_capture/image8.avif "image_tooltip")

I want to launch the unit-tests harness. Select it in the `out` directory.

![alt_text](https://raw.githubusercontent.com/flutter/assets-for-api-docs//5da33067f5cfc7f177d9c460d618397aad9082ca/assets/engine/impeller/xcode_frame_capture/image9.avif "image_tooltip")

Now, when you click `Product -> Run` in Xcode, the unit-tests target will be
brought up to data and run.

# Enabling Metal Validation & GPU Frame Capture

Xcode doesn’t know that the executable you are trying to instrument is Metal
enabled. You just asked it to launch a random executable it knows nothing about.

In the `Options` tab on the `Edit Scheme…` pop-up, in the `GPU Frame Capture`
section, set API detection to `Metal` and check `Profile GPU trace after
capture`.

![alt_text](https://raw.githubusercontent.com/flutter/assets-for-api-docs//5da33067f5cfc7f177d9c460d618397aad9082ca/assets/engine/impeller/xcode_frame_capture/image10.avif "image_tooltip")

Then, in the `Diagnostics` tab on the `Edit Scheme…` pop-up, in the `Metal`
section, enable `API Validation` and `Shader Validation`.

![alt_text](https://raw.githubusercontent.com/flutter/assets-for-api-docs//5da33067f5cfc7f177d9c460d618397aad9082ca/assets/engine/impeller/xcode_frame_capture/image11.avif "image_tooltip")

On a side note, you may be tempted to enable all the other diagnostics. Be aware
that some of those diagnostics need Xcode to be able to re-compile the
translation units in the engine. But, it doesn’t know how to do that, only
GN/Ninja does. So some of those will be unavailable.

Any Impeller test that sets up a Playground will now automatically have GPU
frame capture enabled.

# Select the Playground Enabled Test to Profile

Tests that launch Playground instances are just Google Test cases. You just need
to [pass the right Google Test
flags](https://google.github.io/googletest/advanced.html#running-a-subset-of-the-tests)
to the running executable as command line arguments.

To do this, in the `Options` tab on the `Edit Scheme…` pop-up, in the `Arguments
Passed on Launch` section, add the right `--gtest_filter=` to launch, and
instrument just the one test you want.

You also need to set the `--enable_playground` flag in order to do frame capturing.

![alt_text](https://raw.githubusercontent.com/flutter/assets-for-api-docs//5da33067f5cfc7f177d9c460d618397aad9082ca/assets/engine/impeller/xcode_frame_capture/image12.avif "image_tooltip")

This is also the spot where you will add other command line arguments that will
aid in your debugging. In that example, `–timeout=-1` will disable the Flutter
test hang watchdog which will kill your process if the test doesn’t complete in
30 seconds. I also like to set the VM service port to a known value so I can
get to it and disable service auth codes so I can just refresh the page to
connect to a new instance of the VM service.
