捕获iOS应用程序的GPU帧的第一帧。

4
我的应用程序在第一帧上执行几个渲染操作(我正在使用Metal,尽管我认为相同的方法适用于GLES)。例如,它会渲染到在随后的帧中使用但此后不会更新的目标。我正在尝试调试这些渲染操作中的一些绘制调用,并希望使用“GPU捕获帧”功能来实现。我过去曾经使用过它进行按需GPU帧调试,非常有用。
不幸的是,我似乎找不到捕获第一帧的方法。例如,在调试器中断点之前设置断点时,此选项不可用。Xcode行为也似乎不允许在调试开始后捕获帧。甚至似乎没有API可以执行GPU捕获,无论是在Metal APIs还是CAMetalLayer中。
有人成功地做到了吗?
3个回答

7

我再次遇到了这个问题,并且现在已经彻底理解了。由于这是与我的其他答案完全不同的方法,因此我将其作为单独的答案添加。

首先,一些背景知识。捕获GPU帧有三个组成部分:

  1. 告诉 Xcode 你想要捕获一个GPU帧。通常情况下,你可以通过在 Xcode 中点击“GPU Frame Capture”按钮来手动完成这个步骤。
  2. 指示下一个要捕获的帧的开始。通常情况下,这发生在下一个MTLCommandBuffer presentDrawable:出现的时候,该命令用于将帧缓冲区呈现给底层视图。
  3. 指示正在被捕获的帧的结束。通常情况下,这发生在下一个但一个MTLCommandBuffer presentDrawable:出现的时候。

在捕获第一个帧或第一个帧之前的活动时,只有第三个步骤可用,因此我们需要另一种方法来执行前两个步骤:

  1. 要告诉 Xcode 开始捕获帧,请在代码的某个位置添加一个断点以在要开始捕获帧之前触发。右键单击断点,从弹出菜单中选择编辑断点...,并将捕获GPU帧操作添加到断点中:

    enter image description here

  2. 要在第一次出现MTLCommandBuffer presentDrawable:之前指示要捕获的帧的开始,可以使用MTLCommandQueue insertDebugCaptureBoundary方法。例如,你可以在实例化MTLCommandQueue时立即调用此方法,以立即开始捕获提交到队列的所有内容。确保在调用此代码之前触发项目1中的断点。

  3. 要指示已捕获帧的结束,你可以依靠第一个正常出现的MTLCommandBuffer presentDrawable:,或者你可以添加第二个MTLCommandQueue insertDebugCaptureBoundary的调用。

最后,MTLCommandQueue insertDebugCaptureBoundary方法实际上并不会导致帧被捕获。它只是标记一个边界点,因此你可以在将来的调试中保留它。如果你想将其从生产代码中删除,请将其包装在DEBUG编译条件中。


3

Try...

[myMTLCommandEncoder insertDebugSignpost: @"com.apple.GPUTools.event.debug-frame"]. 

说实话,我自己没有尝试过,但它类似于类似的东西。
glInsertEventMarkerEXT(0, "com.apple.GPUTools.event.debug-frame")

已经有关于OpenGL ES的文件记录,网络上也提到它可以在Metal上运行。


看起来很有前途,但对于Metal似乎不起作用,至少对我来说是这样。 - MuertoExcobito

0
首先,在Metal中,我通常使用Metal进行并行计算,然后GPU捕获帧总是灰色的。所以,到目前为止,我发现有两种方法是可行的。
1. 在iOS 11中,你可以使用[[MTLCaptureManager alloc] startCaptureWithDevice:m_Device];来捕获帧,这样你就可以对计算着色器的性能进行分析。
2. 在iOS 11以下版本(MTLCaptureManager和MTLCaptureScope在iOS 11.0中新增),你可以使用断点,然后编辑操作:Capture GPU Frame

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接