SRPではSRP Batcherという描画負荷軽減テクニックが追加されています
強力な機能ですので調べてみました
SRPってなに
ScriptableRenderPipeline
過去解説したのでこちらをどうぞ
簡単に言うとUnityのC#レンダリングパイプライン
URPもSRPの実装の一つ
SRP BatcherはSRP全般で使えるのでURPでもHDRPでも使える
Built-in RPでは使えません
基礎知識
レンダリングする際には、まずCPUが全てのレンダリング対象オブジェクトの情報を集めます。
次にこれらのうち、マテリアルが同じだったりといったバッチング条件に合うものを一つのメッシュにまとめます。
こうしてまとめたメッシュごとに、Batchという処理単位を作ります。その後このBatchごとに、SetPass Call -> Draw Callの順に処理をしていきます。
SetPass Callとは、マテリアルの設定値をCPUがGPUに教える処理です。
もし一回前にSetPassした時とマテリアルが同じであれば、SetPass Callは不要なのでスキップされます。その後Draw Callが呼ばれます。
Draw Callとは、CPUがGPUに、SetPass Callで設定された値を用いてメッシュを描画することを命令することです。
SRP Batcherの概要
Built-in RPではマテリアルごとにGPUに送信してた
SRPではそこを見直してパラメータ部分だけまとめてGPUに送信するようにした
同一シェーダーのマテリアルを同一SetPassで描画してくれます
あくまでSetPassが減るだけなのでDrawCallの回数自体は変わりません
シェーダーバリアントが少なく、多くのマテリアルに分岐してるメッシュの描画を効率化するのが目的
簡単なサンプルで比較
実際にプロファイルしながら見てましょう
FrameDebugerを開きながらSRP BatcherをON/OFFします
サンプルシーン
検証 | バージョン |
---|---|
Unity | 2020.3.26f1 |
UDP | 10.8.1 |
ShaderGraphで「DefaultLit」を作成し、マテリアルを3つ作成して色だけ変えてあります
このマテリアルをCube/Sphere/Capsuleに割り当てています
FrameDebugerの変化
同一シェーダーの描画が「SRP Batch」としてまとめられています
Statisticsの変化
SetPassが減っています
FPSやBatchesには変化がありませんでした
SetPassが減ってなにがうれしいの?
SetPassは「マテリアルの設定値をCPUがGPUに教える処理」で、CPUの負荷が軽減されます
これはイコールFPS改善につながるわけではありません
FPSはメモリアクセスやGPUなど多彩な要因で数値が下がっていきます
SRP Batcherを使ってもFPSが変わらないならボトルネックは別の場所にあります
UnityはSRP Batcherの効果を計測するために専用のスクリプトを配布しています
これを使って別のシーンを比較しました
サンプルシーン
ShaderGraphを7つのマテリアルにし、19x19の4種類のメッシュに割り当てました
またそれぞれは上下に移動し、RGBの移動する点光源によってライティングされています
SRPBatcherBenchmark
「CPU Rendering time」が0.51msから0.20msに減少しています
Global Main Loopは21.98msから2.14msに減少しています
期待通りの高速化ができました🎉
⚠SPR Batcherの注意点⚠
SRP Batcherは何にでも適用できるわけではありません
ShaderLabで対応するには考慮が必要です ・シェーダーバリアント部分をCBUFFERの定義にいれる必要がある ・HLSLで記述する必要がある ・使用するシェーダーバリアントはできるだけ少なくする必要があります
URPやHDRPでデフォルトで提供されているシェーダーは対応されています
ShaderGraphも自動で対応してくれます
GPUインスタンシングとの共存はできません
詳しくは公式ドキュメントを参照ください
他の高速化と何が違うの?
DynamicBatching
同じマテリアルを共有していて特定条件を満たしている場合、1つのDrawCallにまとめて処理する機能
DrawCall自体の処理が重くなってしまうなどデメリットになるケースも多数あるため
現在では非推奨となっています
MaterialPropertyBlock
コードでMaterialのパラメータを変更する場合、普通であればMaterialインスタントを増やしてしまう
色を変えただけでインスタント増やされるのは塵積で馬鹿にならないコストになりますよね
これでMaterialインスタントを増やさないで済むのがMaterialPropertyBlock
※Draw CallやSetPass Callが減るわけではない
※あくまでもコードで変更したときMaterialインスタンスを増やさないだけ
GPUインスタンシング
GPUインスタンシングでは同一マテリアルのメッシュを大量に描画する場合に高速化されます
SRP Batcherはマテリアルが違っても同一シェーダーなら高速化されるので
そこが大きな違いとなります