Adreno GPU上Android 游戏开发介绍(1)
理解和解决图形内存负载
由于移动 GPU 的硬件条件不同,某些在 PC 和游戏机等平台上运行良好的编程技术可能无法很好地移植到移动设备上。
图形内存 (GMEM) 负载是影响移动应用程序中 GPU 性能的最常见问题之一。 在本节中,我们将向您展示如何使用 Snapdragon Profiler 在您的应用程序代码中查找 GMEM 负载。
简而言之
清除或使所有帧缓冲区附件无效。 这将向 GPU 指示不要将图块数据从系统内存加载到 GMEM。
什么是图形内存负载(未解析)?
Qualcomm® Adreno™ GPU 的平铺架构管道包括渲染通道。 在渲染过程中,每个图块都被渲染到 GMEM 中。 按照驱动程序的正常行为,先前的帧缓冲区数据从主内存加载到每个 tile 的 GMEM 中,即发生 GMEM 加载(或未解析)。
为什么图形内存负载很昂贵?
问题是每个 GMEM 加载都会减慢处理速度。 如果帧缓冲区的内容被清除或无效,驱动程序可以清除 GMEM 中的该图块。 虽然这涉及额外的图形调用及其相关开销,但它比为每个正在渲染的 bin 将帧缓冲区加载回 GMEM 成本更低。
GMEM 负载的两个主要原因是:
- 对驱动程序的不当提示 — 应用程序代码使驱动程序认为需要帧缓冲区的先前内容(通常是通过忽略清除缓冲区)。 这归结为一个相对简单的修复,它在减少渲染时间方面取得了很好的回报。 它主要适用于 OpenGL ES 编程,因为 Vulkan 显式处理条件。
- 算法 - 某些 API,例如 glReadPixels 和 glFlush 强制管道刷新以获得结果。 当您恢复绘图框架内容时,执行此中间框架将导致 GMEM 加载。 您通常可以通过修改算法来避免 GMEM 负载。
在 Snapdragon Profiler 中检测图形内存负载
在 Trace Capture 模式下使用 Snapdragon Profiler,您可以允许渲染阶段指标在其自己的轨道中突出显示 GMEM 负载。
在下面的屏幕截图中(基于来自 Adreno SDK 的景深演示应用程序),红色块显示 GMEM 加载(深度模板)在渲染四个不同的表面(0、16、32 和 48)时发生:
渲染阶段的设置对话框显示这些 GMEM 加载占用了总渲染时间的大约 9%。
如果不需要 GMEM 加载,您可以回收大约 9% 的帧时间。
然后,您可以在 Snapdragon Profiler 中使用 Snapshot Capture 模式来确定 GMEM 负载的原因。
带有 GMEM 负载的第一个表面是第一个绑定的表面 — glBindFrameBuffer。 帧缓冲区参数设置为 1: # 选择帧缓冲区对象 1 (FBO 1) 以检查资源。 检查器视图显示表面具有颜色、深度和模板的附件。 # glClearColor 和 glClearDepth 调用让 GPU 认为 Stencil 附件的内容与下一帧相关。 这会导致 GMEM 负载。 类似地,其他三个表面(此处为 ID 5、7 和 9)具有 Stencil 附件并且不会清除它。
修改代码以从帧缓冲区中明确清除 Stencil 内容后,您可以在 Trace Capture 模式下验证结果,该模式不再显示 GMEM 加载深度 Stencil 轨迹:
在这种情况下,渲染时间缩短了约 9%。
有关 GMEM 负载(尤其是在扩展现实应用中)的更多信息,请参阅 QDN 博客文章 Profiling VR Apps for Better Performance。