Unityの検索機能

『Book of the Dead』に学ぶ、コンソール開発者のためのグラフィックス最適化 10 のヒント

最終更新:2019 年 1 月

このページで学ぶ内容:Unity のコンソール向けグラフィックス開発者である、Rob Thompson (Unite で関連内容の講演実績あり) とUnity のデモチームの協力を得て、コンソール向けのグラフィックス最適化のヒントを皆さんにお届けします。ここで紹介する最適化は、スムーズに動かすことが難しいとされるシーンで、30 fps のパフォーマンス実現を目指して導入されました。

Unity のスクリプタブルレンダーパイプラインで AAA タイトルのクオリティを実現

『Book of the Dead』(以下「BOTD」と表記)は、Unity のデモチームによって制作されました。これはリアルタイムでレンダリングされる短編アニメーションでしたが、実際の所、その制作目的は新しい(まだ実験段階である)スクリプタブルレンダーパイプライン(SRP)の機能を試して、お見せすることにありました。SRP を使えばレンダーループの核となる部分を C# でコーディングできるので、「コンテンツに合わせてシーンをどのように描画するか」という点での、カスタマイズでの柔軟性が大幅に向上します。

コンソール:スクリプタブルレンダーパイプライン

利用可能な SRP は 2 種類あります。 HD レンダーパイプライン (HDRP) (HDRP)は、モダンで AAA タイトルでの利用にも耐える再現度の高いレンダラーに必要な機能をすべて備えたパイプラインであり、一方、 ライトウェイトレンダーパイプライン (LWRP)は、モバイル端末向けに使った場合でも軽快に反応できるパフォーマンスを重視したパイプラインとなっています。『BOTD』では HDRP を使っています。この記事の最後で、ここで紹介した SRP をさらに深く学ぶためのリソースをご紹介します。

また、『BOTD』に用いられたアセットとスクリプトコードは、いずれも 入手可能ですで入手可能です。

コンソールで 1080p、30fps を達成するための主要な最適化パス

このデモの目的は、ユーザーが『BOTD』の世界を歩き回ったり、地面に落ちている小枝をつかんだりといった方法で、伝統的な AAA タイトルのゲームの観点からインタラクティブな体験を提供することでした。具体的に述べると、Xbox One と PS4 で動作する『BOTD』を見せたいと考えていたのです。そこで、私たちはパフォーマンスの要件を「1080p、30fps の達成」と決めました。

完全なゲームではなくデモ映像なので、最適化の主な焦点はレンダリングにありました。

突然大量のパーティクルを生成したり、アニメーションするキャラクターが多数登場するシーンなどはないので、全体的に『BOTD』のパフォーマンスはかなり安定しています。

まず、Rob とデモチームは、パフォーマンスが最も悪かったビューを見つけました。それは GPU のロードに関する部分でした。下の画像が、そのスクリーンショットです。

コンソール:スクリプタブルレンダーパイプライン

シーンで起こっていることは、ほぼ変わりません。違いはカメラのビュー内に入るものだけです。このシーンの処理を軽くすることができれば、デモ全体でのパフォーマンスの向上が見込めます。

このシーンのパフォーマンスが悪いのは、中心を覗き込む形でステージの外観を捉えたビューであるためと、アセットの大部分がカメラの視錐台に含まれるためです。その結果、多くのドローコールが発生します。

このシーンのレンダリング方法は下記のとおりです。

  • HDRP を使用。
  • アーティストが作成したテクスチャのほとんどは 1K と 2K のサイズのマップで、4K のマップは少数。
  • 間接照明に Baked Occlusion と Baked GI を、太陽からの直接照明に Single Dynamic Shadow Casting Light ソースを使用。
  • どの点についても数千回のドローコールを発行(ドローコールとコンピュートシェーダーによるディスパッチ)。
  • パスの最適化を始めたとき、ビューの描画は PS4 Pro で GPU バウンド、所要時間は約 45 ミリ秒。
最適化パス適用前の GPU フレームの内容

Rob とデモチームはステップごとに GPU フレームを見ていき、最適化パスを開始するときにパフォーマンスが以下のようになっていることを見つけました。

  • Gbuffer は 11 ミリ秒(HDRP 用の Gbuffer レイアウトの説明は、Unity のリードグラフィックス開発者である Sebastien Lagarde による この記事 で読むことができます)。
  • Motion Vectors と Screen Space Ambient Occlusion は、それぞれ 0.25 ミリ秒と 0.6 ミリ秒でかなり高速。
  • ダイナミックライトを使ったディレクショナルシャドウのキャスティングからのシャドウマップが、桁外れに大きい 13.9 ミリ秒を消費。
  • Deferred Lighting に 4.9 ミリ秒。
  • Atmospheric Scattering に 6.6 ミリ秒。

