Open31

[Unity]フレームレートに影響する要素まとめ

amamagiamamagi

フレームレートに影響する要素

  • プロジェクト設定
    • Application.targetFrameRate
    • QualitySettings.vSyncCount
  • 実行プラットフォーム
  • デバイス設定
    • リフレッシュレート
    • 垂直同期
  • ワークロードと計算能力
    • CPU時間
    • GPU時間
amamagiamamagi

QualitySettings.vSyncCount

https://docs.unity3d.com/ja/2022.3/ScriptReference/QualitySettings-vSyncCount.html

  • 垂直同期(VSync)の設定
    • ディスプレイの更新タイミングをディスプレイの垂直同期タイミングに制約する
    • ティアリング(画面が引き裂かれたように見える現象)を抑制する
  • デフォルトは0(オフ)
  • 1以上にするとオン
  • オンにするとApplication.targetFrameRateは無視される
  • モニターのリフレッシュレートをvSyncCountで割った数値になるようフレームレートが調整される
    • 例: モニターが144Hzの場合
      • vSyncCount = 1 : 144fps
      • vSyncCount = 2 : 72fps
      • vSyncCount = 3 : 48fps
      • vSyncCount = 4 : 36fps
amamagiamamagi

実行プラットフォーム: Editor

  • vSyncCountは無視される
  • GameViewで垂直同期を有効にするには VSync(Game view only)を有効にする
amamagiamamagi

実行プラットフォーム: Android

  • vSyncCountは無視される

https://docs.unity3d.com/ScriptReference/QualitySettings-vSyncCount.html

Mobile platforms ignore vSyncCount. On mobile devices, when a frame is ready, it displays the next time the screen refreshes. You can use Application.targetFrameRate to control the frame rate on mobile platforms.

Optimized Frame Pacing

https://docs.unity3d.com/Manual/class-PlayerSettingsAndroid.html

amamagiamamagi

デバイス設定: リフレッシュレート

  • ディスプレイの更新頻度
  • アプリケーション側で制御できない要素の一つ
  • OSの設定、GPUのコントロールパネル、VRデバイスの設定などから指定する
  • 低消費電力設定で低い値に設定されることもある
  • 垂直同期がオンの場合、アプリケーションのフレームレートがディスプレイのリフレッシュレートと同期する
amamagiamamagi

デバイス設定: 垂直同期

  • アプリケーション側で制御できない要素の一つ
  • WindowsPCではGPUのコントロールパネルから垂直同期を無効化できる
  • アプリケーションで垂直同期を有効にしていても、デバイス設定で無効にしてある場合はデバイス設定が優先され垂直同期しない

https://zenn.dev/su_do/articles/ab48464ccb264e

amamagiamamagi

ワークロードと計算能力

  • 1フレームを描画するには、シーンを構築してレンダリングする計算時間が最低限必要
    • 計算時間はワークロードと実行デバイスの計算能力に依存する
  • 目標フレームレート内にワークロードの計算時間が終了しなければ処理落ちによりフレームレートは低くなる
amamagiamamagi

🤔垂直同期の処理落ち

  • 垂直同期がオンの場合、目標フレームレートに達しなければ次の垂直同期を待ち、フレームレートが目標の整数分の1になる?
    • 目標が60fpsの場合、30fps(1/2), 20fps(1/3)...
    • SteamVRで発生した
    • 一方WindowsやMacのデスクトップアプリでは再現しなかった
    • どのような条件で発生するのか?
    • プラットフォームごとのフレームバッファの実装による?
      • 仮説: Windows/Macではダブル/トリプルバッファリングによって垂直同期を待たずフレームバッファの更新を行えるため、フレームレートが垂直同期タイミングに制約されない
      • 追記: SteamVRでは処理落ちが続いた場合にアプリケーションのフレームレートを強制的に下げつつディスプレイには倍のフレームレートで映像を出力する仕組み(Motion Smoothing(後述))がある。現象が発生した際、Unityのフレームレートに対してSteamVRのパフォーマンスグラフのフレームレートは十分に高かったことから、SteamVRでFPSが半減したのはフレームバッファの実装都合によるものでなく、コンポジター(後述)よる意図的な制御だと思われる。

