![見出し画像](https://assets.st-note.com/production/uploads/images/26407806/rectangle_large_type_2_fbc80f8fee1ef7eab612511a58dc6cc1.png?width=1200)
[Unity]ShaderVariantについて~後編:ShaderVariantと最適化周り~
ShaderVariantシリーズの最後です。
前編では、ShaderVariantとは何なのか?
中編では、AssetBundleとShaderVariantの関係ということで書いてきました。
■最後は ShaderVariantと最適化周りです
ShaderVariantに関連する最適化の話としては、以下の3点があります。
1.Keyword変更によるVariant切り替え時にCreateGPUProgramの負荷が出てしまう問題
2.コンパイル対象のVariantが多くてビルドに時間がかかる問題
3.ShaderVariantが多くために実行時のメモリを多く占有してしまう問題
それぞれに対して、書いていきたいと思います。
■Keyword変更によるVariant切り替え時にCreateGPUProgramの負荷が出てしまう問題
![画像2](https://assets.st-note.com/production/uploads/images/26407839/picture_pc_8bd0c1ccac669873cd8c07f55b5911f3.png?width=1200)
ライト環境が変わったりしたときに、思わぬ形でShaderVariant切替が起こってしまうことがあります。その結果、急にスパイクが起こるといったことが発生します。
Profiler上では「Shader.CreateGPUProgram」という名前で出てきます。
「Shader.CreateGPUProgram」は、ShaderVariantを利用する前のセットアップ処理です。
Unityでは必要になるまではセットアップ処理を行わないので、このように急な負荷となって現れます。
※2018.4.6f1以降、2019.3以降であれば、Profilerのタイムライン表示でKeywordが出てきます。
・解決策
これを回避するには、中編で紹介したShaderVariantCollectionを使います。
ShaderVariantCollection.Warmupを事前に呼び出しておく事で、事前に「Shader.CreateGPUProgram」を呼び出すことになります。
[2024/3/28]追記
こちらにもあるようにDX12, Vulkan, MetalといったAPIでは頂点レイアウトやレンダー ターゲットの設定がプリウォームに使用されたデータと異なる場合、グラフィックス ドライバー内で別途ウォームアップされないといけません。
これらのAPIを利用している場合、ダミーの描画を実際のMesh・RenderTargetで行う必要があります。
■コンパイル対象のVariantが多くてビルドに時間がかかる問題
![画像1](https://assets.st-note.com/production/uploads/images/26404713/picture_pc_e9c7edd73acd80ca3e21d9e6dae477f3.png)
ビルドするときに、画像のように「Compiling shader variants」で長く掛かってしまっていることないでしょうか?
ビルドの対象とするVariant数だけ処理が行われますので、対象とするVariantが多いと問題となります。
・解決策
「Stripping Scriptable Shader Variant」を利用する事で、開発者側でどのVariantをビルドに含めるかの制御が可能になります。
せっかくShaderVariantCollectionを作ったので、プロジェクト内にあるShaderVariantCollectionにあるものだけがビルドに含まれれば良いのに…
そう思って下記を作成しました。
これをプロジェクトに入れる事で、ShaderVariantCollectionにあるShaderVariantのみがビルド対象になり、ビルド時間が減ります。
ただ ShaderVariantCollectionが正しく設定されている事が大前提になりますので、取り扱いにはご注意ください。
■ShaderVariantが多くために実行時のメモリを多く占有してしまう問題
![画像3](https://assets.st-note.com/production/uploads/images/26410728/picture_pc_56aefb50a48ef3d824b1758bda3a14ab.png?width=1200)
この画面はPackageManagerで取得したMemoryProfiler上で、「 Table->Alloc->ByRoot」をした後に、[Object]でグループ化して確認できます。
ShaderVariantが多いと、MemoryProfiler上で計上される「ShaderLab」が大きくなります。スクリーンショットでは7MBほどですが、多くなると数十MBなど非常に大きなメモリ消費になる事もあります。
・解決策
これはビルドに含まれるShaderVariantを減らすことで、ビルド時間を減らすのと同時に実行時のメモリ消費にも有効になります。
ビルドの時と同じく「Stripping Scriptable Shader Variant」などを使って余計なものを削除することが有効になります。
■まとめ
前編では、ShaderVariantとは何なのか?
中編では、AssetBundleとShaderVariantの関係
後編では、ShaderVariantと最適化周り
以上、ShaderVariantについてでした。
追記:番外編
この記事が気に入ったらサポートをしてみませんか?