Branching is one way of introducing conditional behavior into shader code.
このセクションでは、以下の手法について説明します。
シェーダーコードにおける条件分岐に関する概要と、どちらの手法をどのような場合に使用するかについては、シェーダーコードにおける条件分岐 を参照してください。
シェーダープログラムにコンパイル時に評価される条件文が含まれている場合は、静的分岐が使用されます。コンパイラーは使用されていない分岐側のコードを除外するため、そのコードはコンパイルされたシェーダープログラムには含まれません。
内部的には、Unity はシェーダーバリアントの作成時に静的分岐を使用します。ただし、静的分岐自体には、シェーダーバリアントが持つパフォーマンス上のデメリットはありません。
静的分岐の主なメリットは、ランタイムのパフォーマンスに悪影響を与えないことです。静的分岐の主なデメリットは、コンパイル時間にしか使用できないことです。
静的分岐を使用する場合、コンパイラーがシェーダープログラムから不要なコードを除外します。この結果、必要なコードのみを含む、小さく特化したシェーダープログラムが作成されます。静的分岐にはランタイムのパフォーマンスコストがありません。実際には、小さなプログラムほど、ロード時間が短くなりランタイムのメモリ使用量も少なくなる傾向にあります。
静的分岐を使用するには、条件がコンパイル時間に一定である必要があります。つまり、ランタイムに異なる条件用にコードを実行するために使用することはできません。
シェーダーへの静的分岐の使用は、以下の方法で行います。
#if
、#elif
、#else
および #endif
プリプロセッサーディレクティブまたは #ifdef
および #ifndef
プリプロセッサーディレクティブを使用して静的分岐を作成します。if
ステートメントは動的分岐にも使用できますが、これを行う代わりに、コンパイラーは、コンパイル時間の定数値を検出して静的分岐を作成します。ノート: 静的分岐はハンドコーディングされたシェーダーでのみ使用可能です。Shader Graph で静的分岐を作成することはできません。
シェーダープログラムにランタイムで評価される条件文が含まれている場合は、動的分岐が使用されます。
動的分岐には、均一 (uniform) 変数に基づく動的分岐と、それ以外のランタイム値に基づく動的分岐の 2 種類があります。均一値がドローコール全体を通して一定であるため、通常は均一変数に基づく分岐のほう効率的です。
動的分岐の主なメリットは、プロジェクト内のシェーダーバリアントの数を増やすことなくランタイムで条件分岐を使用できることです。動的分岐の主なデメリットは、GPU パフォーマンスに影響を与えることです。
GPU パフォーマンスへの影響は、ハードウェアによって、またシェーダコードによって異なります。その理由は以下の通りです。
一般的に、コードが均一値で分岐し、両方の分岐の処理負荷がほぼ同様である場合は、GPU パフォーマンスへの影響は小さい傾向にあります。ただし、必ずアプリケーションをプロファイリングし、ケースバイケースでメリットとデメリットを検討する必要があります。
ノート: 動的分岐を使用すると、シェーダープログラムが大きくなる可能性もあります。これは、全ての条件のコードが同じシェーダープログラムにコンパイルされるためです。ただし、通常は、こうした大きなファイルがロード時間やメモリ使用量に与える影響は、シェーダーバリアントによる影響ほどは大きくありません。
シェーダーで条件分岐を使用する他の方法と、自身のユースケースにどの手法が適しているかの判断方法については、シェーダーにおける条件分岐 を参照してください。
シェーダーへの動的分岐の使用は、以下の方法で行います。