游戏开发者教程- Android


1 了解并解决图形内存负载问题

由于移动 GPU 的硬件条件不同,某些在 PC 和游戏机等平台上运行良好的编程技术可能无法很好地移植到移动平台上。
图形内存 (GMEM) 负载是影响移动应用程序 GPU 性能的最常见问题之一。在本节中,我们将向你展示如何使用 Snapdragon Profiler 查找应用程序代码中的 GMEM 负载。

1.1 简介

清除或使所有帧缓冲区附件无效。这将指示 GPU 不要将系统内存中的切片数据加载到 GMEM 中。

1.2 什么是图形内存负载(未解决)?

Qualcomm® Adreno™ GPU 的平铺架构管道包含渲染通道。每个图块都会在渲染过程中渲染到 GMEM 中。按照驱动程序的正常行为,之前的帧缓冲区数据从主内存加载到每个图块的 GMEM 中,即发生 GMEM 加载(或未解析)。

1.3 为什么图形内存负载高?

这个问题是因为每个GMEM负载都会减慢处理速度。如果帧缓冲区的内容被清除或无效,驱动程序可以在GMEM中清除该tile。虽然这涉及到额外的图形调用及其相关的开销,但它比为每个渲染的箱子将帧缓冲区加载回GMEM的开销要小。
造成 GMEM 负载的两个主要原因是:

  • 对驱动程序的不正确提示 - 应用程序代码使驱动程序认为需要帧缓冲区的先前内容(通常是通过忽略清除缓冲区)。这归结为一个相对简单的修复,可以在减少渲染时间方面获得良好的回报。它主要适用于 OpenGL ES 编程,因为 Vulkan 显式处理该条件。
  • 算法 — 某些 API(例如 glReadPixels 和 glFlush)强制管道刷新以获得结果。当你恢复绘图帧内容时,执行此中帧操作将导致 GMEM 加载。通常可以通过修改算法来避免 GMEM 负载。

1.4 在 Snapdragon Profiler 中检测图形内存负载

在跟踪捕获模式下使用 Snapdragon Profiler,可以让渲染阶段指标在其自己的轨道中突出显示 GMEM 负载。

在下面的截图中(基于 Adreno SDK 中的景深演示应用程序),红色块显示在渲染四个不同表面(0、16、32 和 48)时正在进行 GMEM 负载(深度模板):

Alt渲染阶段的设置对话框显示,这些 GMEM 负载占用了总渲染时间的大约 9%。

Alt如果不需要 GMEM 负载,则可以节省约 9% 的帧时间。

你可以使用 Snapdragon Profiler 中的 "快照捕捉 "模式来确定 GMEM 负载的原因。

Alt第一个带有 GMEM 负载的表面是第一个绑定的表面 — glBindFrameBuffer。帧缓冲区参数设置为 1: # 选择帧缓冲区对象 1 (FBO 1) 以检查资源。检查器视图显示表面具有颜色、深度和模板的附件。 # glClearColor 和 glClearDepth 调用让 GPU 认为 Stencil 附件的内容与下一帧相关。这会导致 GMEM 负载。同样,其他三个表面(此处 ID 5、7 和 9)具有模板附件,并且不清除它。

修改代码以明确清除帧缓冲区中的模版内容后,可以在跟踪捕获模式下验证结果,该模式不再显示 GMEM 加载深度模版轨迹:
Alt在这种情况下,渲染时间缩短了大约9%。

有关 GMEM 负载(尤其是扩展现实应用程序)的更多信息,请参阅 QDN 博客文章分析 VR 应用程序以获得更好的性能

2 Qualcomm True HDR

2.1 简介

HDR 显示器在 PC 和电视领域已经存在很长时间了。在移动端,2018年出现的OLED屏幕开始支持更高的动态范围和更宽的色域。为了更好地利用屏幕的广色域和高动态范围,高通推出了True HDR游戏功能。

