【发布时间】:2021-11-11 08:22:25
【问题描述】:
我在自己的应用程序中遇到了一个有趣的 Metal 性能问题,我只需对 this example project 进行小幅调整即可重现该问题。我的视图大小约为 1600x900,如下所示:
每帧有两个绘制调用,一个用于背景,一个用于线条。背景由 4 个顶点组成,线条大约有 2000 个顶点。当像上面那样绘制场景时,Xcode 的 GPU 帧捕获告诉我整个帧需要大约 4 毫秒(!)。一些观察:
- 当首先绘制线条时,帧只需约 30 µs
- 仅绘制四个顶点(构成背景)时,帧需要约 3 µs
- 仅绘制线条时,帧耗时约 40 µs
- 如上图所示,但只有线的前约 900 个顶点,整个帧需要约 4 µs
这对我来说没有意义。为什么上述变化会对帧时间产生如此巨大的影响?相差 100 倍。
我在 2018 Mac mini(配备 Intel UHD Graphics 630 1536 MB)上运行代码,以防万一。
以下是对演示项目所做的更改:
- 在初始化期间创建两个
MTLBuffers
AAPLVertex quadVertices[] = { ... 4 vertices omitted ... };
quadBuffer = [_device newBufferWithBytes:quadVertices length:4 * sizeof(AAPLVertex) MTLResourceStorageModeManaged];
AAPLVertex dataVertices[] = { ... ~2000 vertices omitted ... };
dataBuffer = [_device newBufferWithBytes:dataVertices length:2000 * sizeof(AAPLVertex) MTLResourceStorageModeManaged];
- 在
drawInMTKView中绘制两个缓冲区:
[renderEncoder setVertexBuffer:quadBuffer offset:0 atIndex:AAPLVertexInputIndexVertices];
[renderEncoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4];
[renderEncoder setVertexBuffer:dataBuffer offset:0 atIndex:AAPLVertexInputIndexVertices];
[renderEncoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:2000];
-
开启 8x MSAA:
mtkView.sampleCount = 8;和pipelineStateDescriptor.sampleCount = 8; -
将渲染通道的加载动作更改为
MTLLoadActionLoad:renderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionLoad;
编辑:the project is available on my Github.
编辑 2:我在 2020 M1 Macbook 上运行了示例项目,但我无法重现任何要点。基本情况的总帧时间约为 100 µs。不过,我不得不使用 4 的 MSAA 系数,因为 M1 显然不支持 8。
为了透明,我也在 Apple 开发者论坛上问过这个问题:https://developer.apple.com/forums/thread/695245(我希望没问题)
【问题讨论】:
-
能否将您的示例项目上传到 GitHub。
-
@HamidYusifli 当然,给你:github.com/maxjvh/metal-performance-issue
-
您是否尝试过在第 3 步中不启用 8x MSAA?
-
@JeshuaLacock 问题在 MSAA 样本数较低时并不那么突出,但这并不能真正回答问题。我认为 8x MSAA 只会使上述怪异更加明显。
-
我并不是在暗示这是答案 - 我只是想了解这个问题。
标签: macos gpu intel metal objective-c++