3
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

UnityのSRP BatcherでCPU負荷を軽減する

Last updated at Posted at 2022-02-11

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
SampleScene.png

ShaderGraphで「DefaultLit」を作成し、マテリアルを3つ作成して色だけ変えてあります
このマテリアルをCube/Sphere/Capsuleに割り当てています

FrameDebugerの変化

FrameDebuger_ON_OFF.png

同一シェーダーの描画が「SRP Batch」としてまとめられています

Statisticsの変化

Statistics比較_BuiltinRP_SRPBatch.png

SetPassが減っています
FPSやBatchesには変化がありませんでした

SetPassが減ってなにがうれしいの?

SetPassは「マテリアルの設定値をCPUがGPUに教える処理」で、CPUの負荷が軽減されます

これはイコールFPS改善につながるわけではありません
FPSはメモリアクセスやGPUなど多彩な要因で数値が下がっていきます
SRP Batcherを使ってもFPSが変わらないならボトルネックは別の場所にあります

UnityはSRP Batcherの効果を計測するために専用のスクリプトを配布しています

これを使って別のシーンを比較しました

サンプルシーン

SRPBatcher負荷テスト30ms.gif

ShaderGraphを7つのマテリアルにし、19x19の4種類のメッシュに割り当てました
またそれぞれは上下に移動し、RGBの移動する点光源によってライティングされています

SRPBatcherBenchmark

Profiler比較.png

「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はマテリアルが違っても同一シェーダーなら高速化されるので
そこが大きな違いとなります

他参考資料

3
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?