Ture HDR 游戏是 Snapdragon Elite Gaming 的一部分,该产品是在 2018 年夏威夷 Snapdragon 技术峰会上宣布的。该解决方案保留了细节和色彩,以实现最佳的用户游戏体验。这是移动设备上的第一个端到端 HDR 解决方案。真正的 HDR 游戏还充分利用了 Qualcomm Snapdragon 平台 GPU 和 DPU 的能力。游戏引擎/GPU直接输出HDR内容(RGBA1010102格式/BT2020色域)。颜色体积映射由显示处理单元 (DPU) 执行。

本指南旨在介绍和概述 HDR 相关概念,并介绍 Qualcomm True HDR 游戏解决方案。

2.1.1 高动态范围 (HDR)

在下图中,世界的亮度水平为 [0, 无限) 坎德拉每平方米 (cd/m 2)。通过杆和锥的适应,人类可以感知的亮度约为[10 -6, 10 8] cd/m 2 。
Alt

真实世界的亮度水平和人类视觉系统的高级功能,图像取自 [1]_ 高动态范围系统的感知设计

通过比较支持的亮度,显示设备可以分为标准动态范围(SDR)和高动态范围(HDR)。

  • SDR 支持亮度 [0.0002, 100] cd/m 2
  • HDR 支持亮度 [0.00005,1000 或更大] cd/m 2

下图展示了SDR和HDR管道中动态范围和色域的变化。

Alt

SDR 中的内容传输。图片来源:杜比实验室公司

Alt
HDR 内容传输。图片来源:杜比实验室公司

2.1.2 广色域 (WCG)

人眼具有三种类型的颜色传感器,可响应不同的波长范围。颜色由两部分组成:亮度和色度。例如,白色和灰色具有相同的色度和不同的亮度。

国际照明委员会 (CIE) 创建了 CIE 1931 RGB 色彩空间。马蹄形区域代表了人类对不同光波长的反应。
Alt

CIE 1931 色彩空间

色域是特定的、完整的颜色子集。它通常被称为显示设备上可用的整个颜色范围。下图显示了各种标准的色域。

Alt

BT.709, DCI-P3, BT.2020

  • BT.709,高清晰度电视 (HDTV) 标准
  • DCI-P3,用于电影院演示和 UHD 内容的中间色域
  • BT.2020,超高清电视(UHDTV)标准

比 BT.709 范围更大的色域,例如 BT.2020,通常称为宽色域 (WCG)。

2.1.3 色量

亮度和色域定义了颜色量。更高的动态范围和更宽的色域意味着更大的色量。

Alt

BT.2020色域和BT.709色域的颜色量。图片来源:索尼

2.1.4 显示技术

显示技术不断发展以增加位宽、色域和屏幕亮度。

  • 最大位宽支持包括 6、8、10、12 位。
  • 最大亮度(亮度)支持包括 100 尼特、500 尼特和 1000 尼特。
  • 色域支持包括 BT.709、DCI-P3 和 BT.2020。

Alt

显示设备支持的比特、亮度和色域的演变

2.1.5 Light-to-display概述

Alt

从环境光子到显示光子

当使用相机拍摄照片并查看时,会发生以下情况:

  • 摄像机使用光电传输函数 (OETF) 将光转换为视频信号。
  • 显示器使用相反的功能,即电光传输功能 (EOTF) 将视频信号转换为光信号。

对于 SDR,使用伽玛。对于 HDR,使用感知量化 (ST-2084) 或混合对数伽玛 (BBC / NHK)。对于 ST-2084,如下:

Alt

SMPTE ST 2084 (PQ)

Alt
SMPTE ST 2084 PQ EOTF(PQ)

2.2 HDR10

HDR10 是一个开放标准(于 2015 年 8 月 27 日公布)。本标准由下列规范组成:

  • 位深度:10 位
  • 颜色表示:ITU-R BT.2020
    • 色度
  • 电光传递函数 (EOTF):SMPTE ST 2084
    • 将非线性信号值映射到显示光中
  • 静态元数据:SMPTE ST 2086
    • SMPTE ST2086 是“主显示颜色量”元数据,用于描述用于生成内容的显示器的功能。这包括:
      • 原色的 CIE(x,y) 色度坐标
      • 白点的 CIE(x,y) 色度坐标
      • 最小和最大亮度
      • 其他如 MaxFALL(最大帧平均光照级别)和 MaxCLL(最大内容光照级别)静态值