資料

https://yosshin4004.github.io/memo/vsync/index.html

https://silight.hatenablog.jp/entry/2015/01/14/150016

amamagiamamagi

🤔ワークロードの分析

  • ワークロードは以下の大まかに3つの処理に分解できる
    • MainThread処理: シーンの構築
    • RenderThread処理: GPUへの描画命令発行
    • GPU処理: レンダリング
  • それぞれの処理はパイプラインとして実行され、各処理の並列数は1
  • 各処理の並列数は1なのでいずれかの時間が伸びると待ち時間が発生する
  • 待ち時間はProfilerで観測できる
    • Gfx.WaitForPresentationOnGfxThread (RenderThread待ち)
    • WaitForCommandFromMainThread (MainThread待ち)
    • GfxDeviceD3D11.WaitForLastPresent (GPU待ち)
    • など

資料

https://light11.hatenadiary.com/entry/2021/06/03/204715

https://discussions.unity.com/t/what-exactly-is-happening-in-the-renderthread/818047/2

amamagiamamagi

🤔CPU/GPUのワークロードバランス

  • CPU時間とGPU時間に差がある場合、差を縮めることで待ち時間を減らしてフレームレートを改善することができる
  • CPU時間が不足してGPU時間に余裕がある場合、GPUへのワークロードの移行ができないかを検討すると良さそう
  • ComputeShaderやGPU Resident Drawerなどの手法がある

https://discussions.unity.com/t/gpu-driven-rendering-in-unity/930675

amamagiamamagi
  • 本記事の検証環境はUnity6000.0.12f1, URP3D
  • 疑問を含むトピックには🤔を付けた
  • 調査にあたってはPC、モバイル、XRを対象のプラットフォームとした
amamagiamamagi

XR資料

https://docs.unity3d.com/ja/current/Manual/VRFrameTiming.html

アプリケーションが GPU バインドされている場合、Unity プロファイラーは 1 フレームの時間を超えた XR.WaitForGPU をミリ秒単位で表示します。

アプリケーションが CPU にバインドされている場合、フレームは指定されたフレーム時間より長くかかりますが、Unity プロファイラーは XR.WaitForGPU を 1 フレームより短く表示します。

https://docs.unity3d.com/ja/2020.3/Manual/xrsdk-display.html

https://medium.com/@xavidevsama/optimizing-vr-performance-in-unity-techniques-and-best-practices-b9c6a5d539f3

In summary, choosing “Don’t Sync” for VR games can lead to a more responsive and immersive experience by minimizing input lag, maximizing frame rates, and avoiding the performance penalties associated with VSync. While it may introduce some screen tearing, the benefits of smoother gameplay and quicker response times generally outweigh this drawback. For VR, where maintaining a high and stable frame rate is paramount to prevent motion sickness and enhance realism.

amamagiamamagi

🤔可変リフレッシュレート(VRR)

  • ディスプレイのリフレッシュレートを状況に応じてシームレスに変化させる技術のこと
    • ディスプレイがサポートする範囲のリフレッシュレートであれば、アプリケーションの描画したいタイミングで画面の更新ができる
  • 垂直同期を取らないとアプリケーションとディスプレイのフレームレートが一致せずティアリングが発生し、垂直同期をとると処理落ち時にスタッターや遅延が発生する
    • VRRならアプリケーションとディスプレイのフレームレートが一致しない時のティアリングと処理落ち時のスタッター・遅延を解消できる
  • 現行のVRR規格
    • AMD FreeSync
    • Nvidia G-Sync
    • VESA Adaptive-Sync
    • HDMI 2.1 VRR
    • Apple ProMotion
    • Qualcomm Q-Sync
  • UnityでVRRを利用するには?
    • 特に設定せずともVRRが利用可能な環境なら自動的に利用される
    • Windowsの場合、FullScreenModeがWindowedだとVRRが利用されない場合がある
      • FullScreenExclusiveにするとよい

