blob: ef04d04aff32e1b81a12084a40506acf29265134 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "impeller/renderer/backend/metal/gpu_tracer_mtl.h"
#include <fml/logging.h>
namespace impeller {
GPUTracerMTL::GPUTracerMTL(id<MTLDevice> device) : device_(device) {}
GPUTracerMTL::~GPUTracerMTL() = default;
bool GPUTracerMTL::StartCapturingFrame(GPUTracerConfiguration configuration) {
if (!device_) {
return false;
}
MTLCaptureManager* captureManager = [MTLCaptureManager sharedCaptureManager];
if (captureManager.isCapturing) {
return false;
}
if (@available(iOS 13.0, macOS 10.15, *)) {
MTLCaptureDescriptor* desc = [[MTLCaptureDescriptor alloc] init];
desc.captureObject = device_;
MTLCaptureDestination targetDestination =
configuration.mtl_frame_capture_save_trace_as_document
? MTLCaptureDestinationGPUTraceDocument
: MTLCaptureDestinationDeveloperTools;
if (![captureManager supportsDestination:targetDestination]) {
return false;
}
desc.destination = targetDestination;
if (configuration.mtl_frame_capture_save_trace_as_document) {
if (!CreateGPUTraceSavedDictionaryIfNeeded()) {
return false;
}
NSURL* outputURL = GetUniqueGPUTraceSavedURL();
desc.outputURL = outputURL;
}
return [captureManager startCaptureWithDescriptor:desc error:nil];
}
[captureManager startCaptureWithDevice:device_];
return captureManager.isCapturing;
}
bool GPUTracerMTL::StopCapturingFrame() {
if (!device_) {
return false;
}
MTLCaptureManager* captureManager = [MTLCaptureManager sharedCaptureManager];
if (!captureManager.isCapturing) {
return false;
}
[captureManager stopCapture];
return !captureManager.isCapturing;
}
NSURL* GPUTracerMTL::GetUniqueGPUTraceSavedURL() const {
NSURL* savedDictionaryURL = GetGPUTraceSavedDictionaryURL();
NSString* uniqueID = [NSUUID UUID].UUIDString;
return [[savedDictionaryURL URLByAppendingPathComponent:uniqueID]
URLByAppendingPathExtension:@"gputrace"];
}
bool GPUTracerMTL::CreateGPUTraceSavedDictionaryIfNeeded() const {
NSFileManager* fileManager = [NSFileManager defaultManager];
NSURL* gpuTraceSavedDictionaryURL = GetGPUTraceSavedDictionaryURL();
if ([fileManager fileExistsAtPath:gpuTraceSavedDictionaryURL.path]) {
return true;
}
NSError* error = nil;
[fileManager createDirectoryAtURL:gpuTraceSavedDictionaryURL
withIntermediateDirectories:NO
attributes:nil
error:&error];
if (error != nil) {
FML_LOG(ERROR) << "Metal frame capture "
"CreateGPUTraceSavedDictionaryIfNeeded failed.";
return false;
}
return true;
}
NSURL* GPUTracerMTL::GetGPUTraceSavedDictionaryURL() const {
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString* docPath = [paths objectAtIndex:0];
NSURL* docURL = [NSURL fileURLWithPath:docPath];
NSURL* gpuTraceDictionaryURL =
[docURL URLByAppendingPathComponent:@"MetalCaptureGPUTrace"];
return gpuTraceDictionaryURL;
}
} // namespace impeller