Version: 2019.4
言語: 日本語
詳細な ShaderLab トピック
非同期シェーダーコンパイル

Optimizing shader variants

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

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

  • これらの多数のシェーダーバリアントは、ゲームのビルド時間とゲームのデータサイズを増加させます。
  • Loading large numbers of shader variants at runtime is slow and takes up memory.

ビルド時のストリッピング

ゲームのビルド中に、Unity は内部シェーダーバリアントの一部がゲームで使用されていないことを検出し、ビルドデータから除外 (ストリップ) することができます。ビルド時のストリッピングは以下のように行われます。

  • #pragma shader_feature を使用するシェーダーでは、Unity はバリアントが使用されているかどうかを自動的にチェックします。ビルド内のマテリアルのどれもがバリアントを使用していない場合、そのバリアントはビルドに含まれません。内部シェーダーバリアント ドキュメントを参照してください。スタンダードシェーダー はこれを使用します。
  • いずれのシーンでも使用されていないフォグとライトマップモードを処理するシェーダーバリアントは、ゲームデータに含まれません。この動作をオーバーライドしたい場合は、Graphics ウィンドウを参照してください。
  • また、手動でバリアントを識別し、OnProcessShader API を使用して、ビルドから除外するよう Unity に指示することもできます。

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

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

Under all default settings, Unity loads the shaderlab Shader object into memory at runtime, but does not create the internal shader variants until they are actually needed.

This means that all shader variants that are included in the build can still potentially be used, but there’s no memory or load time cost paid until they are needed. For example, a shader might always include a variant to handle point lights with shadows, but if you never end up using a point light with shadows in your game, then there’s no point in loading this particular variant.

One downside of this default behavior, however, is a possible hiccup for when a shader variant is needed for the first time - since a new GPU program code has to be loaded into the graphics driver. This is often undesirable during gameplay, so Unity has ShaderVariantCollection assets to help solve that.

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

ShaderVariantCollection is an asset that is basically a list of Shaders, and for each of them, a list of Pass types and shader keyword combinations to load in advance, rather than wait until they are needed.

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

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

エディターで使用するシェーダーから ShaderVariantCollection を作成
エディターで使用するシェーダーから ShaderVariantCollection を作成

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

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

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

参照

詳細な ShaderLab トピック
非同期シェーダーコンパイル