Metal着色器代码在什么条件下"crash?"

Under what conditions does Metal shader code "crash?"

我正在开发基于 Metal 的应用程序,在某些情况下,正确编译和链接的着色器代码会导致应用程序崩溃而不会引发任何错误。

A "crash" 包括视觉输出的暂停(在某些情况下,之前有几个交替帧的短暂停顿),但其他应用程序的其余部分正常处理。 Xcode 性能监控实用程序报告 60fps 但 GPU 延迟为 0ms,并且 CPU 端执行继续,对 Metal API 的调用仍然成功完成。

没有错误报告到控制台。

这非常难以调试,因为我没有迹象表明错误来自着色器代码中的何处。如果我知道这实际上应该发生在什么条件下,那将会有所帮助,这样我就可以有一个很好的清单来检查。否则,每当出现这种情况时,我只是在黑暗中射击。

当您读取或注销 MTLBuffer 的末尾、注销 MTLTexture 的末尾,或者只是 运行 太长时,GPU 可能会崩溃。有一个看门狗计时器,如果 GPU 没有在几秒钟内完成其工作,它将重置 GPU。 GPU 上的工作不会被抢先安排。长时间 运行ning 工作可能会阻止基本 GUI 任务的执行,从而使设备看起来被锁定。如果您有长时间的 运行ning 工作负载,则有必要将其拆分为许多较小的内核。为了保持界面响应,您应该保持工作负载 < 100 毫秒。为避免视频卡顿,建议使用一致的帧速率。

我也经常因为沉重的金属着色器而崩溃,并设法通过限制调度率来修复它。您可以通过测量最后一个 "frame" 的运行时间并在每次调度之前按该数量的比率插入等待来轻松地做到这一点:

[NSthread sleepFortimeInterval: _lastRunTime*RATIO];
NSDate *startTime = [NSDate date];
... [use Metal shaders] ...
_lastRunTime = -[startTime timeIntervalSinceNow];

我将 RATIO 设置为 1.0。所以它永远不会使用超过 50% 的 gpu。它显然会影响帧速率,但可以避免随机崩溃。你可以玩这个比例。好处是您不必担心在不同产品上节流太多或太少,因为它是运行时间的比率。