フレームデバッガー
レイヤー

シェーダーのロード時間の最適化

シェーダーは GPU 上で実行する小さなプログラムであり、それらをロードするには時間がかかることがあります。個々の GPU プログラムは一般的にロードするのに時間がかかりませんが、シェーダーは、多くの場合、内部にバリアントがたくさんあります。

たとえば、スタンダードシェーダー 。完全にコンパイルされると、結局、わずかに異なる何千もの GPU プログラムになります。これによって 2 つの問題の可能性が発生します。

  • これらの多数のシェーダーバリアントは、ゲームのビルド時間とゲームのデータサイズを増加させます。
  • ゲーム中、多数のシェーダーバリアントをロードすると、ゲームの速度が遅くなり、メモリを使いきってしまいます。

シェーダービルド時間の削減

ゲームをビルドしている間、Unity は、内部シェーダーバリアントのいくつかがゲームで使用されていないことを検出し、ビルドデータからそれらをスキップします。ビルド時間の削減は、以下のために行われます。

  • #pragma shader_feature を使うシェーダーのための個々のシェーダーの機能。ある特定のバリアントが使用中のどのマテリアルにもまったく使用されない場合、そのバリアントをビルドに加えません。内部シェーダーバリアント に関するドキュメントを参照してください。ビルトインシェーダーのうち、スタンダードシェーダー は、内部シェーダーバリアントを使用しています。
  • シーンのいずれでも使用されていないフォグとライトマッピングモードを処理するシェーダーバリアントは、ゲームデータに含まれません。この動作をオーバーライドしたい場合は、Graphics Settings を参照してください。

上記の組み合せは、シェーダーデータサイズをしばしば大幅に減らします。例えば、完全にコンパイルしたスタンダードシェーダーは数百メガバイトを消費することもあります。しかし、典型的なプロジェクトでは、大抵、わずか数メガバイトを消費します (アプリケーションのパッケージングプロセスによってさらに圧縮されることもよくあります)。

デフォルトの Unity シェーダーのロードの動作

すべてのデフォルト設定で、Unity は、ShaderLab シェーダー オブジェクトをメモリへロードしますが、実際に必要になるまで、内部のシェーダーバリアント を作成しません。

これは、ゲームのビルドに含まれているシェーダーバリアントはまだ使用可能であることを意味します。ただし、それらが必要になるまでメモリやロード時間のコストはかかりません。例えば、シェーダーには常に影を持つポイントライトを処理するためのバリアントが含まれていますが、ゲーム内の影にポイントライトを使わない限り、この特定のバリアントはロードされません。

このデフォルトの動作の欠点の 1 つは、いくつかのシェーダーバリアントが初めて必要になるときに、しゃっくりが起こる場合があることです。- 新しい GPU プログラムコードがグラフィックスドライバーにロードされなければならないからです。これはゲームの間は好ましくないので、Unity には それを解決するための ShaderVariantCollection アセットがあります。

シェーダーバリアントコレクション

シェーダーバリアントコレクションは 1 つのアセットで、基本的に シェーダー のリストです。各シェーダーに関して、パスの種類と起動のためのシェーダーキーワードの組み合わせを表示します。

シェーダーバリアントコレクションのインスペクター
シェーダーバリアントコレクションのインスペクター

実際に使用したシェーダーとそのバリアントに基づいてアセットの作成を支援するために、エディターは実際に使用されているシェーダーとそのバリアントを追跡することができます。Graphics Settings に、現在追跡されているシェーダーから新しいシェーダーバリアントコレクションを作成するボタンと、現在追跡しているシェーダーリストを削除するボタンがあります。

エディターが使用するシェーダーからシェーダーバリアントコレクションを作成する
エディターが使用するシェーダーからシェーダーバリアントコレクションを作成する

ShaderVariantCollection アセットを取得したら、これらのバリアントをアプリケーションのロード中に自動的にプリロードされるか (Graphics Settings の Preloaded Shaders の下) 、スクリプトから個々のシェイダーバリアントコレクションをプリロードすることができます。

Preloaded Shaders リストは、頻繁に使用されるシェーダーを対象としています。ここにリストされているシェーダーのバリアントは、アプリケーションの生存期間にわたってメモリに読み込まれます。これによって、多数のバリアントを含む ShaderVariantCollections アセットに著しい量のメモリが使用される場合があります。これを避けるには、ShaderVariantCollection アセットをより細かく作成し、スクリプトから読み込む必要があります。1 つの方法としては、各シーンに使用されているシェーダーバリアントを記録し、別々の ShaderVariantCollections アセットに保存し、それらをシーン起動時に読み込むことです。

ShaderVariantCollection スクリプトクラスを参照してください。

参照

フレームデバッガー
レイヤー