自 2025 年 3 月 27 日起,我们建议您使用 android-latest-release
而非 aosp-main
构建 AOSP 并为其做出贡献。如需了解详情,请参阅 AOSP 的变更。
Frame pacing
使用集合让一切井井有条
根据您的偏好保存内容并对其进行分类。
Android Frame Pacing 库(也称为 Swappy)是 Android Game SDK 的一部分。它可帮助 OpenGL 和 Vulkan 游戏在 Android 上实现流畅的渲染和正确的帧同步。
帧同步是指游戏的逻辑和渲染循环与操作系统的显示子系统和底层显示硬件之间的同步。Android 显示子系统旨在避免某些视觉伪影,例如画面撕裂。显示子系统可通过执行以下操作避免画面撕裂:
- 在内部缓冲之前的帧
- 检测延迟帧的提交情况
- 当检测到延迟帧时继续显示当前帧
帧展示时间不一致是因为游戏渲染循环的运行速率与本机显示硬件支持的速率不同。如果底层显示硬件的游戏渲染循环运行速度过慢,会产生问题,导致展示时间不一致。例如,当运行速度为 30 FPS 的游戏尝试在原生支持 60 FPS 的设备上渲染时,游戏的渲染循环会导致同一帧在屏幕上又重复显示 16 毫秒。这种类型的中断会导致帧时间严重不一致,例如帧时间可能为 33 ms、16 ms、49 ms 等。过于复杂的场景会让该问题更复杂,因为它们会导致丢帧。
Frame Pacing 库可执行以下任务:
- 补偿由于游戏帧较短而出现的卡顿现象。
- 对导致卡顿和延迟的长帧使用同步栅栏。
- 如果设备支持多个刷新频率,会选择其中一个以便提供灵活流畅的呈现效果。
- 基于帧统计信息提供用于调试和性能分析的统计信息。
如需了解如何根据需求将库配置为以不同模式运行,请参阅支持的操作模式。
如需使用 OpenGL 渲染程序或 Vulkan 渲染程序实现,请参阅以下文章:
如需了解详情,请参阅实现适当的帧同步。
每秒帧数节流干预
借助每秒帧数 (FPS) 节流干预,游戏只需使用平台端更改即可保持适当的 FPS 速度,而无需开发者执行任何操作。
FPS 节流干预的实现使用以下组件:
GameManagerService
GameManagerService 组件会保留每位用户和每个游戏的游戏模式和游戏干预信息。FPS 信息存储在 GameManagerService 中,并在每个用户个人资料的 <PACKAGE_NAME, Interventions>
映射中存储其他干预信息(例如分辨率缩放系数)。
当游戏模式更改或干预更新时,可以访问 FPS 信息。UID
对于每个 PACKAGE_NAME
和用户都是唯一的,可以进一步转换为 <UID, Frame Rate>
对以发送到 SurfaceFlinger。
SurfaceFlinger
SurfaceFlinger 组件现已支持对应用的 FPS 进行节流,但前提是帧速率必须是显示刷新率的除数。
在发生 vsync 的情况下,SurfaceFlinger 会验证 vsync 时间戳是否与应用的帧速率处于同一相位,以检查受到节流的应用的 vsync 有效性。如果帧速率未与 vsync 处于同一相位,则 SurfaceFlinger 会保持该帧,直到帧速率和 vsync 处于同相位。
下图介绍了 GameManagerService 与 SurfaceFlinger 之间的交互:
图 1. GameServiceManager 和 SurfaceFlinger 之间的交互
SurfaceFinger 会维护一个 <UID, Frame Rate>
对映射,以设置新的帧速率节流优先级。UID
在用户和游戏之间是唯一的,因此同一台设备上的每位用户都可以对同一游戏采用不同的帧速率设置。为了对游戏的帧速率进行节流,GameServiceManager 会调用 SurfaceFlinger 来替换 UID 的帧速率。借助此机制,SurfaceFlinger 会在游戏模式更改或干预更新时更新映射。SurfaceFlinger 通过相应地锁定缓冲区来处理 FPS 更改。
如需详细了解 FPS 节流,请参阅 FPS 节流简介。
本页面上的内容和代码示例受内容许可部分所述许可的限制。Java 和 OpenJDK 是 Oracle 和/或其关联公司的注册商标。
最后更新时间 (UTC):2025-03-06。
[[["易于理解","easyToUnderstand","thumb-up"],["解决了我的问题","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["没有我需要的信息","missingTheInformationINeed","thumb-down"],["太复杂/步骤太多","tooComplicatedTooManySteps","thumb-down"],["内容需要更新","outOfDate","thumb-down"],["翻译问题","translationIssue","thumb-down"],["示例/代码问题","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["最后更新时间 (UTC):2025-03-06。"],[],[],null,["# Frame pacing\n\nThe Android Frame Pacing library, also known as Swappy, is part of the [Android Game SDK](https://android.googlesource.com/platform/frameworks/opt/gamesdk/). It helps [OpenGL](/docs/core/graphics/arch-egl-opengl) and [Vulkan](/docs/core/graphics/arch-vulkan) games achieve smooth rendering\nand correct frame pacing on Android.\n\nFrame pacing is the synchronization of a game's logic and rendering loop with\nan OS's display subsystem and underlying display hardware. The Android display\nsubsystem was designed to avoid certain visual artifacts, such as tearing. The\ndisplay subsystem avoids tearing by doing the following:\n\n- Buffering past frames internally\n- Detecting late frame submissions\n- Continuing to display the current frame when a late frame is detected\n\nInconsistent frame display times are caused by a game's render loop running at\na different rate than what the native display hardware supports. Problems arise\nwhen a game's render loop runs too slowly for the underlying display hardware,\nleading to inconsistent display times. For example, when a game running at\n30 fps attempts to render on a device that natively supports 60 fps,\nthe game's render loop causes a repeated frame to remain on the screen for an\nextra 16 ms. This type of disconnect creates substantial inconsistencies in frame times\nsuch as 33 ms, 16 ms, and 49 ms. Overly complex scenes further compound\nthis problem because they cause missed frames to occur.\n\nThe Frame Pacing library performs these tasks:\n\n- Compensates for stuttering due to short game frames.\n - Adds presentation timestamps so that frames are presented on time, not early.\n - Uses presentation timestamp extensions [`EGL_ANDROID_presentation_time`](https://www.khronos.org/registry/EGL/extensions/ANDROID/EGL_ANDROID_presentation_time.txt) and [`VK_GOOGLE_display_timing`](https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/VK_GOOGLE_display_timing.html).\n- Uses sync fences for long frames that lead to stuttering and latency.\n - Injects waits into the app. These allow the display pipeline to catch up, rather than allowing back pressure to build up.\n - Uses sync fences ([`EGL_KHR_fence_sync`](https://www.khronos.org/registry/EGL/extensions/KHR/EGL_KHR_fence_sync.txt) and [`VkFence`](https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/VkFence.html)).\n- Chooses a refresh rate to provide flexibility and a smooth presentation, if your device supports multiple refresh rates.\n- Provides stats for debugging and profiling using [frame\n stats](https://developer.android.com/games/sdk/frame-pacing/#frame_stats).\n\nTo learn how to configure the library to operate in different modes according\nto what you need, see [Supported operating modes](https://developer.android.com/games/sdk/frame-pacing/#supported_operating_modes).\n\nTo implement using OpenGL renderer or Vulkan renderer, see:\n\n- [Integrate Android Frame Pacing into your OpenGL renderer](https://developer.android.com//games/sdk/frame-pacing/opengl/)\n- [Integrate Android Frame Pacing into your Vulkan renderer](https://developer.android.com/games/sdk/frame-pacing/vulkan/)\n\nTo read more, see [Frame Pacing library](https://developer.android.com/games/sdk/frame-pacing/).\n\nFrames per second throttling intervention\n-----------------------------------------\n\nFrames per second (FPS) throttling intervention enables games to pace at an appropriate FPS\nusing only platform side\nchanges and without requiring any action on the developers' part.\n\nThe implementation of the FPS throttling intervention uses the following components.\n\n#### GameManagerService\n\nThe [GameManagerService](https://cs.android.com/android/platform/superproject/+/android-latest-release:frameworks/base/services/core/java/com/android/server/app/GameManagerService.java) component maintains all per-user and\nper-game information of game mode and game intervention. The FPS information is stored in the\nGameManagerService with other intervention information, such as the resolution downscaling factor,\nin a `\u003cPACKAGE_NAME, Interventions\u003e` mapping for each user profile.\nThe FPS information is accessed when the game mode is changed or the intervention is updated. A\n`UID` is unique to each `PACKAGE_NAME` and user, and can further be translated\ninto a `\u003cUID, Frame Rate\u003e` pair to send to the SurfaceFlinger.\n\n#### SurfaceFlinger\n\n[SurfaceFlinger](/docs/core/graphics/surfaceflinger-windowmanager) component already supports\nthrottling the FPS of an application as long as the frame rate is a divisor of the display refresh rate.\nIn the event of a VSync, the SurfaceFlinger checks the validity of the VSync for the throttled\napplication by verifying whether the VSync timestamp is in phase with the frame rate of the\napplication. If the frame rate is not in phase with the VSync, then the SurfaceFlinger holds the\nframe until the frame rate and VSync are in phase.\n\nThe following figure describes the interaction between the GameManagerService and the SurfaceFlinger:\n\n**Figure 1.** Interaction between the GameServiceManager and SurfaceFlinger.\n\nThe SurfaceFinger maintains a `\u003cUID, Frame Rate\u003e` pair mapping to set a new\nframe rate throttling priority. The `UID` is unique between users and games, so that each\nuser on a single device can have different settings of frame rate on the same game. To throttle the\nframe rate of a game, the GameServiceManager calls the SurfaceFlinger to override the frame rate for\na UID. With this mechanism, the SurfaceFlinger updates the mapping whenever\nthe game mode is changed or the intervention is updated. The SurfaceFlinger handles the FPS change\nby latching buffers accordingly.\n\nTo understand more about FPS throttling, see\n[FPS throttling](https://developer.android.com/games/optimize/adpf/gamemode/fps-throttling)."]]