Version: 2022.3
言語: 日本語
シェーダーアセット
非同期シェーダーコンパイル

シェーダーのコンパイル

概要

プロジェクトをビルドするたびに、Unity エディターはビルドに必要なすべてのシェーダーをコンパイルします。必要なグラフィックス API ごとに、必要なシェーダーバリアントをすべてコンパイルします。

Unity エディターでは、すべてを先行してコンパイルすることはありません。すべてのグラフィックス API に対応するすべてのバリアントをコンパイルするには、非常に長い時間がかかるからです。

その代わりに、Unity エディターは以下のようにしています。

  • シェーダーアセットをインポートする場合、一部の最小限の処理 (サーフェスシェーダーの生成など) を行います。
  • シェーダーバリアントを表示する必要がある場合、Library/ShaderCache フォルダーを確認します。
  • 以前にコンパイルされたシェーダーバリアントが同一のソースコードを使用していることを見つけた場合、それを使用します。
  • 一致するものが見つからなかった場合。必要なシェーダーバリアントをコンパイルして、それをキャッシュに保存します。

シェーダーのコンパイルは、UnityShaderCompiler というプロセスを使って行われます。複数の UnityShaderCompiler プロセスを開始することができます (通常、マシンの CPU コアごとに 1 つ)。そのため、プレイヤーのビルド時にシェーダーのコンパイルを並行して行うことができます。エディターがシェーダーをコンパイルしていない間はコンパイラー処理は行われず、コンピューターのリソースを消費しません。

頻繁に変更されるシェーダーが沢山ある場合は、シェーダーキャッシュフォルダーが非常に大きくなる可能性もあります。このフォルダーの削除は安全で、Unity がシェーダーバリアントを再コンパイルするだけです。

プレイヤーのビルド時には、すべての “まだコンパイルされていない” シェーダーバリアントがコンパイルされるため、たまたまエディターがそれらを使用しなかった場合でもゲームデータに含まれます。

さまざまなシェーダーコンパイラー

異なるプラットフォームは、シェーダープログラムのコンパイルに異なるシェーダーコンパイラーを使用します。以下はその例です。

  • DirectX を使用するプラットフォームは、Microsoft の FXC HLSL コンパイラーを使用します。
  • OpenGL (Core & ES) を使用するプラットフォームは、Microsoft の FXC HLSL コンパイラーを使用し、その後、HLSLcc を使用して、バイトコードを GLSL への変換を行います。
  • Metal を使用するプラットフォームは、Microsoft の FXC HLSL コンパイラーを使用し、その後、HLSLcc を使用して、バイトコードを Metal に変換しています。
  • Vulkan を使用するプラットフォームは、Microsoft の FXC HLSL コンパイラーを使用し、その後、HLSLcc を使用して、バイトコードを SPIR-V に変換します。
  • コンソールプラットフォームなどその他のプラットフォームでは、それぞれのコンパイラーを使用します。
  • サーフェスシェーダーステップ は、コード生成解析ステップのために HLSL と MojoShader を使用します。

pragma ディレクティブ を使用して、さまざまなシェーダーコンパイラーの設定を行うことができます。

キャッシングシェーダープリプロセッサー

シェーダのコンパイルにはいくつかのステップがあります。最初のステップの 1 つは前処理です。このステップでは、プリプロセッサー と呼ばれるプログラムが、コンパイラーのシェーダーソースコードを準備します。

In previous versions of Unity, the Editor used the preprocessor provided by the shader compiler for the current platform. Now, Unity uses its own preprocessor, also called the Caching Shader Preprocessor.

The Caching Shader Preprocessor is optimized for faster shader import and compilation. It works by caching intermediate preprocessing data, so the Editor only needs to parse include files when their contents change, which makes compiling multiple variants of the same shader more efficient.

キャッシングシェーダープリプロセッサーと従来の動作の違いについての詳細は、Unity フォーラムの New shader preprocessor を参照してください。

AssetBundles and shaders

If you use AssetBundles, Unity might compile duplicate shaders if you reference one shader in two or more objects. For example:

  • A material in an AssetBundle and a material in a built scene reference the same shader.
  • Multiple AssetBundles contain materials that reference the same shader outside an AssetBundle.

This can increase the memory and storage space shaders use, and break draw call batching.

To avoid this, you can use the following approaches:

  • Load an AssetBundle that contains all your shaders first, then load and instantiate AssetBundle assets that reference the shaders. See AssetBundle Dependencies for more information.
  • Structure your AssetBundles to minimise duplication. See Asset Duplication for more information.

You can add materials and shader variant collections to an AssetBundle to specify which shader variants to include.

If you create a single AssetBundle, some shaders might stay in memory even if they’re no longer needed, because you cannot partially unload an AssetBundle. You can avoid this by creating a separate AssetBundle for each group of shaders you use together, for example a ‘forest’ AssetBundle and a ‘desert’ AssetBundle. See Managing loaded AssetBundles, or Memory management in the Addressables system if you use Addressables.

You can use the Asset Bundle Browser to check which assets in AssetBundles depend on other assets, and find out if any assets are duplicated.

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

ゲームのビルド中、Unity は内部シェーダーバリアントの一部がゲームで使用されていないことを検出し、ビルドデータから削除 (“ストリップ”) します。詳しくは、シェーダーバリアント を参照してください。

シェーダーアセット
非同期シェーダーコンパイル