シェーダーのコンパイルは複数のステップからなる長いプロセスです。最初のステップの 1 つは、シェーダーソースの前処理です。Unity 2020.1 ベータ版では、このコンパイルステップを実行するための新しいカスタムソリューションである「Caching Shader Preprocessor」が導入されています。これは、プラットフォームコンパイラーのプリプロセッサーよりも最大 25% 高速で、C 標準に忠実に追従しつつ、新しい機能を提供します。
Unity を使用する人なら誰でも、直接的あるいは間接的にシェーダーを扱うことになります。シェーダーは GPU 上で実行されるプログラムであり、オブジェクトがどのように画面にレンダリングされるかを決定します。例えば、ポイントライトがシーンに追加された場合、それに反応する必要のあるオブジェクトは、ポイントライトの扱い方を定義する別のシェーダーバリアントを使用します。
まだ出現していない新しいシェーダーバリアントが使われている場合はいつでも、Unity エディターはそれをコンパイルしなければなりません。また、ターゲットデバイス上で動作するようにアプリケーションをビルドする時も、エディターは必要なシェーダーをすべてコンパイルする必要があります。
Caching Shader Preprocessor をオン/オフするチェックボックスは、エディター設定の Shader Compilation セクションにあります。
このブログ記事の残りの部分では、シェーダーを書いている場合に役立つと思われる技術的な詳細をカバーします。
新しいプリプロセッサーは、中間的な前処理データをキャッシュして、シェーダーのインポートとコンパイル時間を短縮します。このキャッシュにより、エディタはインクルードファイルの内容が変更されるまでインクルードファイルを解析する必要がなくなり、同じシェーダーの複数のバリアントをより効率的にコンパイルできるようになります。新しいプリプロセッサーを有効にすると、プロジェクト内のシェーダーがインクルードファイルの大部分を共有している場合に最も顕著な効果を発揮します。
異なるシェーダーコンパイラーのバックエンドには、それぞれ独自のプリプロセッサーが付属しています。コンパイラーが実行される前に標準化されたカスタムプリプロセッサーを実行することで、現在または将来使用されるどのコンパイラーバックエンドに対してもシェーダーコードの互換性が確保され、Unity のバージョン間でのプロジェクトのアップグレードが容易になります。
シェーダーのインポート時に同じプリプロセッサーが使用されるようになり、シェーダーのコンパイルパラメータ(#pragma ディレクティブ)をチェックするために以前採用されていたプレーンテキスト解析ソリューションを置き換えることができるようになりました。これにより、条件付きの#pragma ディレクティブの選択や、それらのディレクティブをインクルードファイルに入れることができるなど、追加の新機能を提供できるようになりました。
前処理されたソースを表示
シェーダーのインスペクターに「Preprocess only」チェックボックスが追加され、コンパイル済みのシェーダーコードと前処理済みのシェーダーのソースの表示を切り替えることができるようになりました。この機能は、シェーダーを開発している人にとって非常に便利で、シェーダーのデバッグを容易にします。
インクルードファイルのシェーダーコンパイルパラメーター
新しく「#include_with_pragmas」プリプロセッサーディレクティブを導入しました。これは、シェーダーの開発者がコンパイル設定を制御する #pragma ディレクティブをインクルードファイルに記述できるようにするものです。これらは通常の #include ディレクティブと同じように動作しますが、シェーダーのインポート時に無視されません。
この違いがシェーダーのインポート時間を最小化します。この機能がなければ、シェーダーに含まれるすべてのファイルに対してプリプロセッサーを実行する必要が出てきます。
古いシェーダーのインポートパスは新しいディレクティブを無視します。
条件付きシェーダーコンパイルディレクティブの選択
シェーダーのインポート中にプリプロセッサーを実行すると、シェーダーのコンパイルを制御する#pragma ディレクティブをプリプロセッサーの条件式でラップすることができます。
すべての条件式が #pragma の選択に影響を与えるわけではありません。プリプロセッサーは、条件式の引数がどこから来るかを検出します。これにより、再帰を防ぎ、シェーダーのコンパイルパイプラインへの影響を最小限に抑えます。条件式が #pragma ディレクティブのレポートに影響を与えるのは、一般的なマクロ定義(Unity バージョンまたは UNITY_OLD_PROPROCESSOR マクロ)、ユーザーマクロ定義、またはビルドターゲットに依存し、他の手段で設定できないプラットフォームキーワードに依存している場合に限られます。最後のものには、SHADER_API_DESKTOP、SHADER_API_MOBILE、UNITY_NO_CUBEMAP_ARRAY、UNITY_FRAMEBUFFER_FETCH_AVAILABLE、UNITY_USE_NATIVE_HDR、UNITY_NO_RGBMのほか、コンソール用のSHADER_API_
正しい使用例:
#pragma vertex vert #if defined(SHADER_API_XBOXONE) || defined(SHADER_API_PS4) #pragma fragment ConsoleFrag #elif defined(SHADER_API_SWITCH) || defined(SHADER_API_MOBILE) #pragma fragment MobileFrag #else #pragma fragment DesktopFrag #endif
正しくない使用例:
#pragma multi_compile __ A B #pragma vertex vert #if defined(A) #pragma fragment FragA #elif defined(B) #pragma fragment FragB #else #pragma fragment Frag #endif
前処理動作の変更
新しいシェーダー前処理ソリューションについて注目すべき動作の変更点は以下のとおりです。
古いシェーダーのインポートパイプラインでは、UNITY_OLD_PREPROCESSOR マクロが定義されるようになりました。これは、2 種類のプリプロセッサーを区別するために使うことができます。
Caching Shader Preprocessor は新しい機能です。Unity 2020.1 では実験版機能とマークされ、すべてのプラットフォームとレンダーパイプラインに適用されます。
2020 年のバージョンサイクルの終わりまでに完全に利用できるようにする予定ですので、Unity 2020.1 ベータ版でこの機能をぜひお試しいただき、フォーラムにフィードバックをお寄せください。
Is this article helpful for you?
Thank you for your feedback!