1. サイトトップ
  2. ブログ
  3. Unity
  4. 【Unity】UnityでのリアルタイムGPU負荷測定について

【Unity】UnityでのリアルタイムGPU負荷測定について

はじめに

こんばんは、代表の堂前です!

まず、弊社ホームページがリニューアルされました。
新しいデザインはいかがでしょうか?
今までは堂前が片手間で更新していてデザイン性が皆無でしたがw、カッコいいものになったと思います。
(ご制作下さったDUCK WORKSさま、ありがとうございます!!)

それに伴い、このブログもだいぶ技術的な記事をサボってしまっていたので。。
今後は続けられるようにしていきます。

そんな生まれ変わりの初回ですがUnityでのGPU負荷測定をテーマに取り上げます。
※検証したのはWindowsのUnity2019.1.10f1になります。

GPU負荷の測定について

プログラムを実行するとCPUに負荷がかかり処理時間がかかりますが、グラフィックを描くGPUに関してもそれは同様です。
そして処理時間が多くかかると、ゲームでは処理落ちにつながってしまいます。

自分もゲーム業界に長く働いていますが、開発中はリアルタイムでGPUの負荷を測定し、それを画面上に表示させていることが殆どでした。
ですのでゲーム開発においてGPU負荷がすぐ見れる状態にしておくというのは当たり前だと思っていましたが、Unityを触り始めた当初、GPUの負荷が計測できないことに大変驚きました。

どう解決するか質問したところ「Profilerやキャプチャソフト使えば?」的に言われますが、それは違うんです!
今回は「リアルタイムで」というのが強いポイントになっています。
つまり今表示させている絵での負荷がデバッグとして表示されますし、絵が変わればその値も増減します。
リアルタイムで計測することのメリットとして、以下が挙げられます。

  • 例えばマップ表示で、見ている場所、見る方向でGPU的にボトルネックになっている部分が見つけやすい。
  • リアルタイムでGPU負荷測定をすることで、重くなった時に描画解像度を下げるなどの対策が取れる。(動的解像度)
  • Profilerやキャプチャソフトでは1フレームでの負荷しか取れないので、連続してのデータが非常に取りづらい。
  • 何よりProfilerやキャプチャソフトは、プログラマ以外が扱うのに難しい。

UnityではGPU負荷が取れないためデルタタイムによるfpsなどで確認するしかなく、これでどうやってみんな作っているんだろうと思いましたが。。
今回紹介する「FrameTimingManager」で、そういった悩みを解決できそうです!

準備と環境

「FrameTimingManager」を使うには、以下の条件と準備が必要です。

  • 動作するプラットフォームが限られます。
  • 「Project Settings – Player – Enable Frame Timing Stats」を有効にする。
(※Enable Frame Timing Statsの設定)

プラットフォームですが、WindowsやVulkan(Android)では測定不可でした。
iOSのMetalでは実現できたので、今回はそれで行っています。(未確認ですがPS4,XboxOneなども大丈夫そうとのことです)
今回は↓の様なシチュエーションで測定しました。

(※今回のシチュエーション)

フルカラーのテクスチャを貼り付けた板を40回程度上書きするのを用意し、それを表示オンオフすることでGPU負荷的に「軽⇔重」を繰り返します。

FrameTimingManager

MonoBehaviourを追加し、以下のような処理を追加します。

void Update()
{
    // 結果格納のための準備(数は適当)
    FrameTiming[]   frameTimings = new FrameTiming[10];

    // キャプチャ実行
    FrameTimingManager.CaptureFrameTimings();

    // 結果を取得
    uint    numTimings = FrameTimingManager.GetLatestTimings(
                             (uint)frameTimings.Length,
                             frameTimings
                         );
}

FrameTimingManagerというのが今回キモになるクラスです。
FrameTimingの配列を作り、CaptureFrameTimings()でキャプチャ実行し、GetLatestTimings()でその結果をFrameTimingに書き込みます。

FrameTimingですが、GPU負荷だけではなく様々な情報を取得できます。
全ての説明は割愛しますが、GPU負荷は「gpuFrameTime」というメンバに格納されます。

※↑軽いシーン
※↑重いシーン

これを利用して先述のシーンにgpuFrameTimeを表示させると以下の様になります。

「軽」と「重」でGPUの数字が変わっているのが分かるかと思います。
これがgpuFrameTimeで、フレームにおけるGPU処理時間がms(ミリ秒)で表示されていて、「軽」では2.5msで、「重」では約20msとなっています。
「重」は60fps(1フレーム=16.666..ms)を超えていますので、非常に重い状況だなというのが分かります。

このようにしてFrameTimingManagerを利用することでGPUのリアルタイム負荷測定が出来そうです。

まとめ

FrameTimingManagerによるUnityでのリアルタイムGPU負荷測定について説明しました。
個人的にこういった機能は本当に必要だと思っていて、いろんなところで言い続けていたのですが、実装されていて本当に嬉しいです。

GPU負荷をリアルタイムで測定できることでデバッグであったり、実際のゲームの挙動であったりで有効活用できるかと思いますので、皆さんもぜひご活用ください。


【免責事項】

本サイトでの情報を利用することによる損害等に対し、
株式会社ロジカルビートは一切の責任を負いません。