Search code examples
iosmetal

Metal: GPU capture from a unit test


Is there a way to do a GPU capture from a unit test? This would be useful for our debugging of compute kernels (specifically, how they modify textures). Also useful for profiling and optimization.

I tried using MTLCaptureManager but it didn't seem to do anything within a unit test.


Solution

  • This is possible in a slightly roundabout way using the programmatic GPU capture APIs introduced in macOS Catalina. Although you cannot perform a capture and automatically launch the Metal frame debugger, you can capture inside a unit test and write the results to a GPU trace file for subsequent inspection.

    To do this you need to create a GPUCaptureDescriptor object specifying which object's scope to capture (device, command queue, etc.), set its destination to .gpuTraceDocument, and give it a URL to write the file to. Then you can start/stop capture in your setUp/tearDown methods, or wherever you prefer.

    let captureDescriptor = MTLCaptureDescriptor()
    captureDescriptor.captureObject = commandQueue
    captureDescriptor.destination = .gpuTraceDocument
    captureDescriptor.outputURL = URL(filePath: "/some/path/someName.gputrace")
    try MTLCaptureManager.shared().startCapture(with: captureDescriptor)
    

    Note that the host app must have GPU capture enabled either via an environment variable or by adding an entry for the MetalCaptureEnabled key (set to a Boolean value of YES) in its Info.plist, or capture will not be enabled, even if it would otherwise be enabled by the app's scheme settings.