笔记:
应用颜色体积映射时,参考显示器和内容的亮度和色度属性必须传递到显示器。这些属性由 SMPTE ST 2086 标准中定义的静态元数据字段表示。

2.2.1 传统游戏 HDR

在HDR与SDR图像的对比中,传统的HDR图像具有更令人信服的视觉效果。

Alt

sdr 图像(左)和传统 HDR 图像(右),图像取自 Unreal

Alt

传统 HDR 管道

传统的游戏 HDR 流程分为以下步骤:

  1. 渲染场景:场景以 HDR 格式在 Render-Targets 上渲染,例如 RGBA16、R11G11B10、R10G10B10A2。
  2. 后期处理:光晕、晕影、颗粒抖动、运动模糊等。
  3. 颜色分级:对比度、饱和度和伽玛、增益等。
  4. ToneMapping:将动态范围数据映射到标准范围数据 (RGBA8888/sRGB)。传统的映射曲线有很多种:
    Alt

2.3 True HDR

True HDR 图像具有更高的对比度。高光和阴影区域保留了更多细节。 Qualcomm True HDR 游戏兼容 HDR10 标准。事实上,显示处理单元 (DPU) 期望 HDR10 数据输入。

Alt

传统 HDR 图像(上)、True HDR 图像(下)

2.3.1 True HDR管道

HDR 游戏内容是在具有更高动态范围和更宽色域的参考显示器上生成的。渲染的场景在后处理阶段映射到True HDR支持的动态范围和色彩空间,并通过元数据通知显示。

Alt

游戏 True HDR 管道的工作流程

下面提供了 True HDR 管道及其工作原理的详细概述:

  • HDR 内容:在具有大色量(更高的动态范围和更宽的色域)的参考显示器上生成的游戏内容。
  • 场景参考图像:以 HDR 内容作为输入,采用基于物理的渲染 (PBR) 等逼真的渲染方法,生成具有适当曝光、丰富的高光和阴影的良好 HDR 场景参考图像。
  • 后期处理、调色: 与传统游戏 HDR 相同。
  • GamutMap 和 Tonemapper:将 RenderedScene 的动态范围和色彩空间映射到 True HDR 支持的动态范围和色彩空间。
  • UIToneMapper:将 UI 渲染数据映射到 HDR。
  • 添加比例因子:向 UI 添加比例因子以与主渲染场景相匹配。
  • 合成:混合场景 HDR 和 UI HDR 输入。如果游戏依赖大量透明 UI,那么与直接将 UI 渲染到后台缓冲区相比,在渲染目标中渲染整个 UI,然后与后台缓冲区混合会更容易。
  • ST-2084-PQ(OETF):True HDR 需要后缓冲区接收的数据是 ST-2084-PQEncoded。因此,后备缓冲区将由 ST-2084-PQ 进行编码,并将编码值映射到 [0.0,1.0] 范围。
  • **EOTF/Tonemapping/GamutMapping:**由 Qualcomm DPU 处理。
    • ST-2084-PQ(EOTF): ST-2084-PQ(OETF)的逆变式。
    • 色调映射:将 EOTF 的输出映射到屏幕使用的实际色彩空间和实际动态范围。
    • GamutMaping:将一种颜色空间映射到另一种颜色空间。通常的方法是线性拉伸或压缩。 HDR10标准要求的色彩空间为BT2020,但实际屏幕无法满足这一要求。 Qualcomm DPU 将执行色域转换。

2.3.2 Academy 颜色编码系统 (ACES) 色调映射

即使使用 HDR 屏幕,支持的动态范围也是有限的。场景参考图像可以生成非常高动态范围的图像。 SceneToneMapper 会将输入 HDR 场景(高达 10000 尼特)映射到 True HDR 场景(1000 尼特)。 UIToneMapper 会将 UI 数据映射到 True HDR 数据。

