Understanding performance for mixed reality [Mixed Reality ドキュメント]
今回はこのドキュメントを読む.
最適なフレームレート
アプリが最適なフレームレートで動作しない場合,以下の問題が発生する.
- ホログラム物体が不安定に見える
- 環境のヘッドトラッキングが不正確になる
これによりユーザ体験に悪影響を及ぼすため,フレームレート・パフォーマンス維持を考慮することが大事である. HoloLensの場合はフレームレート60FPSを最低限維持する必要がある.
パフォーマンスのボトルネックを理解する
フレームレートが低下している場合,ボトルネックとなっている原因を追究する必要がある. ボトルネックの発生源として以下の3点が可能性として挙げられる.
- アプリケーションスレッド(CPU) アプリケーションのロジックを担当しているスレッド. 入力処理,アニメーション処理,物理演算などを行っている.
- レンダースレッド(CPU to GPU) GPUへの描画コールの送信を担当しているスレッド. アプリがオブジェクトをレンダリングを行う時にGPUに要求を送信して,操作を実行する.
- GPU 3Dモデルをピクセルに変換するアプリケーションのグラフィックスパイプラインを処理する. 最終的にはデバイスのスクリーンに送信するための2Dイメージを生成している.
パフォーマンスの分析方法
以下のツールを使おう.
- Intel Graphics Performance Analyzers
- Visual Studio Graphics Debuggers
- Unity Profiler
- Unity Frame Debugger
環境に依存しないプロファイリング方法
GPU Bound か CPU Bound かを判断する方法として,
Unityでは,XRSettings.renderViewportScale
プロパティを利用することで,
実行時にアプリのレンダリング解像度を変更することが出来る.
using UnityEngine; public class RenderScaleController : MonoBehaviour { [SerializeField, Range(0, 1)] private float renderScale = 0.7f; void Start () { UnityEngine.XR.XRSettings.renderViewportScale = renderScale; } }
アプリケーションの最適化方法
CPU
CPUの場合は,以下が最適化の対象になる.
- アニメーション
- 物理演算
- メモリの割り当て
- 複雑なアルゴリズム(IKや経路探索)
GPU
メモリ帯域幅とフィルレート(テクセル描画速度)を理解しよう
GPU上でフレームをレンダリングする時,メモリ帯域幅かフィルレートの何方かに制限がかかる.
メモリ帯域幅
GPUがメモリから読み書き出来る速度のこと.
帯域幅の制限を確認するためには,テクスチャ品質を下げて,フレームレートが改善されたか確認する.
Unityでは Edit > Project Settings > Quality SettingsでTexture Quality
でテクスチャ品質を調整できる.
テクスチャ品質を低減したり,少ないテクスチャを利用することで,メモリ帯域幅は最適化される.
フィルレート(テクセル描画速度)
GPUが1秒間に描画できるピクセル数のこと.
フィルレートの制限を確認するためには,レンダリング解像度を下げて,フレームレートが改善されたか確認する.
Unityでは XRSettings.renderViewportScale
プロパティで調整できる.
レンダリング処理するオブジェクトの数,シェーダごとの操作数,ポストプロセスなどのような最終GPUステージの数,
レンダリングするピクセル数を減らすことで最適化される.
ポリゴン数
シーンのポリゴン数を減らすことでレンダリング時間が短縮される.
オーバードローの制限
オーバードローとは,単一フレームのレンダリングにおいてシステムが画面上の 1 つのピクセルを複数回描画すること.
複数回描画することで,動作が重くなる傾向にある.
後ろにオブジェクトがある壁を例に挙げる.
この時オブジェクトは見えないため,壁だけを描画すればいいけれど,
オーバードローでオブジェクトもレンダリングされてしまうのは無駄な処理となる.
シェーダ
シェーダは多くの変換やライティング計算を実行する. シェーダでの計算の操作を減らすことで,フレームあたりのGPUに必要なタスクを減らすことができる.
GPUステージをなくす
ポストプロセスはフィルレートを大きく上げてしまうため,ポストプロセスステージはなくすこと. HoloLensでは,ポストプロセスステージをなくし,シェーダステージの追加を避ける.
メモリ
Object Poolingを利用しよう. Object Pooling とは オブジェクトが繰り返し生成されたり破棄されたりするのを回避するためのデザインパターンのこと. InstantiateとDestroyは呼び出しコストが高いので,だいたいObject Poolingデザインパターンを利用することがある.
Unityで簡単オブジェクトプール. qiita.com
参考記事
パフォーマンスのチューニングを行う場合,以下のカヤックさんの記事が参考になりそう. techblog.kayac.com