MacOS Metal:无法从命令行应用程序捕获 GPU 帧

MacOS Metal: Failing to capture GPU Frame from command line app

我正在尝试在命令行应用程序中使用 MTLCaptureManager 以编程方式捕获 GPU 帧。

到目前为止,捕获管理器无法支持 MTLCaptureDestinationGPUTraceDocument 目的地。

我尝试使用 XCode 创建一个非常小的重现案例:

#import <Foundation/Foundation.h>
#import <Metal/Metal.h>

int main(int argc, const char * argv[]) {
  @autoreleasepool {

      id<MTLDevice> device = MTLCreateSystemDefaultDevice();
      
      MTLCaptureManager* captureManager = [MTLCaptureManager sharedCaptureManager];
      if (![captureManager supportsDestination:MTLCaptureDestinationGPUTraceDocument])
      {
        NSLog(@"********** captureManager does not support MTLCaptureDestinationGPUTraceDocument ************");
      }
      else
      {
        NSLog(@"captureManager support is fine");
      }
  }
  return 0;
}

当运行和XCode时,似乎愿意工作:输出是:

2020-09-02 16:25:59.712217+0200 testMetalCapture[20095:416447] Metal GPU Frame Capture Enabled
2020-09-02 16:25:59.712503+0200 testMetalCapture[20095:416447] Metal API Validation Enabled
2020-09-02 16:26:00.669092+0200 testMetalCapture[20095:416447] captureManager support is fine
Program ended with exit code: 0

但是当我从终端存档构建结果并运行时,它失败了:

2020-09-02 16:32:57.607 testMetalCapture[20126:419837] ********** captureManager does not support MTLCaptureDestinationGPUTraceDocument ************

是否有任何 运行 时间环境我可以在终端中重现以使 MTLCaptureManager 正常工作?

(环境是 XCode 11.6 + MacOS 10.15 Catalina)

据我了解(我找不到任何官方文档):

  • MTLCaptureManager 需要 Info.plist 的授权:MetalCaptureEnabled 应设置为 YES
  • 正确的方法是将命令行应用程序与这样的plist捆绑在一起
    • 这很复杂,参见示例 Building OSX App Bundle

我偶然发现,如果在与命令行应用程序相同的目录中有一个 Info.plistMTLCaptureManager 也可以工作。

这个Info.plist几乎可以是空的,像这样:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>MetalCaptureEnabled</key>
    <true/>
</dict>
</plist>

通过这个简单的设置,我可以 运行 我的测试程序(以及我的真实程序)

% ./testMetalCapture
2020-10-02 15:53:08.507 testMetalCapture[28559:686864] Metal GPU Frame Capture Enabled
2020-10-02 15:53:08.523 testMetalCapture[28559:686864] captureManager support is fine

(我目前使用的是MacOSX 10.15.6,以后可能会坏掉)

@rotoglup 的技巧对我有用,直到它不再起作用:一些缓冲区充满了零,并且没有图像出现在金属调试器内的 'screenshots' 中。我不知道这是因为 OS 或 XCode 或其他原因的更新。

正如@rotoglup 建议的那样,我仍然需要 Info.plist 包含此内容:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>MetalCaptureEnabled</key>
    <true/>
</dict>
</plist>

但我还需要在启动命令行应用程序的终端中将 METAL_DEVICE_WRAPPER_TYPE 环境变量设置为 1:

export METAL_DEVICE_WRAPPER_TYPE=1

有了这个,缓冲区就被正确填满了,我得到了 non-empty 个屏幕截图。