To get a better view of the performance of our game, we would like to run a Metal Capture while running on iOS. For this, we would like to use the system documented by Apple here https://developer.apple.com/documentation/xcode/capturing\-a\-metal\-workload\-programmatically.
Over the past couple of weeks, I have attempted to translate the Swift code to work within the Objective C Unreal Engine 4.27 configuration.
Below is the code that I am using for this. When the metal capture starts, the framerate gets a lot worse as you would expect when performing such an intensive profiling run. The code also successfully generates a .gputrace file, but when I try to open it in Xcode, I get an error saying “Xcode failed to open the gputrace document. The index file does not exist. The capture may be incomplete or corrupt. (2)”.
I believe that this is because I do not commit the command buffer before stopping the capture. In StopMetalCapture, I have commented out the code that does so, because running that code crashes the game. What is the correct code to commit the Unreal Metal Command Buffer?
#if PLATFORM_IOS
void StartMetalCapture()
{
FMetalContext& Context = GetMetalDeviceContext();
mtlpp::Device MetalDevice = Context.GetDevice();
id<MTLDevice> device = MetalDevice.GetPtr();
// Get Documents directory path
NSArray<NSURL *> *documentsDirectories = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask];
NSURL* documentsDirectory = [documentsDirectories firstObject];
NSURL* outputURL = [documentsDirectory URLByAppendingPathComponent : @"MyCapture.gputrace"];
MTLCaptureManager *captureManager = [MTLCaptureManager sharedCaptureManager];
MTLCaptureDescriptor *captureDescriptor = [[MTLCaptureDescriptor alloc] init];
captureDescriptor.captureObject = device;
captureDescriptor.destination = MTLCaptureDestinationGPUTraceDocument;
captureDescriptor.outputURL = outputURL;
if (![captureManager supportsDestination:MTLCaptureDestinationGPUTraceDocument])
{
NSLog(@"Capturing to a GPU trace file isn't supported.");
return;
}
NSError *error = nil;
if (![captureManager startCaptureWithDescriptor:captureDescriptor error:&error])
{
NSLog([Content removed] error);
}
else
{
NSLog([Content removed] outputURL);
}
}
void StopMetalCapture()
{
/*FMetalContext& Context = GetMetalDeviceContext();
mtlpp::CommandBuffer& CommandBuffer = Context.GetCurrentCommandBuffer();
id<MTLCommandBuffer> NativeCommandBuffer = CommandBuffer.GetPtr();
[NativeCommandBuffer commit];*/
MTLCaptureManager *captureManager = [MTLCaptureManager sharedCaptureManager];
[captureManager stopCapture];
NSLog(@"Finished metal capture");
}
#endif