Academy 颜色编码系统 (ACES) 经常在游戏中使用。

2.3.2 ACES 管道

ACES中有两个色域:AP0和AP1。

AP0 和 AP1 包含 BT.709 和 BT.2020。这意味着 ACES 可以处理各种类型的色调映射和色域映射。
Alt

ACES使用的BT.2020、BT.709和AP0/AP1色域比较。

Alt
ACES 管道

对于游戏来说,场景渲染后的图像是场景引用图像。在 ACES 管道中,只有三个组件:

  • 颜色分级:ACES 颜色空间中的分级。
  • 参考渲染变换 (RRT):将场景参考色度转换为显示参考色度。颜色空间转换为 ACES 定义的 AP0 颜色空间。动态范围转换为 0-10000 尼特,因此允许渲染到任何输出设备。
    在这里插入图片描述
    图 18 RRT 曲线
  • 输出设备转换 (ODT):将色彩空间转换为 ACES 定义的 AP1 色彩空间。动态范围映射到设备支持的动态范围。输出前将 AP1 转换为设备支持的色彩空间。 ODT有很多种,比如ODT_48nits、ODT_1000nits、ODT_2000nits等。
    在这里插入图片描述
    RRT+ODT_1000 尼特(左)和 RRT+ODT_48 尼特(右)

2.4 True HDR 代码设置

要在 OpenGL ES 中启用 True HDR,必须支持以下扩展:

  • EGL_EXT_gl_colorspace_display_p3
  • EGL_EXT_gl_colorspace_bt2020_pq
  • EGL_EXT_surface_SMPTE2086_metadata

笔记:
适用于 Android 的 Vulkan Swapchain/WSI 仅支持 VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT。有关如何为 Vulkan 启用此功能的更多信息,请查看 Android 开发人员文档中的使用宽颜色内容增强图形指南。

2.4.1 设置 EGLSurface 格式

将 EGLSurface 格式设置为 R10G10B10A2:

EGLConfig EGLConfigList [1]; int ConfigAttributes [] = {
    EGL_RED_SIZE,10
    EGL_GREEN_SIZE,10
    EGL_BLUE_SIZE,10
    EGL_ALPHA_SIZE,2
    EGL_COLOR_COMPONENT_TYPE_EXT,
EGL_COLOR_COMPONENT_TYPE_FIXED_EXT, EGL_NONE};

eglChooseConfig (eglDisplay,ConfigAttributes,EGLConfigList,1, eglNumConfigs);

2.4.2 设置色彩空间

将eglWindowSurface的颜色空间设置为EGL_GL_COLORSPACE_BT2020_PQ_EXT。

EGLint attribs[] = {EGL_GL_COLORSPACE_KHR,EGL_GL_COLORSPACE_BT2020_PQ_EXT,EGL_NONE };
EGLSurface eglSurface=eglCreateWidowSurface(eglDisplay,eglConfigParam, InWindow, attribs);

2.4.3 设置元数据

设置eglSurface的元数据属性。