描画開始から完了までの GPU フレームの内容:

コンソール:GPU フレーム

この図の通り、GPU フレームは 45 ミリ秒です。2 本のオレンジ色のラインは、30 fps と 60 fps のフレームレートを達成するための GPU フレームの短縮目標をそれぞれ示しています。

『Book of the Dead』のレンダリングを最適化する 10 の方法

バッチカウントを制御する

『BOTD』はゲームではなくデモなので、CPU のパフォーマンスについては大した問題ではありません。つまり、通常のゲーム制作に必要なシステムに対応するスクリプトコードに、複雑さはないのです。よって、主な関心事は、レンダリングの作業を最適化することでした。

ただし、バッチカウントを低く抑えることは、どのプラットフォームでも有益なことです。チームは、 オクルージョンカリング, および主要なテクニックとして、 GPU のインスタンス化. を使用してバッチカウントを低く抑えました。なお、確実にパフォーマンスを向上できる場合を除き、コンソールでのダイナミックバッチングの使用は避けてください。

この場合、GPU のインスタンス化が最も有用な方法でした。インスタンス化なしだとこのシーンのバッチ数は 4500 でしたが、インスタンス化を使用することで、バッチ数は 1832 まで減りました。

覚えておくべき点:このシーンを作るために使用されたアセットの数は、実はごくわずかです。質の高いアセットをうまく配置することで、チームは繰り返しに見えない複雑なシーンを作成し、さらに GPU のインスタンス化によってバッチカウントを低く抑えました。

インスタンス化なしのシーン:

コンソール:スクリプタブルレンダーパイプライン

インスタンス化ありのシーン:

コンソール:スクリプタブルレンダーパイプライン

コンソール機に搭載されているマルチコアを活用する

Xbox One と PS4 は両方ともマルチコアデバイスであり、最高の CPU パフォーマンスを得るには、それらのコアを常にビジー状態に保つ必要があります。

Unity からのニュースを追っている方は、Unity が 高性能のマルチスレッドシステム の開発に取り組んでいることをご存知かと思います。これは、現在市場に出回っているものから将来発表されるものまで含めて、マルチコアプロセッサーの機能をフルに活用できるシステムとなります。とても簡単に言えば、このシステムは Entity Component SystemC# Job System、および Burst コンパイラー の 3 つのサブシステムで構成されています。

新しいマルチスレッドシステムは、まだ初期の実験段階にあります。Unity のグラフィックスシステムでは、同じく実験段階の Graphics Jobs モードを通して試すことができます。また、Graphics Jobs のコントロールは、Player Settings > Other Settings から表示できます。

コンソール:Graphics Jobs

Graphics Jobs モードでは、コンソール機に対して、文字通り少数のバッチを描画する場合を除き、ほとんどすべての状況でパフォーマンスの最適化を実現します。利用できる最適化は、以下の 2 タイプです。

  • PS4 の「Legacy Jobs」と Xbox One の「DirectX 11」
    • 他のコアに作業を分散させることで、メインスレッドの負荷を軽減できます。ただし、かなり大きなシーンでは、この処理が、Unity がプラットフォームホルダーのグラフィックス API とやりとりするために使用する Render Thread のボトルネックとなることがあるのでご注意ください。
  • PS4 の「Native Jobs」と Xbox One の「DirectX 12」(まもなく提供開始)
    • 使用可能なコアに最も多くの作業を割り当てるため、大きなシーンの作業に最適なオプションです。
    • 2018.2 以降のバージョンでは、常に最善の選択肢となります(2018.1 以前のバージョンでは、メインスレッドへの処理集中を引き起こし、パフォーマンスの低下を招くことがあります)。

プラットフォームホルダーのパフォーマンス分析ツールを使用する

Microsoft と Sony は、CPU と GPU の両方のパフォーマンスを分析する 優れたツール を提供しています。これらのツールは、コンソール上で作業している場合は無料で利用できますので、早い段階でツールの使い方を習得し、開発過程で活用しましょう。Xbox One 用の Pix は Microsoft 製で、PS4 用の Razor Suite は Sony 製です。Rob は「これらのツールは、それぞれのプラットフォームで最適化を行うためのメインツールになるでしょう」と述べています。

