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 中?

iOS 上 Swift 中的自定义 SceneKit 几何图形不起作用,但等效的 Objective C 代码可以

使用 SceneKit 的台球游戏中的后旋效果

ios SceneKit 3D引擎初探

iOS SceneKit 霓虹灯

USDZ 模型在 SceneKit 中有孔,但在 QuickLook 中没有