EGLint SurfaceAttribs [] = {
EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT,       EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT,
    EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT,
    EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT,
    EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT,
    EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT,
    EGL_SMPTE2086_WHITE_POINT_X_EXT,
    EGL_SMPTE2086_WHITE_POINT_Y_EXT,
    EGL_SMPTE2086_MAX_LUMINANCE_EXT,
    EGL_SMPTE2086_MIN_LUMINANCE_EXT
};
static const DisplayChromacities DisplayChromacityList [] = { {{0.70800f, 0.29200f, 0.17000f, 0.79700f, 0.13100f, 0.04600f, 0.31270f, 0.32900f}}, // DG_Rec2020 };
for (uint32_t i = 0; i < 8; i++)
{
    eglSurfaceAttrib(PImplData->eglDisplay,eglSurface, SurfaceAttribs[i],EGLint(DisplayChromacityList[0].ChromaVals[i]* EGL_METADATA_SCALING_EXT));
}

2.4.4 获取Android上显示器的亮度

最大平均亮度:
https://developer.android.com/reference/android/view/Display.HdrCapativity.html#getDesired MaxAverageLuminance() 最大亮度:https://developer.android.com/reference/android/view/Display.HdrCapability.html# getDesired MaxLuminance() 最小亮度:https://developer.android.com/reference/android/view/Display.HdrCapability.html#getDesired MinLuminance()

[1]
Kunkel, T & Daly, Scott & Miller, S & Froehlich, Jan. (2016). Perceptual Design for High Dynamic Range Systems. 10.1016/B978-0-08-100412-8.00015-2.

3 识别应用程序瓶颈

3.1 每秒多少帧?

在开始使用 Snapdragon Profiler 之前,你可能已经知道自己存在性能问题。即使你不这样做,也建议检查应用程序当前的整体性能以识别瓶颈。

帧速率是一个理想的起点。游戏通常以每秒 30 或 60 帧 (fps) 的速度运行效果最佳,有时虚拟和扩展现实 (VR/XR) 应用程序的运行速度更高。

其中一个方面是平均帧速率,它衡量应用程序的平均运行速度。另一个方面是帧速率的一致性。即使你的平均值保持接近目标帧速率,偶尔的长帧也可能会错过该目标。用户体验会出现卡顿和故障,并且运动不流畅,因此你的应用程序将从优化中受益。

如果你的应用程序未优化,平均帧速率可能低于你的目标,并且应用程序将无法达到其所需的性能水平。如果你优化了应用程序,则可能会更接近平均值,但帧速率仍然会出现周期性峰值。这些尖峰会阻碍动画,因此你需要通过识别问题并修改代码来平滑这些尖峰。

在这两种情况下,Snapdragon Profiler 都可以直接带你了解应用程序的性能水平(以 fps 为单位)。下面的屏幕截图显示平均(浅蓝色线)为 42.022 fps。
在这里插入图片描述虽然 42 fps 可能足以作为平均值,但范围(蓝线)会周期性地降至 37.322 fps。这表明该应用程序正在丢帧,这会损害性能。

另请注意,应用程序应选择达到其平台 Vsync 速率的除数或倍数的帧速率。由于典型平台具有 60Hz 垂直同步,因此 30Hz 或 60Hz 是唯一可接受的目标。

3.1.1 探索潜在瓶颈

虽然没有任何单一指标可以告诉你性能问题出在哪里以及如何解决这些问题,但 Snapdragon Profiler 可以让你检查数十个指标,以了解你的应用程序如何与硬件交互。

跟踪捕获模式屏幕截图中的部分对应于三个重要的指标:

  • 渲染阶段 – Snapdragon Profiler 中的每个渲染阶段都是一个指标,代表应用程序在 GPU 上的执行情况。每个数据轨道都是指标的子集,轨道数量根据应用程序而变化。在下面的屏幕截图中,绿色、洋红色和紫色条显示各个表面,表面条下方的轨迹代表相关的渲染阶段。

在这里插入图片描述

  • GPU 活动 – 显示 CPU 和 GPU 之间交互的系统指标。
  • CPU 调度(“跟踪内核 - 调度 CPU”)— 一种系统指标,提供应用程序在每个 CPU 核心上的执行情况的概述。你可以查看应用程序的哪些部分在何处运行,以及是否存在调度或线程争用问题。

在这里插入图片描述这些指标可以帮助你探索性能可能受到限制的三个主要领域:GPU、CPU 和垂直同步,或显示器上的垂直同步刷新。

3.1.2 GPU 受限的应用程序

在图形密集型应用程序中,建议从 GPU 开始消除过程。

在 Snapdragon Profiler 的实时视图中,GPU % Utilization 是一个顶级指标。下面的屏幕截图显示利用率在 26-38% 范围内。

在这里插入图片描述将其与以下屏幕截图进行比较,显示利用率在 98-100% 范围内:

在这里插入图片描述后者强烈表明该应用程序受 GPU 限制。

除了实时视图之外,Snapdragon Profiler 中的跟踪捕获模式还提供了另一个参考点。如果应用程序不受 GPU 限制,则可能会出现 GPU 活动的间隙。

在这里插入图片描述如果应用程序受 GPU 限制,则 GPU 执行可能会延迟,并且 GPU 可能会不断渲染表面。

在这里插入图片描述

3.1.3 CPU受限的应用程序

如果应用程序不受 GPU 限制,请确定该应用程序是否受 CPU 限制。

与 GPU 受限应用程序不同,实时视图中的 CPU 利用率并不是 CPU 受限应用程序的可靠指标。

在这里插入图片描述第一个应用程序的平均 CPU 利用率为 16%,第二个应用程序的平均 CPU 利用率为 23%。第一个是 CPU 受限,但它们之间的差异并不像上面的 GPU 受限应用程序那么明显,因此该应用程序可能看起来不受 CPU 受限影响。

受 CPU 限制的应用程序的两个重要标准是它不受 GPU 限制并且平均帧时间超过 16 毫秒。要确定应用程序是否受 CPU 限制,请考虑应用程序和 CPU 的多线程性质。超越 CPU 利用率并检查频率和线程调度等指标也很有帮助。

在下面的跟踪捕获模式屏幕截图中,Sched CPU 6 中的线程似乎成为 CPU 瓶颈:

在这里插入图片描述下一步是更深入地研究该线程,以确定多线程的热点和候选者。采样捕获模式以固定的时间间隔定期对 CPU 程序计数器进行采样,并识别 CPU 热路径。它提供活动的统计表示,包括在每个函数和库中花费的时间。你可以查看代码中的哪些函数占用的执行时间最多。

以下捕获显示了 CPU 上运行的用于渲染布料纹理的函数和函数序列。红色和橙色块表示应用程序代码中的热点。

在这里插入图片描述在本例中,CPU 采样显示 SatisfyConstraints() 是最大的热点,具有 98% 的活动。

为了更深入地研究,Snapdragon Profiler 支持用户标记和 Android NDK 中内置的本机跟踪 API。 Android 开发人员可以使用该 API 将跟踪标记插入应用程序代码中,并在 Snapdragon Profiler 中查看此数据。

在下面的示例中,你可以使用 android/trace.h 来检测 SatisfyConstraints() 调用并将其追溯到主线程,这是一个辅助函数。

在这里插入图片描述渲染帧中的纹理需要每块布料一个函数,该函数根据经过的时间的需要进行滴答。一旦修改应用程序代码以将函数线程化,Snapdragon Profiler 就可以立即显示所有活动的以下包含性、相关性视图。

在这里插入图片描述现在,布料计算是在多个线程中进行的。 CPU 调度中的输出显示更多线程。应用程序不再受 CPU 限制,因此 CPU 等待调度绘制。

该流程是使用 Snapdragon Profiler 识别、诊断和解决性能问题的典型流程。

3.1.4 Vsync受限的应用程序

如果您确定应用程序既不受 CPU 限制,也不受 GPU 限制,则它可能受 Vsync 限制,即,它的运行速度可能与显示硬件所能容纳的速度一样快。在 Snapdragon Profiler 中使用跟踪捕获模式,您可能会看到类似以下内容:

在这里插入图片描述请注意,帧时间约为 16 毫秒(1 秒除以 60 fps),并且在帧末尾附近有一个间隙,在此期间 GPU 和 CPU 都在等待可用表面进行渲染。

虽然许多应用程序的目标是在显示器允许的范围内尽可能快地运行,但即使应用程序受垂直同步限制,并且具有超越更高帧速率的优势,仍然有优化的机会。

移动应用中的大多数问题都归结于功耗和电池寿命。即使您的应用程序可以在不绑定 CPU 和 GPU 的情况下满足目标帧速率,您可能仍然希望优化您的代码。如果可以对其进行修改以使用更少的功耗并在更低的温度下运行,则应用程序将在完成更少的工作的同时满足目标帧速率。它还可能在低端设备上提供更好的性能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值