https://ja.wikipedia.org/wiki/可変リフレッシュレート
https://forums.blurbusters.com/viewtopic.php?t=7158

amamagiamamagi

🤔コンポジター

https://developer.oculus.com/resources/os-compositor/

  • XRでは酔いの抑制が重要
  • 頭を動かしている状況ではレンダリング開始時とディスプレイへの表示の間に頭の位置にズレが生じて酔いを引き起こす
  • 頭の位置を低遅延に反映した映像をディスプレイに表示したいモチベーションがある
  • このモチベーションから、一般にXRではレンダリングしたフレームはコンポジターのフレームバッファに蓄積され、頭の位置を反映した映像に加工してからディスプレイに表示される
  • コンポジターの実装によっては過度な処理落ち時に急激にフレームレートが下がる(半減する)
amamagiamamagi

🤔スワップチェーン

https://learn.microsoft.com/en-us/windows/win32/direct3d9/what-is-a-swap-chain-
https://en.wikipedia.org/wiki/Swap_chain

  • フレームバッファを複数用意し、グラフィックAPIによって書き込まれるバッファ(バックバッファ)とディスプレイ書き換え用のバッファ(フロントバッファ)を分離する
  • 新しいフレームを表示する際は、フレームがレンダリングされたバックバッファをフロントバッファと入れ替える(フリップ/スワップ)
  • レンダリング時間に余裕が生まれて安定したフレームレートが実現できる
amamagiamamagi

🤔 QualitySettings.maxQueuedFrames

https://docs.unity3d.com/ScriptReference/QualitySettings-maxQueuedFrames.html
https://unity.com/ja/blog/engine-platform/fixing-time-deltatime-in-unity-2020-2-for-smoother-gameplay

  • バックバッファのサイズを指定する
  • デフォルトは2
  • 1にすると低遅延を目指せるが、パイプライン化による最適化ができない
  • グラフィックAPIがDX11, DX12, Vulkanの場合に有効な設定
    • Metalでは指定できない?

Currently, maxQueuedFrames is implemented in Direct3D 11, Direct3D 12, and Vulkan graphics APIs only and ignored by other graphics APIs. For information about other graphics APIs and where maxQueuedFrames is implemented, refer to platform-specific documentation.

amamagiamamagi

ダブル・トリプルバッファリング

https://learn.unity.com/tutorial/optimizing-graphics-in-unity#64dc7690edbc2a26d993c1ac

With double buffering (and when VSync is enabled), your application must wait until the next vertical retrace before it starts rendering the next frame. Vertical retraces occur at the vertical refresh rate, typically in the 60–100 Hz range. If supported by the graphics driver, turning off VSync eliminates this delay and provides the highest frame rate. However, it can cause visual artifacts called tearing.
With triple buffering, your application renders a frame in one back buffer (a regular framebuffer). While it is waiting to flip, it starts rendering in the other back buffer. The result is that the frame rate is typically higher than double buffering (and VSync enabled) without any tearing.

  • ダブルバッファリング + VSync
    • アプリケーションは次のフレームをレンダリングする前にディスプレイの垂直同期を待つ必要がある
  • トリプルバッファリング
    • あるバックバッファがフリップを待っている間に、もう一つのバックバッファに書き込むことができる
    • ダブルバッファリングよりフレームレートが高くなる
    • デバイスやグラフィックAPIでサポートされている必要がある
amamagiamamagi

https://cedil.cesa.or.jp/cedil_sessions/view/2897

この事例ではUIを60FPS、3Dを30FPSでレンダリングしている。URPのカスタマイズによって実現。
3Dのレンダリング結果のテクスチャを保持しておき、3Dのレンダリングをスキップするフレームでは保持したテクスチャを参照する仕組み。

amamagiamamagi

アプリスペースワープ (AppSW)

