[MR Dev Tips #10] HoloLens の フレームレート と パフォーマンス最適化 の基礎

# はじめに
今回は Mixed Reality アプリケーションのパフォーマンスの最適化について調査した内容をまとめます。具体的な改善方法は後日の記事でまとめる予定です。本記事では、HoloLens アプリケーションのパフォーマンスで考慮すべき内容をサクッとご紹介できればと思います。

# フレームレートとは？
**アプリケーションが1秒間にイメージをレンダリングできる回数** です。フレームレートは、デバイスで表示されるホログラムを安定させるための一番重要な部分となります。ホログラムを World で安定させるためには、ユーザーに提示される各画像の正しい場所にホログラムが描画されている必要があります。HoloLens のディスプレイは、1秒あたり 240回 更新され、新しくレンダリングされたイメージごとに4つの個別の色フィールドが表示され、ユーザー体験は 60 FPS となります。最大限のユーザー体験 (UX) を提供するには、アプリケーションのフレームレートを 60FPS で維持し続ける必要があります。これは 16ミリ秒 (フレームタイム) ごとにオペレーティングシステムに新しい画像を提供していることに相当します。

https://learn.microsoft.com/ja-jp/windows/mixed-reality/develop/advanced-concepts/app-quality-criteria-overview

# Mixed Reality アプリにおけるパフォーマンスの重要性
Mixed Reality アプリケーションが最適なフレームレートで動作しないと、ユーザー体験の品質が大きく低下してしまいます。ホログラムの表示が不安定になったり、ヘッドトラッキングやハンドトラッキング (環境認識) の精度が下がる等、ユーザー体験の品質に大きく影響を与えるからです。

HoloLens 2 や Windows Mixed Reality デバイスでは、各プラットフォームごとにターゲットとなるフレームレート (ターゲットフレームレート) が設定されています。

| プラットフォーム | ターゲットフレームレート |
| --- | --- |
| HoloLens | 60 FPS |
| Windows Mixed Reality PC | 60 FPS |

 目標フレームレートを達成するためには、まず Mixed Reality アプリケーションの処理の流れ、パフォーマンスのボトルネックを理解する必要があります。

# パフォーマンスのボトルネックを理解する
アプリケーションのフレームレートのパフォーマンスが低い場合、まず最初に検討すべきことは、アプリケーションのどの部分に計算負荷がかかっているかを分析して特定することです。シーンのレンダリング作業は、CPU と GPU 2つの主要なプロセッサが担っており、それぞれが Mixed Reality のあらゆる処理を行っています。

**ボトルネックが発生する可能性が高い箇所** は、以下の3つです。

| ボトルネックとなりうる箇所 | 概要 |
| --- | --- |
| **1.アプリスレッド (CPU)** | 入力、アニメーション、物理演算、その他 (アプリロジックの処理など)、アプリケーションのロジック処理を行います。 |
| **2.レンダースレッド (CPU to GPU)** | ドロ―コールを GPU に送信する役割を担います。このスレッドは、アプリケーションで Cube や Sphere など、オブジェクトをレンダリングをする際に、その操作を行うための要求を GPU へ送信します。 |
| **3.GPU** | 一般的には、3Dデータ (モデル、テクスチャなど) をピクセルに変換するグラフィックパイプラインの処理を行います。最終的には、デバイスのディスプレイに表示する 2D 画像を生成します。| 

> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/08d2fc74-ebc9-c378-c923-09767eda0f0f.png)
>
> [Microsoft Docs | パフォーマンスのボトルネックを理解する](https://learn.microsoft.com/ja-jp/windows/mixed-reality/develop/advanced-concepts/understanding-performance-for-mixed-reality#understanding-performance-bottlenecks) より画像引用


# CPU のパフォーマンスに関する推奨事項
一般的に、CPU で行われる Mixed Reality アプリケーションのほとんどの処理は、シーンのシミュレーションとアプリケーションのロジックの処理です。最適化の対象となる領域は以下の通りです。
- アニメーション
- 物理計算
- メモリの割り当て
- 複雑なアルゴリズム (逆運動学、パスファインディングなど)

[CPU パフォーマンスに関する推奨事項 | MS Docs](https://learn.microsoft.com/ja-jp/windows/mixed-reality/develop/advanced-concepts/understanding-performance-for-mixed-reality#cpu-performance-recommendations)

# GPU のパフォーマンスに関する推奨事項

- 帯域幅とフィルレートへの理解
- ポリゴン数 (多角形の数) を減らす
- オーバードローを制限する
- シェーダー
- GPU ステージを削除する

[GPU のパフォーマンスに関する推奨事項 | MS Docs](https://learn.microsoft.com/ja-jp/windows/mixed-reality/develop/advanced-concepts/understanding-performance-for-mixed-reality#gpu-performance-recommendations)

# メモリに関する推奨事項
メモリの割り当てと割り当て解除の操作が過剰に行われるとパフォーマンスが安定せず、フレームがフリーズしたり、その他の悪影響を引き起こす可能性があります。メモリ管理はガベージコレクターによって制御されるため、Unity で開発する時はメモリに関する考慮事項を理解することが特に重要です。

- ガベージコレクション (GC)
- オブジェクトプーリング

[メモリに関する推奨事項 | MS Docs](https://learn.microsoft.com/ja-jp/windows/mixed-reality/develop/advanced-concepts/understanding-performance-for-mixed-reality#memory-recommendations)

# アプリケーション起動時のパフォーマンスについて
アプリケーションの開始時に読み込まれるシーンの容量が大きいと、ユーザーとアプリケーションが対話状態 (操作可能な状態) になるまで時間がかかってしまいます。この状態を避けるには、比較的小さなシーンでアプリケーションを開始した後、``SceneManager.LoadSceneAsync`` API を使用して、残りのシーンを読み込むことで可能な限り素早くアプリを対話状態に移行することができます。

新しいシーンをアクティブ化する際には、大きな CPUスパイク が発生する可能性があること、レンダリングされるコンテンツが途切れたり停止したりする場合があります。この症状を回避する方法として、シーンの読込み時に ``AsyncOperation.allowSceneActivation`` プロパティを ``false`` に設定しておき、シーンの読み込みが終わった段階で、画面をブラックアウトさせ、プロパティを ``true`` に戻すことでアクティブ化を完了する方法があります。

# Refs

https://learn.microsoft.com/ja-jp/windows/mixed-reality/develop/advanced-concepts/hologram-stability

https://learn.microsoft.com/ja-jp/windows/mixed-reality/develop/unity/performance-recommendations-for-unity?tabs=openxr

https://learn.unity.com/tutorial/diagnosing-performance-problems-2019-3?language=en#