夜風のMixedReality

xRと出会って変わった人生と出会った技術を書き残すためのGeekなHoloRangerの居場所

ShaderをSRPBatcherに対応させる。

本日はShader学習枠です。

UnityのURPなど新しいレンダーパイプラインではレンダリングにおける最適化の手法としてSRPBacherを使用することができます。

筆者もよく使用するものの仕組みなど深く理解できていない部分があったため今回は勉強していきます。

〇SRPBathcherとは?

 SRP BacherはUnityのレンダーパイプラインであるSRP(Scriptable RenderPipeline)で使用できる最適化手法です。つまり冒頭で記述した通りURP、HDRPでは使用できクラシックなビルドインレンダーパイプラインでは使用ができません。

はじめにそもそもバッチングという処理自体よく聞くけどよくわかっていなかったのでこの際さらっていきます。

〇バッチング(バッチ処理)とは?

 バッチングは複数の処理をまとめる処理を指します。コンピュータ上では大量の処理を行わなくてはならないため一つ一つの処理をそれぞれ行うよりも、同様の処理はまとめて行っておいたほうが良いという考えの様です。

www.imkk.jp

 われわれ人間も数式などを解くときに一つ一つ計算するのではなくある規則の部分は最初に計算してしまうという事がありますのでそれに似た考えでしょうか?

〇Untiyの1フレームで行われているレンダリング処理

 次にUnityにおいて1フレームの間に行われている処理を見ていきます。

 こちらのドキュメントに詳しく記載されています。

learn.unity.com

①すべてのオブジェクトをチェックしレンダリングするか判別(CPU)

The CPU checks every object in the scene to determine whether it should be rendered.

②レンダリングするすべてのオブジェクトのデータをドローコールと呼ばれるコマンドに分ける(CPU)

The CPU gathers information about every object that will be rendered and sorts this data into commands known as draw calls.

ドローコールにはメッシュのデータとメッシュをどのようにレンダリングするか(Shaderの変数)が含まれます。

異なるオブジェクトのデータをまとめるバッチ処理が行われています。

③SetPassCallを行う(CPU)

The CPU may send a command to the GPU to change a number of variables known collectively as the render state

[Set Pass Call]とはCPUからGPUにコマンドを送りレンダリング状態と呼ばれる変数を更新することを指します。

これはGPUに次のメッシュのレンダリングに使用するための変数を伝える役割があります。

④CPUからGPUにドローコールを送る(CPU) ドローコールはSetPassCallで定義された変数を使用してメッシュをレンダリングするために使用します。

The CPU sends the draw call to the GPU

⑤CPUからのタスクを送信された順に処理する(GPU)

The GPU handles tasks from the CPU in the order that they were sent.

⑥現在のタスクがSetPassCallの場合レンダリング状態を更新、DrawCallの場合メッシュをレンダリングします。(GPU)

GPUではCPUから送られた多数がすべて処理されるまでこのプロセスを繰り返します。

If the current task is a SetPass call, the GPU updates the render state. If the current task is a draw call, the GPU renders the mesh. This happens in stages, defined by separate sections of shader code. This part of rendering is complex and we won’t cover it in great detail, but it’s useful for us to understand that a section of code called the vertex shader tells the GPU how to process the mesh’s vertices and then a section of code called the fragment shader tells the GPU how to draw the individual pixels. This process repeats until all tasks sent from the CPU have been processed by the GPU.

〇SRPBacherでできること

前述のようにGPUでレンダリングを行う処理を[DrawCall]と呼びます。

通常[DrawCall]はマテリアルごとに呼ばれ、そのマテリアルの変数をGraphics APIへ送っています。

SRP Bacherを使用することでドローコールとドローコールの間の処理をまとめることで処理を早くする仕組みがあります。

もっと具体的にまとめるとSRP Bacherを使用することで同一のシェーダーを使用している複数のマテリアルで一つのSetPass Callで処理を行うことができます

〇SRPの仕組み

f:id:Holomoto-Sumire:20220113175549p:plain

公式ドキュメントの図がわかりやすいですが、CBUFFERにバインド(束ねる)しています。

SRP Batcherの処理はGPUメモリ上に格納されます(Persistent Material)。

では次に実際のShaderコードでSRPBatcherの導入を行います。

必要なことは1つだけです。Sampler以外の変数をCBUFFER_START(UnityPerMaterial)~CBUFFER_ENDブロックで囲うことです。

CBUFFER_START(UnityPerMaterial)
float4 col;
half value;
CBUFFER_END

この際Samplerを入れないのは推測ですがもともと画像データはメモリに格納されているためではないかと思っています。

SRP Batherに対応しているかどうかを確認するにはUnityのプロジェクトウィンドウでShaderファイルを選択し、inspectorウィンドウの表記を確認します。

SRP Batherに対応している場合[Compatible]と表示されます。

f:id:Holomoto-Sumire:20220113185905j:plain

対応していない。対応できていない場合は[not compatible]と表示されます。

f:id:Holomoto-Sumire:20220113185803j:plain

以上でSRPBatherに関して簡単にまとめてみました。

CBUFFERなど今回学んだ点に関してもまだよくわかっていない点もあるので、スキルアップのためにまた深堀してみたいです。

〇参考ドキュメント

docs.unity3d.com