https://developer.oculus.com/documentation/unity/unity-asw/
https://developer.picoxr.com/document/unity/application-spacewarp/

  • Meta Quest/Picoに導入されたCompositor処理
  • アプリケーションのフレームレートに対して倍のフレームレートでレンダリングできる

新しいフレームを合成するためにシステムで使うモーションベクトルバッファと深度バッファを低解像度でレンダリングすることにより半分のレートで(72 FPSに対して36 FPSで)レンダリングし、かつディスプレイ出力は72 FPSとすることができます。

amamagiamamagi

Compositor処理の種類

https://www.uploadvr.com/reprojection-explained/

  • Timewarp
    • ディスプレイ出力の直前に頭の回転に基づいて映像を再投影する技術
    • 映像レイテンシを軽減させるXRの基礎中の基礎技術
  • Asynchronous Timewarp
    • ゲームがフレームレートを維持できないとき、前フレームの映像と最新のトラッキングデータに基づいた中間フレームを生成する
    • 頭の回転が考慮される
    • GPUのフレーム描画が間に合わなかった場合、前のフレームの描画結果を利用して再投影する
    • レンダリングが間に合うかどうかにかかわらず常時処理が行われる
  • Interleaved Reprojection (SteamVR)
    • Asynchronous Timewarpとほぼ同じ
    • 頭の回転が考慮される
    • 処理落ちが一定の期間続くと自動的にアプリケーションのフレームレートを落とし、ディスプレイ出力は同じ描画結果から2フレーム分再投影する
  • Asynchronous Spacewarp (Oculus) / Motion Smoothing (SteamVR)
    • 頭の回転だけでなく頭の位置も考慮した再投影技術
    • 処理落ちが続いた際に発動し、自動的にアプリケーションのフレームレートを落とし、ディスプレイ出力は同じ描画結果から2フレーム分再投影する
  • ASW 2.0 (Oculus)
    • 深度バッファを考慮したAsynchronous Spacewarp
    • 頭の回転と位置も考慮される
    • 処理落ちが続いた際に発動し、自動的にアプリケーションのフレームレートを落とし、ディスプレイ出力は同じ描画結果から2フレーム分再投影する
  • Positional Timewarp (Oculus)
    • 常時動作するAWS2.0
    • 深度バッファ、頭の回転と位置が考慮される

https://developers.meta.com/horizon/blog/asynchronous-timewarp-examined/
https://developers.meta.com/horizon/documentation/unity/os-app-spacewarp

  • AppSW
    • Eyeバッファ、モーションベクトル、深度バッファから未来のフレームを合成する
    • 常時動作しており、単一の入力から2フレーム分生成する
      • アプリケーションのフレームレートを落とすことができて、計算時間の余裕が70%増えるとされる
    • 生成されたフレームはPTWで再投影されてディスプレイに表示される
amamagiamamagi

余談: visionOSのCompositor

https://developer.apple.com/documentation/visionos/understanding-the-visionos-render-pipeline

Maintain a consistent metal rendering frame rate that is equal to the Apple Vision Pro display refresh rate. Use the visualizations in the Display instrument timeline to compare your rendered frame times to the display refresh rate — usually 90Hz on the Apple Vision Pro, but it can be higher under certain environmental conditions.

2024年時点ではvisionOSのCompositor処理にフレームレート向上技術は採用されていなようで、アプリケーションのフレームレートはディスプレイのリフレッシュレート(90Hz)を維持することが求められる。

amamagiamamagi

GPUドライバの技術

https://pc.watch.impress.co.jp/docs/topic/feature/1017166.html

G-SYNC

  • NVIDIAのVRR技術
  • 一般にVRRではアプリケーションのフレームレートがディスプレイの最大リフレッシュレートを超えた場合に垂直同期を取ってティアリングを抑える
  • ティアリングしてでもアプリケーションを高フレームで実行したいユースケースのために、垂直同期しないオプションがある

