Metal GPU 帧时间表现不直观

bod*_*lex 5 macos gpu intel objective-c++ metal

我在自己的应用程序中遇到了一个有趣的 Metal 性能问题,我只需对此示例项目进行少量调整即可重现该问题。我的视图大小约为 1600x900,如下所示:

\n

在此输入图像描述

\n

每帧有两次绘制调用,一次用于背景,一次用于线条。背景由4个顶点组成,线条大约有2000个顶点。当场景像上面一样绘制时,Xcode 的 GPU 帧捕获告诉我整个帧需要大约 4 毫秒(!)。一些观察结果:

\n
    \n
  • 当先画线时,该帧只需要~30 \xc2\xb5s
  • \n
  • 当仅绘制四个顶点(构成背景)时,框架需要 ~3 \xc2\xb5s
  • \n
  • 仅绘制线条时,帧需要约 40 \xc2\xb5s
  • \n
  • 当像上面一样绘制时,但只有线的前 ~900 个顶点,整个框架需要 ~4 \xc2\xb5s
  • \n
\n

这对我来说没有意义。为什么上述变化会对帧时间产生如此巨大的影响?这是 100 倍的差异。

\n

我正在 2018 Mac mini(配备 Intel UHD Graphics 630 1536 MB)上运行代码,以防万一这很重要。

\n
\n

以下是对演示项目所做的更改:

\n
    \n
  1. MTLBuffer在初始化期间创建两个s
  2. \n
\n
AAPLVertex quadVertices[] = { ... 4 vertices omitted ... };\nquadBuffer = [_device newBufferWithBytes:quadVertices length:4 * sizeof(AAPLVertex) MTLResourceStorageModeManaged];\n\nAAPLVertex dataVertices[] = { ... ~2000 vertices omitted ... };\ndataBuffer = [_device newBufferWithBytes:dataVertices length:2000 * sizeof(AAPLVertex) MTLResourceStorageModeManaged];\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. 将两个缓冲区绘制在drawInMTKView
  2. \n
\n
[renderEncoder setVertexBuffer:quadBuffer offset:0 atIndex:AAPLVertexInputIndexVertices];\n[renderEncoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4];\n\n[renderEncoder setVertexBuffer:dataBuffer offset:0 atIndex:AAPLVertexInputIndexVertices];\n[renderEncoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:2000];\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. 打开 8x MSAA:mtkView.sampleCount = 8;pipelineStateDescriptor.sampleCount = 8;

    \n
  2. \n
  3. 将渲染通道的加载操作更改为MTLLoadActionLoadrenderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionLoad;

    \n
  4. \n
\n

编辑:该项目可以在我的 Github 上找到

\n

编辑 2:我在 2020 M1 Macbook 上运行了示例项目,但无法重现任何要点。基本情况下的总帧时间约为 100 \xc2\xb5s。不过,我必须使用 MSAA 因子 4,因为 M1 显然不支持 8。

\n
\n

为了透明起见,我还在苹果开发者论坛上提出了这个问题:https://developer.apple.com/forums/thread/695245(我希望没问题)

\n

roj*_*jun 0

我可以验证,如果没有 8x MSAA,它的运行速度会更快。但是,8x MSAA 不应在如此简单的项目中导致问题。为什么这是一个选择?

使用相同的机器:

  • 样本计数 1 => 300 us
  • 样本计数 2 => 600 us
  • 样本计数 4 => 1.9 毫秒
  • 样本计数 8 => 3.7 毫秒