Understanding performance for mixed reality [Mixed Reality ドキュメント]

今回はこのドキュメントを読む.

docs.microsoft.com

最適なフレームレート

アプリが最適なフレームレートで動作しない場合,以下の問題が発生する.

  • ホログラム物体が不安定に見える
  • 環境のヘッドトラッキングが不正確になる

これによりユーザ体験に悪影響を及ぼすため,フレームレート・パフォーマンス維持を考慮することが大事である.
HoloLensの場合はフレームレート60FPSを最低限維持する必要がある.

パフォーマンスのボトルネックを理解する

フレームレートが低下している場合,ボトルネックとなっている原因を追究する必要がある.
ボトルネックの発生源として以下の3点が可能性として挙げられる.

  • アプリケーションスレッド(CPU)
    アプリケーションのロジックを担当しているスレッド.
    入力処理,アニメーション処理,物理演算などを行っている.
  • レンダースレッド(CPU to GPU)
    GPUへの描画コールの送信を担当しているスレッド.
    アプリがオブジェクトをレンダリングを行う時にGPUに要求を送信して,操作を実行する.
  • GPU
    3Dモデルをピクセルに変換するアプリケーションのグラフィックスパイプラインを処理する.
    最終的にはデバイスのスクリーンに送信するための2Dイメージを生成している.

f:id:xrdnk:20200428165520p:plain

パフォーマンスの分析方法

以下のツールを使おう.

環境に依存しないプロファイリング方法

GPU Bound か CPU Bound かを判断する方法として,

  1. レンダリング解像度を下げる
  2. 下げた後,フレームレートが上がっていればGPU Boundが原因
  3. 下げた後,フレームレートが変わらなければ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;
    }
}

docs.unity3d.com

アプリケーションの最適化方法

CPU

CPUの場合は,以下が最適化の対象になる.

  • アニメーション
  • 物理演算
  • メモリの割り当て
  • 複雑なアルゴリズム(IKや経路探索)

GPU

メモリ帯域幅とフィルレート(テクセル描画速度)を理解しよう

GPU上でフレームをレンダリングする時,メモリ帯域幅かフィルレートの何方かに制限がかかる.

メモリ帯域幅

GPUがメモリから読み書き出来る速度のこと
帯域幅の制限を確認するためには,テクスチャ品質を下げて,フレームレートが改善されたか確認する.
Unityでは Edit > Project Settings > Quality SettingsでTexture Quality でテクスチャ品質を調整できる.

f:id:xrdnk:20200428190111p:plain

テクスチャ品質を低減したり,少ないテクスチャを利用することで,メモリ帯域幅は最適化される.

フィルレート(テクセル描画速度)

GPUが1秒間に描画できるピクセル数のこと
フィルレートの制限を確認するためには,レンダリング解像度を下げて,フレームレートが改善されたか確認する.
Unityでは XRSettings.renderViewportScaleプロパティで調整できる.

レンダリング処理するオブジェクトの数,シェーダごとの操作数,ポストプロセスなどのような最終GPUステージの数,
レンダリングするピクセル数を減らすことで最適化される.

ポリゴン数

シーンのポリゴン数を減らすことでレンダリング時間が短縮される.

オーバードローの制限

オーバードローとは,単一フレームのレンダリングにおいてシステムが画面上の 1 つのピクセルを複数回描画すること.
複数回描画することで,動作が重くなる傾向にある.

後ろにオブジェクトがある壁を例に挙げる.
この時オブジェクトは見えないため,壁だけを描画すればいいけれど,
オーバードローでオブジェクトもレンダリングされてしまうのは無駄な処理となる.

シェーダ

シェーダは多くの変換やライティング計算を実行する.
シェーダでの計算の操作を減らすことで,フレームあたりのGPUに必要なタスクを減らすことができる.

GPUステージをなくす

ポストプロセスはフィルレートを大きく上げてしまうため,ポストプロセスステージはなくすこと.
HoloLensでは,ポストプロセスステージをなくし,シェーダステージの追加を避ける.

メモリ

Object Poolingを利用しよう.
Object Pooling とは オブジェクトが繰り返し生成されたり破棄されたりするのを回避するためのデザインパターンのこと.
InstantiateとDestroyは呼び出しコストが高いので,だいたいObject Poolingデザインパターンを利用することがある.

doruby.jp

Unityで簡単オブジェクトプール.
qiita.com

参考記事

パフォーマンスのチューニングを行う場合,以下のカヤックさんの記事が参考になりそう.
techblog.kayac.com

logmi.jp