ポストプロセスエフェクトをプロファイルする

Rob は PS4 で Unity ゲームをプロファイルしたと述べています。実は、開発者は気づいていませんが、PS4 ではポストプロセッシングによって、フレームレートが 3 分の 1 まで落とされてしまうことがあります。これは、主に PC 用に作成されたポストプロセッシングアセットをアセットストアからダウンロードすることによって引き起こされます。それらはコンソール上で正常に動作するように見えますが、実際にはパフォーマンスの特性が非常に悪いのです。

エフェクトを適用するときは、 GPU での実行時間をプロファイルし、ビジュアルの品質とパフォーマンスのバランスが取れるまでプロファイルを繰り返します。それが終わったら、その時点のプロファイルをキープします。これは、バランスの取れたプロファイルにはすべてのシーンの静的コストが含まれているためです。つまり、その情報から GPU の帯域福にどのくらい余裕が残っているかが分かるのです。

特別な理由がない限りテッセレーションの使用を避ける

一般的にコンソールゲームグラフィックスにおいて、GPU 上でランタイムのテッセレーションを行うのはお勧めできません。ほとんどのケースでは、同等のアーティストのオーサリングされたアセットを使用する方が有効です。

しかし『BOTD』の場合は、テッセレーションを使用するのに十分な理由がありました。それは木の皮をレンダリングするためでした。

コンソール:テッセレーション

テッセレートされた面のディスプレイスメントを使って、法線マッピングでは不可能な深いくぼみとごつごつしたディテールをジオメトリに加えることができました。

『BOTD』の大部分は樹木が主役のオブジェクトなので、テッセレーションの使用は理にかなっていました。これは LOD 0 と LOD 1 で樹木に同じメッシュを使用したことによって行われました。2 つの LOD の違いは、オブジェクトが LOD 1 に切り替わる時に、テッセレーションされたメッシュのディスプレイスメントを小さくして、その効果がわからなくなるようにすることだけです。

GPU で常に程よいウェーブフロントの占有率を目指す

ウェーブフロント占有率を理解することは、非常に重要です。

ウェーブフロントは GPU 作業のパケットとして考えることができます。GPU へのドローコールか、コンピュートシェーダーのディスパッチをサブミットすると、その作業は多くのウェーブフロントに分割され、それらのウェーブフロントは GPU で使用可能な全コンピュートユニット内のすべての SIMD に分散されます。

コンソール:ウェーブフロントの占有率

各 SIMD には、一度に実行できるウェーブフロントに限界があり、GPU 上で並列して実行できるウェーブフロントの最大合計数はあらかじめ決まっています。これらのウェーブフロントのうち、使用しているもののの数が「ウェーブフロントの占有率」と呼ばれ、GPU の並列処理するための性能をどれだけうまく利用しているかを知る指標になります。

Pix と Razor は、ウェーブフロントの占有率を非常に詳しく示すことができます。左側の画像は、ウェーブフロントの良好な占有率を示しています。緑色の領域は、頂点シェーダーのウェーブフロントがいくつか実行されていることを、青色の領域は、ピクセルシェーダーのウェーブフロントが実行されていることを、それぞれ示しています。

一方、左側の画像はパフォーマンスに問題が見られます。頂点シェーダーがかなり動いているのに比べ、ピクセルシェーダーのアクティビティが少なすぎるのです。言わば、GPU のポテンシャルを無駄遣いしている状態になっています。私たちは、ここから次の最適化へのヒントを得ました。

なお、この現象は「頂点シェーダーが動いているが、ピクセルが描画されていないとき」によく見られます。

デプスプレパスを利用する

Pix と Razor でさらに分析したところ、Gbuffer パスの間に多くのオーバードローが発生していることが分かりました。これは、コンソールでアルファテストしたオブジェクトを表示する時、特に顕著なようです。

コンソールで、ピクセルのデータ破棄命令を出したり、ピクセルシェーダのデプスに直接書き込むと、アーリーデプスリジェクションを利用できません。これらのピクセルシェーダーのウェーブフロントは、ウェーブフロントによる処理結果が最後には破棄される場合でも実行されてしまいます。

この問題の解決策は、デプスプレパスを追加することでした。これは、非常に軽いシェーダーを使用して事前にデプスだけをレンダリングする方法です。こうすることで、これまで重い Gbuffer シェーダーバウンドがかかっていたデプスリジェクションを、より賢く行うための準備ができます。

