序文
このシリーズは、パフォーマンスの最適化に関する少しの知識であり、毎日のゲーム開発とパフォーマンスのポイントです。この記事は、このシリーズの記事の2番目の記事です。前の記事はリンクされています。
初期Unity
のバッチの処理方法は、主に次の3つでした。
Static Batching
Dynamic Batching
GPU Instancing
また、使用には厳しい制限があります。Unity
発売後、SPR
バッチ処理の範囲と効率を向上させるために、新しいバッチ処理方法が提供されSPR Batcher
ます。この記事では、これらのバッチ処理技術を簡単に紹介します。
ドローコール、バッチャー、サットパスコール
バッチ処理を理解する前に、CPU処理のレンダリングレートを測定するためのいくつかの参照値を理解する必要があります
Draw Call
Unityエンジンの初期段階では、レンダリングパイプラインでのCPUの処理段階は主にデータの準備と送信を行うためのアプリケーション段階であるため、レンダリング中のCPUのリソース消費は主に描画呼び出しの数によって測定されます。 Draw Callの処理段階はアプリケーション段階です。この数値は、CPUがGPUにデータを送信する回数を表します。DrawCall自体はデータストリームのほんの数バイトです。主なパフォーマンスの消費はデータにあります。 CPUの準備フェーズ。
Batcher
バッチ処理の出現により、すべてのレンダリングオブジェクトが描画呼び出しを生成するわけではないため、今回は新しいメジャーが提案されます:バッチャー
Set Pass Call
前述のようにCPU
、レンダリング段階では、パフォーマンス消費のピークは一般Draw Call
にデータ準備の段階ではないため、データ送信数を測定基準として使用することは正確ではありません。より多くのパフォーマンスを消費します。これは、CPU
レンダリング段階全体で最もパフォーマンスを消費するステップでもあるためUnity
、Set Pass Call
パフォーマンス消費の標準として使用されます。
主なバッチ技術の紹介
Unity
以下は、中国で一般的に使用されているバッチ処理方法の簡単な説明です。これらの説明は主にUnity
公式文書からのものであり、一部は直接コピーされており、情報は比較的正確です。
1、静的バッチ処理
Unity
公式文書によるとStatic Batching
、動作原理は次のとおりです。
- 静的なゲームオブジェクトをワールドスペースに変換し、それらの共有頂点とインデックスバッファを構築します。
- 有効に
Optimized Mesh Data
すると、頂点バッファを構築するときにシェーダーバリアントで使用されていない頂点要素を削除します。Unity
これを行うために、システムはいくつかの特別なキーワードチェックを実行します。たとえば、キーワードUnity
が検出されない場合、ライトマップはバッチから削除されます。LIGHTMAP_ON
UV
- 一連の単純な描画呼び出しは、同じバッチ内の表示されているゲームオブジェクトに対して実行され
Unity
、各呼び出し間で状態はほとんど変化しません。技術的には、描画Unity
呼び出しは削減されませんが、状態はそれらの間で変化します(これは多くのリソースを消費する部分です)。API
ほとんどのプラットフォームでは、バッチ処理は64kの頂点と64kのインデックスに制限されています(OpenGLES
48kのインデックスmacOS
は、 32kのインデックスは)
簡単に言えば、Static Batching
いくつかの小さなメッシュをマージしてメモリに戻すことにより、レンダリング操作を実行するときに、マージされたCPU
メモリを送信して一度に量GPU
を減らしますが、特定の制限があります。Draw Call
- オブジェクトは静的で移動できない必要があります
- マージされたオブジェクトは同じマテリアルを使用します
同時に、Static Batching
使用時に結合されたジオメトリを格納するために追加のメモリが必要になるため、ある程度のメモリの浪費が発生します。簡単に言えば、メモリを交換することで時間効率の良い操作が得られるため、CPU
パフォーマンス上の利点を得る際に不要なメモリの問題を回避するために、実際の状況に応じてレンダリングオブジェクトを慎重に追加する必要があります。
使用に関しては、最初に次のオプションにチェックマークStatic Batching
を付ける必要があります。Project Setting
Player
Static Batching
次に、Inspector
パネルでStatic Batching
必要なオブジェクトを確認できます。Batching Static
具体的な位置は次の図のようになります。
2、動的バッチ処理
Dynamic Batching
オブジェクトを共通のマテリアルとマージすることもできますが、オブジェクトは動的である可能性があり、このプロセスは動的であるため、チェックボックスをオンにする必要がProject Setting
あります。ただし、テンプレートでは、このオプションは構成ファイルに移動されています。特定の場所を図に示します。Player
Dynamic Batching
URP
URP
セットアップ手順は非常に簡単ですがDynamic Batching
、その使用条件は非常に厳しく、バッチ処理の効果を達成するには一連の資格を満たす必要があります。Unity
関係者はまた、ドキュメントに詳細なリストを作成しました。
-
動的ゲームオブジェクトのバッチ処理には頂点ごとのオーバーヘッドがあるため、バッチ処理は、合計で900以下の頂点属性と300以下の頂点を含むメッシュにのみ適用されます。シェーダーが頂点位置、法線、および単一のUVを使用する場合、最大300の頂点をバッチ処理できますが、シェーダーが頂点位置、法線、UV0、UV1、および接線を使用する場合は、180の頂点のみをバッチ処理できます。
-
GameObjectの変換に鏡像がある場合、それらのオブジェクトはバッチ処理されません(たとえば、+1スケールのGameObjectAと-1スケールのGameObjectBを一緒にバッチ処理することはできません)。GameObjectが基本的に同じであっても、異なるマテリアルインスタンスを使用すると、GameObjectが一緒にバッチ処理されなくなります。例外はシャドウキャスターレンダリングです。
-
ライトマップを含むゲームオブジェクトには、ライトマップインデックスとライトマップオフセット/スケールという追加のレンダラーパラメータがあります。一般に、動的ライトマップのGameObjectは、バッチ処理されるまったく同じライトマップの場所を指している必要があります。
マルチパスシェーダーはバッチ処理を中断します。 -
ほとんどすべてのUnityシェーダーは、フォワードレンダリングで複数のライトをサポートし、それらの追加パスを効果的に実行します。追加のピクセルごとのライトの描画呼び出しはバッチ処理されません。
従来の遅延(ライティングプリパス)レンダリングパスは、ゲームオブジェクトを2回描画する必要があるため、動的バッチ処理を無効にします
たくさんあるように見えますが、簡単な要約では、モデルは単純であるShader
必要があり、使用されるモデルは単一である必要がありますPass
。同時に、単一のPass
制限のため、遅延レンダリングの場合、照明は別々のPass
処理に分離されるため、照明されたオブジェクトは動的なバッチ処理操作を実行する方法がなく、直接ブロックされます。Dynamic Batching
3、GPUインスタンス化
GPU Instanceing
少数の描画呼び出しで、同じメッシュの複数のコピーを一度に描画(またはレンダリング)するために使用します。建物、木、草など、シーンで繰り返されるオブジェクトを描画する場合に便利です。
-
GPU Instanceing
各描画呼び出しで同じメッシュのみがレンダリングされますが、各インスタンスに異なるパラメーター(たとえば、色やスケール)を設定して、バリエーションを増やし、外観の繰り返しを減らすことができます。 -
GPU Instanceing
シーンごとに使用される描画呼び出しの数を減らすことができます。プロジェクトのレンダリングパフォーマンスを大幅に向上させることができます。
他のバッチ処理方法と同様に、GPU Instanceing
いくつかの使用制限もあります。
-
Unity
インスタンス化してGraphics.DrawMesh
呼び出す。サポートされていないことに注意してくださいSkinnedMeshRenderer
-
Unity
GPU
1回のインスタンス化された描画呼び出しで同じメッシュと同じマテリアルを共有するバッチゲームオブジェクトのみ。少数のメッシュとマテリアルを使用すると、インスタンス化の効率を向上させることができます。バリアントを作成するには、シェーダースクリプトを変更して、各インスタンスのデータを追加します
その説明の公式リンクは次のとおりです。GPUインスタンス化
上記は公式文書の説明GPU Instanceing
です。他の2つのバッチ処理方法とは異なり、同じ材料に加えて、同じメッシュを使用するオブジェクトに主に有効であることがわかります。そのため、名前Instanceing
が示すように、GPU
直接です。オブジェクトをインスタンス化してCPU
、シーンオブジェクトのデータコマンド準備のパフォーマンス消費を削減する技術的手段
4、SRPバッチャー
SRP Batcher
公式ドキュメントへのリンク:SRP Batcher、公式ドキュメントに移動したくないかどうかは関係ありません。また、ここに直接移動して、説明テキストを追加しました。
SRPバッチを有効にする:
を使用するSRP Batcher
には、プロジェクトでプログラム可能なレンダリングパイプラインを使用する必要があります。プログラム可能なレンダリングパイプラインは次のとおりです。
- ユニバーサルレンダリングパイプライン(
URP
) - HDレンダリングパイプライン(
HDRP
) - カスタマイズ
SRP
後者の2つの方法は一般的に使用されないため、この記事はURP
テンプレートに基づいて紹介されURP
ます。具体的な詳細については、この記事を確認してください:Urp(Universal Rendering Pipeline)へのUnityアップグレードプロジェクトと画面の後処理
プロジェクトでURPテンプレートを使用するURP
と、現在のプロジェクトの構成ファイルがリソースディレクトリにありSRP Batcher
、制御オプションが表示されます。
同時に、プロジェクトがURP
テンプレートの下にある場合、スイッチ制御オプションも構成ファイルに移行されますが、デフォルトのレンダリングパイプラインとDynamic Batching
比較すると、このテクノロジは、SRP Batcher
SRPバッチャーの原則:
Unity
、任意のマテリアルのプロパティは、フレーム内でいつでも変更できます。ただし、このアプローチにはいくつかの欠点があります。たとえばDrawCall
、新しい素材を使用する場合、やるべきことがたくさんあります。したがって、シーン内のマテリアルが多いほど、データのUnity
設定に使用する必要があります。この問題を解決する従来の方法は、レンダリングコストを最適化するために数を減らすことです。これは、が放出される前に多くのセットアップを行う必要があるためです。実際のコストは、それ自体からではなく、その設定から発生します(コマンドバッファーにプッシュする必要がある数バイトのみ)GPU
CPU
DrawCall
CPU
Unity
DrawCall
CPU
GPU DrawCall
DrawCall
Unity
GPU
説明で説明したようSet Pass Call
に、レンダリング段階でCPU
のゲームのパフォーマンス消費は、主にマテリアル切り替え段階でのいくつかのタスクに関連しており、新しいマテリアルの準備時間は、データバッファSPR Batcher
内のデータGPU
バッファの永続的な保存と交換されます、それによってデータ準備の圧力CPU
を減らします。CPU
SRP Batcher
一連のコマンドBind
とコマンドDraw GPU
をバッチ処理することにより、設定を減らします。特定のプロセスを図に示します。DrawCall
GPU
レンダリングパフォーマンスを最大にするには、これらのバッチをできるだけ大きくする必要があります。これを実現するには、同じシェーダーでできるだけ多くの異なるマテリアルを使用できますが、使用するシェーダーのバリエーションはできるだけ少なくする必要があります。
内側のレンダリングループでUnity
は、新しいマテリアルが検出されると、CPU
すべてのプロパティが収集され、さまざまな定数バッファがGPU
メモリ。GPU
バッファの数は、シェーダがその宣言方法によって異なります。CBUFFER
シーンが多くの異なるマテリアルを使用しているがシェーダーバリアントがほとんどない一般的なケースで処理を高速化するために、SRP
パラダイムをネイティブに統合します(GPU
データの永続性など)
SRP Batcher
は、マテリアルデータをGPU
メモリ内。マテリアルの内容が変更SRP Batcher
されない場合は、バッファを設定してバッファをアップロードする必要はありませんGPU
。実際、SRP Batcher
専用のコードパスを使用しGPU
てUnity
、次のような大きなバッファーのエンジンプロパティをすばやく更新します。
これがSRP Batcher
レンダリングワークフローです。SRP Batcher
専用のコードパスを使用して、大きなGPU
バッファーのUnity
エンジンプロパティをすばやく更新します。ここでCPU
は、上の画像のようにPer Object large buffer
マークたUnity
エンジンプロパティのみが処理されます。すべての資料はGPU
メモリCBUFFER
され、いつでも使用できます。これにより、レンダリングが高速化されます。理由は次のとおりです。すべてのマテリアルコンテンツがGPU
メモリた。専用コードは、すべてのオブジェクトごとのプロパティの大きなオブジェクトごとのプロパティを管理しますGPU CBUFFER
SRPバッチャーの制限:
SRP Batcher
コードパスでオブジェクトをレンダリングできるようにするには:
-
レンダリングされるオブジェクトは、メッシュまたはスキンメッシュである必要があります。オブジェクトをパーティクルにすることはできません。
-
シェーダーはと
SRP Batcher
互換性がある。すべての点灯およびHDRP
消灯シェーダーがこの要件を満たしています(これらのシェーダーの「パーティクル」バージョンを除く)。シェーダーをSRPバッチャーと互換性を持たせるには:URP
-
すべての組み込みエンジンプロパティは、名前付きで宣言する必要が
UnityPerDraw
あります。CBUFFER
たとえばunity_ObjectToWorld
またはunity_SHAr
-
すべての材料特性は
UnityPerMaterial
、CBUFFER
バッチパフォーマンステスト用
従来のバッチ:
一般的に、バッチ処理はシーンレンダリングのデータ処理を減らし、それによってCPU
レンダリング中のプレッシャーを減らすことです。Unity
パフォーマンス分析ツールを使用Profiler
すると、それに関連する値を簡単に確認できます。
クリックRendering
して、参加、、、および3つのバッチ処理テクノロジーなどのパラメーターの数にOpen Frame Debugger
固有のバッチ処理に関連する知識をパネルに表示しますStatic Batching
Dynamic Batching
GPU Instancing
Draw Call
もちろん、CPU
パフォーマンスの消費を分析してCPU
、セグメントのボトルネック情報を取得することもできます。
をクリックするCPU Usage
と、下のパネルで確認できますBatchRendener.Flush
。これは、レンダリングパフォーマンスに影響を与える可能性のある非常に注目に値するCPU
パラメータでありSelf
、時間のかかる現在の影響を評価できCPU
ます。
展開すると、最大4つのサブオプションが表示されます。
Render.Mesh
:CPU
バッチ処理できない対応して処理されたオブジェクトBatch.DrawInstanced
:処理に対応CPU
するGPU Instancing
処理対象の場合Batch.DrawStatic
:CPU
処理される対応するStatic Batching
オブジェクトBatch.DrawDynamic
:CPU
処理される対応するDynamic Batching
オブジェクト
上記のスクリーンショット分析のシナリオでは、バッチプロセス全体のリソース消費を分析し、それと時間の統計を作成するために、それぞれに1つを配置し、異なるバッチ操作を実行しました30000
。このバッチメソッドはここでは削除されています。シーン内のオブジェクトの特定のバッチメソッドは次のとおりです。Cube
Draw Call
Dynamic Batching
CPU
- 10000オブジェクト:
Static Batching
- 10000オブジェクト:
GPU Instancing
- 10000オブジェクト:
Dynamic Batching
- 2つの追加オブジェクト:処理されません
Profiler
パフォーマンスパフォーマンスの監視を通じてCPU
、3つのバッチ処理方法の運用効率は静的バッチ処理で最も高く、GPU Instancing
比較的Dynamic Batching
劣っています。シーンにオブジェクトが多数ある場合、観測された値は注目に値します。上記の分析方法で得られたものを表示しますGPU Instancing
。時間はそれ以上ですが、実際にはレンダリング段階全体Dynamic Batching
での2つのバッチ技術の合計時間は逆になります。モードを切り替えると結果がはっきりとわかります。に:CPU
Profile
Hierarchy
TimeLine
上図からわかるように、Dynamic Batching
それ自体で発生する時間(下の短い段落の合計)は比較的小さいですが、対応するBatchRendener.Flush
(上の段落)の時間が長くなるため、分析しています。使用におけるそれらの利点。、TimeLine
全体的な時間のかかる状況を分析するためにモードに切り替えることができます
具体BatchRendener.Flush
的な内容は、公式フォーラムの技術者の説明から理解できますUnity
。その人の元の言葉は次のとおりです。
SRPバッチャー:
プロジェクトでオンにすると、ブロッキングSRP Batcher
と同じように他のバッチ処理方法が機能しなくなることがわかりますが、違いは、この部分の特定のドキュメントの説明がなく、単純な仮定であるということです。ただし、このステートメントを確認するための実験を行うだけで済みます。オンになっていない場合は、いくつかの特定のオブジェクトに動的バッチ処理を使用すると、静的バッチ処理が正常に実現されていることがわかります。次に、スイッチをオンにした後、次のようにします。Static Batching
GPU Instancing
SRP Batcher
Profiler
SRP Batcher
したがって、ここでは、他のバッチ処理方法がブロックされることを簡単に理解できます。パフォーマンスの消費SRP Batcher
を観察したい場合は、図に示すように、それSRP Batcher
を直接見つけることができます。TimeLine
SRP Batcher.Flush
要約する
中国でのバッチ処理方法についてUnity
は、上記の成熟した効果的な方法がいくつかありますが、それぞれ長所と短所があります。実際のアプリケーションシナリオに応じて適切な方法を選択する必要があります。つまり、メモリバジェットが非常に限られている場合は、メモリの負荷の増加を避けるために、静的バッチ処理を考慮しないでください。これらの技術的メリットを享受するときに支払う価格を忘れないでください