当 MTKView 嵌入 SwiftUI 应用程序时,由于调用 currentRenderPassDescriptor (currentDrawable/nextDrawable) 阻塞而导致卡顿

问题描述 投票:0回答:1

我发现 SwiftUI 应用程序中嵌入的 MTKView 有时会出现卡顿。我使用仪器对此进行了调查:

几乎所有时间,一切都很好,视图以 60fps 流畅渲染。在这里,顶部的行是一个路标,它包装了 MTKViewDelegate 的整个绘制方法。这通常在 1 毫秒内完成。底行是带有显示同步的显示仪器:

有时,我看到对

currentRenderPassDescriptor
的调用会阻塞约 16 毫秒,直到下一帧。这似乎偶尔会影响下一帧,不必要地阻塞主队列并导致卡顿:

根据 Metal 最佳实践指南,它会阻止获取框架的 Drawable,并且只有 3 个,因为它是三重缓冲的。

我没有做任何不寻常的事情,代码遵循 Xcode 中 Metal 游戏模板的示例代码以及 Apple 在 DisplayingAPointCloudUsingSceneDepth 示例项目中在 SwiftUI 中使用 MTKView 的做法。

这通常是由渲染时间较长的帧开始的。单独的框架通常不是什么大问题,而且通常一切都很顺利。但有时这似乎会导致某种“交通堵塞”,其中所有后续帧都会因对

currentRenderPassDescriptor
的阻塞调用而延迟。就像下面的 Hitches 仪器截图一样,前 3 次故障并没有造成大问题,但第四次就出现了“交通拥堵问题”:

当我将 UIKit 滑块放在故事板顶部时,即使使用标准的“Metal Game”Xcode 模板,我也可以重现口吃;拖动滑块时会出现“帧拥堵”。

有人也看到过这个问题,并找到了解决方案吗?如何以平滑的帧速率渲染带有 SwiftUI 内置 UI 的 MTKView?

metal mtkview
1个回答
0
投票

一个有点帮助的解决方案似乎是设置 CAMetalLayer#presentsWithTransaction 属性 属性也可用于 MTKView。

这带有不同的提交/呈现过程,如文档中所述:

commandBuffer.commit()
commandBuffer.waitUntilScheduled()
view.currentDrawable?.present()

这解决了简单滑块示例和我的应用程序中的卡顿问题。

(这是一个经过更改的示例项目:MetalGamePresentsWithTransaction)。

编辑:这大大改善了我的 iPhone 13 Mini 上的卡顿现象,尽管它似乎在 iPhone 15 Pro 上以较低的帧速率渲染,看起来更糟。我认为 120fps/ProMotion 显示器可能存在问题。

© www.soinside.com 2019 - 2024. All rights reserved.