ちなみにG-SYNCは元々、テアリング発生を抑えるために、ディスプレイの対応リフレッシュレート以上に達した場合、垂直同期を取る仕様であったが、ゲーマーの声を反映し、垂直同期をオフにするオプションも後から加わったという。

FAST SYNC

  • ゲームエンジンを騙して低遅延化する技術
  • まだフリップされていないバックバッファに書き込める、とゲームエンジンに伝えてアプリケーションの待ち時間を減らす
  • アプリケーションのフレームレートがディスプレイのリフレッシュレートを超えるような軽いゲームでは入力遅延を減らすことができる
  • NVIDIAコントロールパネルの 3D設定>垂直同期>高速 で有効になる

これまでバックバッファだったバッファを、フロントバッファに出力したものとして、新たにレンダリングを受け付けるようにした。これによりゲームエンジンからは絶えず新しいバッファがあるとして認識され、垂直同期を待たずして処理を継続できるようにしたわけだ。

amamagiamamagi

低遅延化技術

NVIDIA Reflex

https://game.watch.impress.co.jp/docs/kikaku/1275225.html

SDKを利用してソフトウェアを開発し、NVIDIA Reflexに対応させることで、ゲームはそのレンダーキューを取り除くことができる。これにより、CPUとGPUが待機している時間が減ることになり、トータルでのレイテンシを削減することができるようになるのだ。

https://developer.nvidia.com/performance-rendering-tools/reflex

Activate this mode to align game engine work to complete just-in-time for rendering, eliminating the GPU render queue and reducing CPU back pressure in GPU-bound scenarios.

AMD Anti-Lag

https://www.4gamer.net/games/022/G002212/20240628071/

https://github.com/GPUOpen-LibrariesAndSDKs/AntiLag2-SDK

amamagiamamagi

フレーム生成技術

NVIDIA DLSS

https://www.nvidia.com/ja-jp/geforce/technologies/dlss/

  • フレーム生成、アップスケーリング、AA
  • ゲーム側の対応が必要

AMD FSR

https://www.amd.com/ja/products/graphics/technologies/fidelityfx/super-resolution.html

  • フレーム生成、アップスケーリング
  • ゲーム側の対応が必要

AMD Fluid Motion Frames (AFMF)

https://www.amd.com/ja/products/software/adrenalin/afmf.html

  • フレーム生成
  • ゲーム側の対応が不要
amamagiamamagi

Compositing window manager

https://en.wikipedia.org/wiki/Compositing_window_manager
https://learn.microsoft.com/en-us/windows/win32/dwm/dwm-overview

  • PCでのウィンドウ表示においてはCompositorによって各ウィンドウのオフスクリーンバッファの合成が行われる
  • Screen.fullScreenMode が ExclusiveFullScreen であれば Compositor 処理をスキップできる

https://www.nvidia.com/en-us/geforce/guides/system-latency-optimization-guide/

Turn on Exclusive Fullscreen - If possible, always be in Exclusive Fullscreen mode. This will bypass the windows compositor that adds latency.

amamagiamamagi

SteamVRのMotion Smoothing

https://store.steampowered.com/news/app/250820/view/2898585530113853534

  • 処理落ちを検知すると最後に配信されたフレームから新しいフレームを生成し、カクつきを防ぐ技術

  • SteamVRにサードパーティー製のHMDを接続した場合はMotion Smoothingとは異なる技術が使用される

    • このためSteamVRの設定にMotion Smoothing設定が表示されない

    SteamVRでOculus RiftまたはWindows Mixed Realityヘッドセットを使用している場合、アプリケーションのフレームレートが不足する場合に、それらの基礎となるディスプレイドライバが異なる技術を使用するため、モーションスムージングは有効になりません。

  • 例えばHMDをVirtualDesktop経由でSteamVRに認識させている場合、VirtualDesktopのSynchronous Spacewarpが適用される。

https://steamcommunity.com/app/250820/discussions/0/2251182852569611901/

if you are using virtual desktop, go to your streaming settings menu through your headset, and turn Synchronous Spacewarp (SSW) to Disabled.. saved me so much headache