Vulkan 的内存限制
Mali GPU
本文介绍 Vulkan 应用程序在 Mali GPU 上可能触发内存不足 (OOM) 条件的情况,即使 API 使用正确,也会导致 DEVICE_LOST
错误。开发人员最常遇到的 OOM 条件是由于顶点负载过高引起的,这在将 Vulkan 应用程序从桌面移植到移动平台时可能相对常见。
Mali GPU 有一个内存区域,可用于存储渲染通道的中间几何输出。此内存用于存储顶点、细分和几何着色生成的,在片段着色之前的所有可变数据。超出此区域的大小可能会导致 VK_ERROR_DEVICE_LOST
。在当前的 Mali GPU 上,此限制固定为 180 MB,但在未来的 GPU 中可能会增加或完全取消。
此限制背后的原因是,基于图块的渲染器需要写出然后读回中间几何输出,因此顶点负载与内存带宽直接相关。对于一个典型的程序,每个顶点使用 64 字节的可变数据,180 MB 的中间存储可以包含超过 200 万个顶点,我们预计这足以满足普通移动应用程序的使用。我们现在将介绍为什么这种顶点负载不太可能持续以及如果您的应用程序正在遇到这种情况,可能的缓解措施。
让我们考虑一个顶点繁重的应用程序,它使用单个渲染通道并达到 180 MB 的限制。由于 GPU 必须将数据写出并从内存中读回,这会导致每个渲染通道 2 x 180 = 360 MB,在 30 FPS 时,内存带宽高达 30 x 360 = 10.8 GB/s。内存带宽与功耗直接相关,可以估计为 100 mW/(GB/s)。这意味着使用 180 MB 可变数据的应用程序将消耗至少 1.08 W,这还不包括对内存带宽和通用 GPU 功耗的进一步贡献。移动 GPU 无法在不出现过热的情况下维持如此高的功耗,这会进一步导致 GPU 频率降低和性能下降。
解决此问题的唯一真正方法是保持应用程序的顶点数低于大约 200 万个,如上所述,对于每个顶点平均使用 64 字节的可变数据。在超出内存存储且减少顶点负载不可行的情况下,我们建议应用程序将渲染通道拆分为多个渲染通道,每个渲染通道使用安全的中间存储量。稍后的渲染通道可以使用 loadOp=LOAD 来恢复帧缓冲区的内容,并继续在早期渲染之上进行渲染。这种形式的增量渲染可能会影响性能,因为颜色图像会被写出,然后再次读回。
如果你的顶点负载不可预测,并且在实际应用中遇到了 DEVICE_LOST
问题,你可以设置一个方案来估计渲染通道中每个绘制调用的内存消耗,然后在达到限制时执行增量渲染。 你应该记住,内存会分配给绘制调用引用的最小和最大索引之间的所有顶点索引,以及细分和几何着色生成的所有顶点,即使它们随后被裁剪和剔除过程剔除。 这样的估计会是保守的,因为实际分配的内存量可能会更低,因此我们不建议在 180 MB 的限制上增加额外的安全边距。