iOS 14 解决方法中的 SceneKit Metal 着色器编译性能错误
Posted
技术标签:
【中文标题】iOS 14 解决方法中的 SceneKit Metal 着色器编译性能错误【英文标题】:SceneKit Metal shader compilation performance bug in iOS 14 workaround ideas 【发布时间】:2021-02-04 21:28:22 【问题描述】:我正在寻找 SceneKit 专家来提出一些方法来解决 ios 14.x 和 macOS Catalyst 11.x 中 SceneKit 的内置金属着色器编译中的性能不佳错误。由于我已尽我所能让 Apple 解决问题(TSI、反馈、Twitter、开发者论坛、Apple Evangelist),因此我们需要一种解决方法。
使用带有 SceneKit 跟踪的 Xcode Instruments 应用,在 iOS 14.0、14.1 和 14.2 Beta(包括 Beta 4)与 iOS 13.7 中,SceneKit 着色器编译似乎会慢约 100 倍。例如,在 iOS 13.7 中,SceneKit 编译着色器通常需要 1-2 毫秒,而在 iOS 14 中可能需要 200 毫秒。
每次我们将新的模型节点树添加到可见场景中的父节点时,SceneKit 似乎都会自动编译着色器。
在我们的应用程序中加载包含数十个模型节点的典型 SceneKit 场景可能需要不到 2 秒到超过 30 秒。并且由于 SceneKit 着色器编译发生在似乎由 CADisplayLink 处理程序调用的渲染线程上,因此整个应用程序 UI 可以完全冻结数秒(在测试中超过 30 秒)。这极大地影响了我们基于 SceneKit 的应用的可用性。
如果您认为要获得 60-30 fps 的场景更新,您需要每帧花费不超过 16-33 毫秒的时间来避免丢帧,那么每个帧花费 200 毫秒是非常糟糕的。 (如果你想在 iPad Pro 上获得 120 fps...)
这个错误的一个问题是它非常不一致:我可以使用 Instruments 运行一次应用程序,编译时间会很好(1-2 毫秒),我会再运行几次,它会是每个着色器编译都不好(100-200 毫秒)。我认为有一些金属着色器缓存正在进行,但我不知道它是如何工作的以及是什么导致它失效。
我已经尝试了几十种方法来解决这个问题:多个队列/线程/操作、事务、延迟节点添加以一次添加多个节点、使用执行(避免:致命的崩溃错误)等。我试过了在所有其他节点之前或在所有其他节点之后添加带灯光的节点。
我们在整个模型中使用 PBR 材质,并且在大多数场景(例如户外的太阳或月亮、室内的灯)中启用了多个带阴影的灯光以及环境照明。在 SCNView 非 AR 模式下不启用反射,但显然 ARSceneView 确实启用了它们。我们通常不使用任何我们自己的着色器,尽管一些场景使用自定义着色器修改器,移除后似乎没有任何效果。
非常感谢任何和所有建议。谢谢!
这是一个示例场景屏幕截图和来自 Instruments 12.1 的着色器编译时间,在带有 iOS 14 的 iPad Pro 11 (2018) 上运行应用程序:
00:01.347.989 667.58 µs Compile shader
00:01.349.275 579.62 µs Compile shader
00:01.350.529 779.17 µs Compile shader
00:01.353.772 809.92 µs Compile shader
00:01.358.928 909.54 µs Compile shader
00:01.361.232 831.96 µs Compile shader
00:01.363.443 779.17 µs Compile shader
00:01.371.931 1.09 ms Compile shader
00:02.336.543 786.88 µs Compile shader
00:02.338.079 594.67 µs Compile shader
00:02.344.969 805.38 µs Compile shader
00:02.349.393 845.71 µs Compile shader
00:02.351.679 775.33 µs Compile shader
00:02.353.969 714.75 µs Compile shader
00:02.355.389 578.96 µs Compile shader
00:02.374.813 243.54 ms Compile shader
00:02.619.090 204.87 ms Compile shader
00:02.824.654 203.34 ms Compile shader
00:03.033.721 203.22 ms Compile shader
00:03.245.523 199.92 ms Compile shader
00:03.446.541 641.67 µs Compile shader
00:03.458.231 200.25 ms Compile shader
00:03.670.527 202.03 ms Compile shader
00:03.875.402 200.12 ms Compile shader
00:04.089.184 725.21 µs Compile shader
00:04.091.070 201.98 ms Compile shader
00:04.297.075 212.00 ms Compile shader
00:04.509.799 200.11 ms Compile shader
00:04.710.886 203.88 ms Compile shader
00:04.915.507 199.86 ms Compile shader
00:05.116.368 199.27 ms Compile shader
00:05.316.424 200.51 ms Compile shader
00:05.517.957 203.45 ms Compile shader
00:05.722.065 646.38 µs Compile shader
00:05.723.205 582.29 µs Compile shader
00:05.802.072 831.96 µs Compile shader
00:05.808.265 203.29 ms Compile shader
【问题讨论】:
【参考方案1】:我在 iOS 14 中看到过类似的性能下降。 在 App Clip 中运行的基于 SceneKit 的 ARKit 项目甚至会发生完全冻结。 您最近是否听说过任何改进或解决方法?
【讨论】:
不幸的是,性能问题在 iOS 14.3 中仍然没有得到修复。 UI 挂起非常糟糕 - 在我们的应用程序将多个模型加载到场景中时,我们看到在控制台应用程序中记录了这样的挂起:com.apple.hangtracer 检测到挂起:10.03 秒(始终挂起报告)com.apple。 hangtracer 检测到挂起:1.55 秒(始终挂起报告)我在 Apple 开发者论坛中创建了一个线程,提供更多信息,其他开发者也遇到问题:developer.apple.com/forums/thread/659856 感谢您的提醒。我已经在论坛上发帖并邮寄给苹果开发关系。这真的很糟糕——基本上是在冻结发生时强迫用户杀死应用程序。这在较旧的设备上非常突出(在 iOS 13 上构建相同的设备类型可以完美运行)。我真的很希望这里有 iOS 14.3……这是并排比较:streamable.com/wx2at9 左边是 iOS 14.2,右边是 iOS 13.6。以上是关于iOS 14 解决方法中的 SceneKit Metal 着色器编译性能错误的主要内容,如果未能解决你的问题,请参考以下文章
如何将 .dae 文件加载到 iOS SceneKit 中的 SCNNode 中?