帧步调

Android 帧步调库(也称为 Swappy)是 Android Game SDK 的一部分。它可以帮助 OpenGLVulkan 游戏在 Android 上实现流畅渲染和正确的帧步调。

帧步调是将游戏的逻辑和渲染循环与操作系统的显示子系统和底层显示硬件同步。Android 显示子系统旨在避免某些视觉伪影,例如画面撕裂。显示子系统通过执行以下操作来避免画面撕裂:

  • 在内部缓冲过去的帧
  • 检测到延迟帧提交
  • 检测到延迟帧时继续显示当前帧

不一致的帧显示时间是由于游戏的渲染循环以不同于本地显示硬件支持的速率运行而引起的。当游戏的渲染循环对于底层显示硬件运行速度过慢时,就会出现问题,从而导致显示时间不一致。例如,当以 30 fps 运行的游戏尝试在原生支持 60 fps 的设备上渲染时,游戏的渲染循环会导致重复帧在屏幕上额外停留 16 毫秒。这种断开连接会在帧时间中产生显着的不一致,例如 33 毫秒、16 毫秒、49 毫秒等等。过度复杂的场景会进一步加剧这个问题,因为它们会导致错过帧的发生。

帧步调库执行以下任务:

  • 补偿由于短游戏帧导致的卡顿。
  • 对于导致卡顿和延迟的长帧,使用同步栅栏。
    • 将等待注入到应用中。这些允许显示管道赶上进度,而不是允许反向压力累积。
    • 使用同步栅栏(EGL_KHR_fence_syncVkFence)。
  • 如果您的设备支持多种刷新率,则选择刷新率以提供灵活性和流畅的显示效果。
  • 提供用于调试和分析的统计信息,使用帧统计信息

要了解如何根据您的需求配置库以在不同模式下运行,请参阅支持的运行模式

要使用 OpenGL 渲染器或 Vulkan 渲染器来实现,请参阅

要了解更多信息,请参阅实现适当的帧步调

每秒帧数限制干预

每秒帧数 (FPS) 限制干预使游戏能够仅使用平台侧更改以适当的 FPS 步调运行,而无需开发者执行任何操作。

FPS 限制干预的实现使用以下组件

GameManagerService

GameManagerService 组件维护游戏模式和游戏干预的所有用户和游戏信息。FPS 信息与诸如分辨率缩小系数之类的其他干预信息一起存储在 GameManagerService 中,在每个用户配置文件的 <PACKAGE_NAME, Interventions> 映射中。当游戏模式更改或干预更新时,会访问 FPS 信息。UID 对于每个 PACKAGE_NAME 和用户都是唯一的,并且可以进一步转换为 <UID, Frame Rate> 对以发送到 SurfaceFlinger。

SurfaceFlinger

SurfaceFlinger 组件已经支持限制应用程序的 FPS,只要帧速率是显示刷新率的约数即可。在垂直同步事件中,SurfaceFlinger 通过验证垂直同步时间戳是否与应用程序的帧速率同步来检查垂直同步对于受限应用程序的有效性。如果帧速率与垂直同步不同步,则 SurfaceFlinger 会保持帧,直到帧速率和垂直同步同步为止。

下图描述了 GameManagerService 和 SurfaceFlinger 之间的交互

Interaction between the GameManagerService and the SurfaceFlinger

图 1. GameServiceManager 和 SurfaceFlinger 之间的交互

SurfaceFinger 维护一个 <UID, Frame Rate> 对映射,以设置新的帧速率限制优先级。UID 在用户和游戏之间是唯一的,因此单个设备上的每个用户都可以在同一游戏上具有不同的帧速率设置。为了限制游戏的帧速率,GameServiceManager 调用 SurfaceFlinger 以覆盖 UID 的帧速率。使用此机制,每当游戏模式更改或干预更新时,SurfaceFlinger 都会更新映射。SurfaceFlinger 通过相应地锁定缓冲区来处理 FPS 更改。

要了解有关 FPS 限制的更多信息,请参阅FPS 限制简介