非同期シェーダーコンパイルはエディターのみの機能で、多くのシェーダーバリアントを持つ複雑なシェーダーオブジェクトがある場合、ワークフローを改善することができます。
このページには以下の情報が含まれています。
シェーダーオブジェクトには数百から数千の シェーダーバリアント が含まれている場合があります。シェーダーオブジェクトをロードするときにすべてのバリアントをコンパイルすると、インポートプロセスは非常に遅くなります。そのようにせず、エディターは最初にシェーダーバリアントに遭遇したときに、必要に応じてシェーダーバリアントをコンパイルします。
これらのシェーダーバリアントをコンパイルすると、グラフィックス API やシェーダーオブジェクトの複雑さに応じて、エディターがミリ秒から数秒にわたってストール (待機) することがあります。このようなストールを避けるために、非同期シェーダーコンパイルを使用してシェーダーバリアントをバックグラウンドでコンパイルし、その間プレースホルダーシェーダーオブジェクトを使用することができます。
非同期のシェーダーコンパイルは以下のように行われます。
以下の例外があります。
DrawProcedural
や CommandBuffer.DrawProcedural
を使用してジオメトリを描画する場合、エディターはダミーのシェーダーを使用しません。代わりに、エディターはシェーダーバリアントをコンパイルし終わるまで、このジオメトリの描画をスキップします。シェーダーの非同期コンパイルは、デフォルトで有効になっています。
シェーダーの非同期コンパイルを有効または無効にするには、以下を行います。
ノート: この方法で非同期シェーダーコンパイレーションを有効/無効にすると、デフォルトでは シーンとゲームビューにのみ影響します。エディターの他の部分で使用したい場合は、カスタムエディターツールと非同期シェーダーコンパイル を参照してください。
C# スクリプトで特定のレンダリングコマンドの非同期シェーダーコンパイルを有効または無効にすることができます。
以下の説明では、即時のスコープと、CommandBuffer のスコープで、機能を有効または無効にする方法を示しています。
即時スコープでは、ShaderUtil.allowAsyncCompilation
を使用します。
手順は以下のとおりです。
ShaderUtil.allowAsyncCompilation
の現在の状態を変数に格納します。ShaderUtil.allowAsyncCompilation
を false
に設定します。ShaderUtil.allowAsyncCompilation
を以前の状態に戻します。以下は擬似コードの例です。
// 現在の状況を保存
bool oldState = ShaderUtil.allowAsyncCompilation;
// 非同期コンパイルを無効にする
ShaderUtil.allowAsyncCompilation = false;
// プレースホルダーシェーダーを使用しないレンダリングコードを入力
Graphics.DrawMesh(...);
// 古い状態を復元
ShaderUtil.allowAsyncCompilation = oldState;
CommandBuffer
スコープでは、ShaderUtil.SetAsyncCompilation
とShaderUtil.RestoreAsyncCompilation
を使用できます。
ShaderUtil.SetAsyncCompilation
を呼び出して false
に設定します。CommandBuffer の後続のコマンドでは非同期コンパイルはできません。Shader.Util.RestoreAsyncCompilation
を呼び出して、非同期シェーダーコンパイルの状態を復元します。以下はその例です。
// CommandBuffer を作成
CommandBuffer cmd = new CommandBuffer();
// 後続のコマンドの非同期コンパイルを無効にします
ShaderUtil.SetAsyncCompilation(cmd, false);
/// プレースホルダーシェーダーを使用しないレンダリングコマンドを入力
cmd.DrawMesh(...);
// 古い状態を復元
ShaderUtil.RestoreAsyncCompilation(cmd);
強制的に、特定のシェーダーオブジェクトの非同期シェーダコンパイルを無効にするようにし、常に同期的にコンパイルすることができます。これは、レンダリングの開始時に常に存在するデータ生成シェーダーオブジェクトに適したオプションで、比較的短時間でコンパイルできます。これは、高度なレンダリング を行っている場合に、必要となる可能性が高いでしょう。
シェーダーオブジェクトの同期コンパイルを強制するには、#pragma editor_sync_compilation
ディレクティブ をシェーダーのソースコードに加えます。
ノート: レンダリング中に新しいシェーダーバリアントに遭遇する複雑なシェーダーオブジェクトに対して、強制的に同期コンパイルを行うべきではありません。エディターでのレンダリングが滞る可能性があります。
C# の API を使って、非同期のシェーダコンパイルの状態を監視し、その状態が変化したときに操作を行うことができます。
これは 高度なレンダリング で最も有効な方法です。プレースホルダーのシェーダーが生成されたデータを汚染する場合は、コンパイルが完了するまで待って、汚染されたデータを破棄し、正しいシェーダーバリアントで新しい一揃いを再生成できます。
調べたいマテリアルがすでにわかっている場合は、ShaderUtil.IsPassCompiled
を使って、シェーダーバリアントのコンパイル状況を確認することができます。ステータスが Uncompiled から Compiled に変わると、コンパイルが完了です。
どのマテリアルを調べたいのかわからない場合や、複数のマテリアルを調べたい場合は、 ShaderUtil.anythingCompiling
を使って、Unity がシェーダーバリアントを非同期にコンパイルしているかどうかを検出することができます。これが true
から false
に変わると、現在のすべてのコンパイルは完了です。
高度なレンダリングソリューションでは、データを一度生成し、後のフレームで再利用することが重要です。エディターがこのプロセスでプレースホルダーシェーダーを使用すると、生成されたデータを汚染する可能性があります。これが発生すると、シェーダーバリアントのコンパイルが終わった後でも、シーンにシアン色やその他のレンダリングアーティファクトが表示されます。
これを回避するには、以下を行います。
デフォルトでは、 非同期シェーダーコンパイルはゲームビューとシーンビューで動作します。カスタム製のエディターツールで使用したい場合は、カスタムツールの C# を使って有効にできます。
そのために、特定のレンダリングコールに対して非同期シェーダーコンパイルを有効 にします。
カスタムツールを使って、マテリアルごとのプレースホルダーシェーダー以外のものを描画することができます。このようにして、シアンになる可能性のあるシェーダーバリアントでレンダリングすることを避け、代わりにシェーダーバリアントのコンパイル中に何か他のものを描画することができます。
特定のシェーダーバリアントがコンパイルされたかどうかを確認するには、非同期シェーダーコンパイルの検出 を参照してください。
手動でコンパイルを開始するには、ShaderUtil.CompilePass
を使います。このようにして、シアンのプレースホルダーでのレンダリングを避け、代わりにシェーダバリアントのコンパイル中に他のものを描画することができます。