HDRP には、すべてのアルファテスト済みオブジェクトのデプスプレパスが含まれていますが、必要に応じて完全なデプスプレパスに切り替えることもできます。HDRP を制御するための設定や、どのレンダリングパスが使用されるのか、機能の有効化などはすべて、

HDRP プロジェクトで HD Render PipelineAsset を検索すると、HDRP の挙動をすべて制御できるチェックボックスのセットが表示されます。

なお、『BOTD』では、デプスプレパスの使用が GPU に良い影響を与えますが、一方で CPU に描画対象のバッチを追加するオーバーヘッドをかけることも覚えておいてください。

シャドウマッピングのレンダーターゲットのサイズを小さくする

前述のように、このシーンのシャドウマップは、シャドウを描画する単一のディレクショナルライトに対して生成されます。4 つの分割シャドウマップが使用され、最初に 32 ビット深度で 4K シャドウマップにレンダリングされています。これは HDRP プロジェクトのデフォルトの設定です。シャドウマップにレンダリングするとき、ほとんどの場合、シャドウマップの解像度が制限要因となります。これは、Pix と Razor による分析で裏付けされました。

シャドウマップの解像度を下げることは、品質に影響を与える可能性はあるものの、明らかな解決策でした。

そのため、デモチームはシャドウマップの解像度を 3k に下げて、パフォーマンスに対し完全に受け入れられるトレードオフを提供しました。さらに、開発者が 16 ビット深度のシャドウマップにレンダリングできるオプションを追加しました。ご自身で試してみたい場合は、プロジェクトアセットを ダウンロード してください。

また、シャドウマップの解像度を変更したため、ライトに関する設定も若干変更する必要がありました。

シャドウのサイズを減らす

この時点で、チームはシャドウマップのリビジョンを作成し、シャドウマッピングのカメラを再配置して、縮小後の新しい解像度を最大限に活用する方法を探りました。その次に彼らは何を行ったでしょうか?

最もズームアウトされた最後のシャドウマップの分割を、ステージロード時に 1 回だけ描画する

シャドウマッピングのカメラはあまり動かないので、この方法はうまくいきました。ちなみに、最もズームアウトされた分割は、通常、Player のカメラから最も遠い影をレンダリングするために使われます。

この方法を試した結果、品質の低下は見られませんでした。GPU のフレームレートの時間と CPU のバッチ数の減少の両方で節約できるため、とても有効な最適化であることが判明しました。

この一連の最適化が行われた後、シャドウマップの開発フェーズは 13 ミリ秒から 8 ミリ秒未満になりました。ライティングパスは 4.9 ミリ秒から 4.4 ミリ秒に、大気散乱パスは 6.6 ミリ秒から 4.2 ミリ秒になりました。

下の画像は、チームがシャドウマッピングの最適化を行った後の状態です。現在、彼らは PS4 Pro で 30fps 動作させることができています。

コンソール:GPU フレーム

Async Compute を活用する

Async Compute(非同期演算)は、実用性に優れるコンピュートシェーダーを使って GPU の使用率が低い期間を最小限に抑えるのに役立つ手法です。現在は PS4 でしかサポートされていませんが、近日中に Xbox One の DX12 でもサポートされる予定です。Async Compute には、Unity のコマンドバッファインターフェースからアクセスできます。これは SRP 専用というわけではありませんが、SRP を主な対象としています。コード例は BOTD のアセットに含まれているほか、HDR PSOS で公開されています。

シャドウマッピングを使用した深度のみのフェーズは、GPU のポテンシャルをフルに活用していない問題があります。しかし、Async Compute を使用すれば、コンピュートシェーダーをグラフィックキューと並行して動かすことができます。それによって、グラフィックキューが十分に活用してないリソースを利用することができます。

『BOTD』では、Deferred Lighting の中でタイルライトリストを集めるために Async Compute を使用します。それらのほとんどは、HDRP のコンソール上のコンピュートシェーダーで処理されるほか、SSAO の計算にも使用されます。これらは両方ともウェーブフロントの使用でギャップを埋めるためにシャドウマップのレンダリングとオーバーラップしています。

Async Compute を使った概念コードは、Rob の Unite セッション の 35 分 30 秒付近で紹介されています。

その他のリソース

今後のためにうかがいます。このコンテンツはいかがでしたか?

もっと読みたい いまいちです
OK

弊社のウェブサイトは最善のユーザー体験をお届けするためにクッキーを使用しています。詳細については、クッキーのポリシーのページをご覧ください。