Chr*_*isL 5 xcode scenekit metal swift3
我有一个 SceneKit 应用程序(使用 Metal)在屏幕上出现新节点时口吃的问题,即使该应用程序在 60 fps 之前和之后顺利运行。
想象一个游戏,其中的东西被摧毁,有时在某些东西被摧毁的地方会出现通电。我很确定口吃与出现的能量提升有关,因为当事物刚刚被破坏(因此从场景中移除)时它不会发生。
到目前为止我所做的尝试修复口吃:我通过 SceneKit 视图的 preload 方法预加载节点,并仅在其完成处理程序中将它们添加到场景中。我早在需要显示它们之前就将它们添加到相机上方,并且在需要时将它们移动到正确的位置。我已经实施了一种排队机制,以确保每帧仅进行一次更改(移除被破坏物品的节点,将通电移至其位置)。
但是有时(并非总是)在出现通电时仍然会出现口吃。我想知道 SceneKit 是否仅在节点第一次出现时才执行某些操作(即使它们已被预加载)。无论发生什么似乎都足以导致口吃,但对于 XCode 性能计来说太短了,无法显示它。每帧都有大量空闲时间,CPU 和 GPU 甚至从未接近最大化。
我不认为这个问题与复杂的几何图形或巨大的纹理有关,因为当我使用具有统一颜色的简单立方体时,它仍然会发生。
知道这里发生了什么或者我如何追踪它吗?
我自己找到了原因,如果你遇到同样的问题,我想与你们分享。
SceneKit 在幕后所做的神秘任务是重新编译各个节点的着色器。虽然 Apple 没有证实这一点,但我很确定 SceneKit 有一个策略,即始终使用最有效的着色器,这些着色器足够复杂以按预期渲染相应的节点。这意味着每当您添加效果、材质属性或光源时,它都会编译更复杂的着色器。当您消除照明计算复杂性增加的原因时,它将再次用更简单的着色器替换它。
虽然这在始终获得尽可能高的性能方面很棒,但它也有一个缺点,这就是我所经历的。重新编译着色器需要一些时间,导致 CPU 负载并强制 GPU 等待着色器的新版本。最后,它会导致应用程序卡顿,即使它们大部分时间都运行得非常流畅。
解决这个问题的最简单方法是用您自己的代码(使用 SCNProgram)替换 SceneKit 着色器,但这也会让您失去 SceneKit 提供的大部分舒适度。由于这不是我想要的,我最终采用了以下方法:
我强制 SceneKit 最初编译所有节点的所有着色器,这些着色器通过在开始时用黑色覆盖覆盖场景,在相机前面添加所有节点,然后在淡出覆盖之前将它们移动到正确的位置层。我还通过从不完全关闭我一直不需要的效果来避免重新编译(例如,通过将其强度更改为 0.1 而不是 0 来关闭灯光)。这使得 SceneKit 始终保持相同的着色器,从而避免口吃。
再说一遍:这还没有得到 Apple 的证实,但到目前为止它有效,所以我认为我的假设是正确的 ;-)。
| 归档时间: |
|
| 查看次数: |
452 次 |
| 最近记录: |