Version: 2021.2
言語: 日本語
シェーダーのバリエーションとシェーダーのキーワード
シェーダーキーワード

シェーダーバリアント

Unity は、シェーダーのソースファイルを個々のシェーダープログラムにコンパイルします。コンパイルされた各シェーダープログラムは、1 つまたは複数の バリアント を持っています。バリアントとはシェーダープログラムのバージョンのことで、シェーダーキーワード の異なる組み合わせで動作します。ランタイムに、Unity がジオメトリをレンダリングするとき、現在の要件に合うバリアントを使用します。Unity がどのようにシェーダーバリアントをロードして使用するかについては、シェーダーのロード を参照してください。

シェーダープログラムには、その時点のマテリアルに必要なコードだけが含まれているため、シェーダーバリアントはパフォーマンスを向上させるのに役立ちます。一般的にこの方法で最適化されるものは、テクスチャの読み込み、頂点の入力、インターポレーター、ループのような複雑なコードなどです。また、シェーダープログラム自体も小さくなります。

シェーダーバリアントは、同じシェーダーソースファイルを違う方法で使用できるため、ワークフローの改善にもつながります。例えば、様々なマテリアルのための設定、異なるハードウェアのための機能定義、ランタイムのシェーダーの動作の動的変更などが可能です。

しかし、潜在的なデメリットもあります。非常に多くのバリアンとを簡単に作れるため、以下が起こる可能性があります。

  • ビルド時間、ファイルサイズ、ランタイムのメモリ使用量、ロード時間が増加する。
  • シェーダーを手動でプリロード (事前準備) する際に、より複雑になる。

In larger projects, these issues can lead to significant problems with performance and workflow. It is therefore very important to understand how shader variants work, and how to exclude (“strip”) unneeded variants from compilation. For more information on shader stripping, see Shader variant stripping.

非常に多くのバリアントを持つシェーダーは、“メガシェーダー” または “ウーバーシェーダー” と呼ばれます。Unity のスタンダードシェーダーは、その一例です。

シェーダーバリアントの数

ビルド時に、Unity は現在のビルドターゲットの各グラフィックス API に対して 1 セットのシェーダーバリアントをコンパイルします。各グラフィックス API とビルドターゲットの組み合わせに対するバリアントの数は、シェーダーのソースファイルとシェーダーキーワードの使用に依存します。

グラフィックス API

Unity は現在のビルドターゲットの各グラフィックス API に対して 1 セットのシェーダーバリアントをコンパイルします。シェーダーは、各ビルドターゲットとグラフィックス API の組み合わせごとに異なります。例えば、Unity は iOS の Metal と macOS の Metal に対して、異なるシェーダーをコンパイルします。

シェーダープログラムやキーワードによっては、指定のグラフィックス API やビルドターゲットのみを対象とするものもあります。そのため、グラフィックス API とビルドターゲットの組み合わせごとのバリアントの数は異なります。ただし、これらのバリアントをコンパイルする手順は同じです。

現在のビルドターゲットのグラフィックス API のリストを表示および編集するには、Player 設定 ウィンドウ、または PlayerSettings API を使用します。

シェーダープログラムの数

Unity は、現在のビルドターゲットとグラフィックス API の組み合わせに対して、コンパイルするシェーダープログラム数を決定する必要があります。

ビルドに含まれるシェーダーのソースファイルごとに、固有のシェーダープログラムをいくつ定義するかが決定されます。

  • コンピュートシェーダーアセットは、1 つのシェーダープログラムを定義します。
  • ハンドコードされたシェーダーでは、シェーダープログラムの数はコードに依存します。総数は以下から構成されます。
    • ソースファイルのすべてのパスのすべてのシェーダーステージ。例えば、各頂点ステージで 1 つのシェーダープログラムを定義し、各フラグメントステージで 1 つのシェーダープログラムを定義する、というように。
    • ソースファイルの依存関係にあるすべてのパスのすべてのシェーダーステージ。これには、すべての フォールバックシェーダーUsePass コマンド を使用するすべてのパスが含まれます。
  • Shader Graph シェーダーでは、シェーダープログラムの数は、Unity がグラフから生成するコードに依存します。Unity が生成するシェーダーコードを見るには、Shader Graph アセットを右クリックし、 See generated code を選択します。その後、ハンドコードされたシェーダーの場合と同じ方法で、シェーダープログラムの総数が決まります。

ノート: シェーダーのソースファイルは、ビルドのシーンで参照されている場合、Resources フォルダーの何かによって参照されている場合、Graphics Settings ウィンドウの Always-included Shaders セクションに含まれている場合に、そのビルドに含まれます。

シェーダープログラムに影響を与えるキーワード

Unity は、現在のビルドターゲットとグラフィックス API に対して、コンパイルするシェーダープログラム数を決定し、次に、各シェーダープログラムに対してコンパイルしなければならないシェーダーバリアントの数を決定します。

各シェーダープログラムに対して、Unity はそのプログラムに影響を与えるシェーダーキーワードの組み合わせを決定します。これは以下によって構成されています。

Unity が 1 つのシェーダープログラムに対してコンパイルするシェーダーバリアントの数は、キーワードの積です。つまり、Unity は各セットから 1 つの要素を含むすべての組み合わせに対して 1 つのバリアントをコンパイルします。

例えば、このセットには 3 つのキーワードが含まれています。

  • COLOR_RED
  • COLOR_GREEN
  • COLOR_BLUE

このセットには 4 つのキーワードが含まれています。

  • QUALITY_LOW
  • QUALITY_MEDIUM
  • QUALITY_HIGH
  • QUALITY_ULTRA

これらのキーワードの影響を受けるシェーダープログラムは、以下の 12 種類のヴァリアントになります。

  • COLOR_RED、QUALITY_LOW
  • COLOR_RED、QUALITY_MEDIUM
  • COLOR_RED、QUALITY_HIGH
  • COLOR_RED、QUALITY_ULTRA
  • COLOR_GREEN、QUALITY_LOW
  • COLOR_GREEN、QUALITY_MEDIUM
  • COLOR_GREEN、QUALITY_HIGH
  • COLOR_GREEN、QUALITY_ULTRA
  • COLOR_BLUE and QUALITY_LOW
  • COLOR_BLUE and QUALITY_MEDIUM
  • COLOR_BLUE and QUALITY_HIGH
  • COLOR_BLUE and QUALITY_ULTRA

Unity がコンパイルするバリアントの数は、キーワードのセットを増やせば増や すほど急速に増えていきます。例えば、かなり典型的なユースケースを考えてみましょう。シェーダーが、それぞれ 2 つのキーワード (<feature name>_ON<feature name>_ OFF) を持つ多くのキーワードセットを持っている場合です 。シェーダーがそのキーワードセットを 2 個持っている場合、これは 4 つのバリアントになります。シェーダーがそのキーワードセットを 10 個持っている場合は、1024 つのバリアントになります。

シェーダーバリアントの重複排除

コンパイル後、Unity は同一パス内の同一バリアントを自動的に識別し、これらの同一バリアントが同じバイトコードを指すようにします。これを 重複排除 と呼びます。

Deduplication prevents identical variants in the same Pass from increasing file size; however, identical variants still result in wasted work during compilation, and increased memory usage and shader loading times at runtime. With this in mind, it is always best to strip unneeded variants.

シェーダーのバリエーションとシェーダーのキーワード
シェーダーキーワード