2025 年 3 月 27 日より、AOSP のビルドとコントリビューションには aosp-main
ではなく android-latest-release
を使用することをおすすめします。詳細については、AOSP の変更をご覧ください。
フレーム ペーシング
コレクションでコンテンツを整理
必要に応じて、コンテンツの保存と分類を行います。
Swappy という名前でも知られる Android Frame Pacing ライブラリは、Android Game SDK の一部です。このライブラリは、OpenGL と Vulkan のゲームが Android でスムーズなレンダリングと正確なフレーム ペーシングを行えるようにサポートします。
フレーム ペーシングとは、ゲームのロジックおよびレンダリング ループを、OS のディスプレイ サブシステムおよび基盤となるディスプレイ ハードウェアと同期させることです。Android ディスプレイ サブシステムは、テアリングなどの特定の視覚的アーティファクトを回避するように設計されています。ディスプレイ サブシステムは次の処理を行って、テアリングを回避します。
- 過去のフレームを内部的にバッファリングする
- 遅延しているフレーム送信を検出する
- 遅延フレームが検出されたときに現在のフレームを表示し続ける
フレームの表示時間の不整合は、ゲームのレンダリング ループがネイティブ ディスプレイ ハードウェアがサポートするものとは異なるレートで実行されることにより発生します。基盤となるディスプレイ ハードウェアに対してゲームのレンダリング ループが遅すぎる場合に問題が発生し、これによって表示時間の不整合が引き起こされます。たとえば 30 FPS で実行されるゲームが、ネイティブに 60 FPS をサポートするデバイスでレンダリングを実行しようとすると、ゲームのレンダリング ループによって、繰り返されるフレームが 16 ミリ秒間余計に画面上に残ります。このタイプの接続解除では、33 ミリ秒、16 ミリ秒、49 ミリ秒などのフレーム時間の間に大きな不整合が生じます。極度に複雑なシーンはフレームの欠落を生じさせるため、この問題をさらに複雑にします。
Frame Pacing ライブラリでは次のタスクを実行します。
- ゲームのフレームが短いため、スタッタリングを補正します。
- スタッタリングとレイテンシを引き起こす長いフレームに同期フェンスを使用します。
- デバイスが複数のリフレッシュ レートをサポートしている場合は、リフレッシュ レートを選択することでより柔軟でスムーズな表示が可能になります。
- フレーム統計情報を使用してデバッグとプロファイリングを行うための統計情報を提供します。
ニーズに応じて異なるモードで動作するようにライブラリを構成する方法については、サポートされている動作モードをご覧ください。
OpenGL レンダラまたは Vulkan レンダラを使用して実装する方法については、以下をご覧ください。
フレーム ペーシングを適切に行うで詳細をご覧ください。
フレーム/秒スロットリング介入
フレーム/秒(FPS)スロットリング介入では、プラットフォーム側の変更のみで、ゲームのペースを適切な FPS に調整できます。デベロッパーが対応する必要はありません。
FPS スロットリング介入の実装で使用するコンポーネントは次のとおりです。
GameManagerService
GameManagerService コンポーネントは、ゲームモードとゲーム介入に関する、ユーザーごとの情報とゲームごとの情報をすべて保持します。FPS 情報は、他の介入情報(解像度のダウンスケーリング ファクタなど)とともに、各ユーザー プロファイルの <PACKAGE_NAME, Interventions>
マッピングで GameManagerService に格納されます。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
はユーザーとゲームの間で一意であるため、1 つのデバイスのユーザーごとに、同じゲームで異なるフレームレートを設定できます。ゲームのフレームレートをスロットリングするために、GameServiceManager は SurfaceFlinger を呼び出して UID のフレームレートをオーバーライドします。このメカニズムにより、SurfaceFlinger はゲームモードが変更されるか介入が更新されるたびにマッピングを更新します。それに応じて SurfaceFlinger はバッファをラッチすることで FPS の変更を処理します。
FPS スロットリングについて詳しくは、FPS スロットリングの概要をご覧ください。
このページのコンテンツやコードサンプルは、コンテンツ ライセンスに記載のライセンスに従います。Java および OpenJDK は Oracle および関連会社の商標または登録商標です。
最終更新日 2025-03-02 UTC。
[[["わかりやすい","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"]],["最終更新日 2025-03-02 UTC。"],[],[],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)."]]