フレーム プロファイリングを使用すると、頂点に関連するパフォーマンスの問題のいくつかを診断できます。[Commands] ペインを使用すると、特定のフレームでゲームが実行するすべての描画呼び出しと、描画呼び出しごとに描画されたプリミティブの数を表示できます。これにより、単一フレームで送信される頂点の総数を概算できます。
![glDrawElements 呼び出しのフレーム プロファイリング ビューにカーソルを合わせると、描画呼び出しパラメータの詳細が表示されます](https://developer.android.com/static/images/agi/vertex-formats-images/sample_drawcall.png?authuser=8&hl=ja)
glDrawElements
呼び出しのフレーム プロファイリング ビュー頂点属性の圧縮
ゲームで直面する一般的な問題として、平均頂点のサイズが大きいというものがあります。平均頂点サイズが大きい頂点が多数送信されると、GPU による頂点メモリの読み取り帯域幅が大きくなります。
特定の描画呼び出しの頂点形式を確認する手順は次のとおりです。
目的の描画コールを選択します。
これには、シーンの一般的な描画呼び出し、多数の頂点を伴う描画呼び出し、複雑なキャラクターモデルの描画呼び出し、またはその他の種類の描画呼び出しがあります。
[Pipeline] ペインに移動し、入力アセンブリの [IA] をクリックします。GPU に渡される頂点の形式を定義します。
一連の属性とその形式を確認します。たとえば、
R32G32B32_SFLOAT
は 3 コンポーネントの 32 ビット符号付き浮動小数点数です。
![描画呼び出しの入力アセンブリのフレーム プロファイリング ビューと、非圧縮の頂点属性](https://developer.android.com/static/images/agi/vertex-formats-images/sample_bigvertex.png?authuser=8&hl=ja)
多くの場合、頂点属性を圧縮することで、描画されるモデルの品質の低下は最小限に抑えられます。具体的には、次のことをおすすめします。
- 頂点の位置を半精度の 16 ビット浮動小数点数に圧縮する
- UV テクスチャ座標を 16 ビット符号なし整数 ushorts に圧縮する
- 四元数を使用して法線ベクトル、タンジェント ベクトル、超正規ベクトルをエンコードすることで、タンジェント空間を圧縮する
状況に応じて、その他の属性も低精度の型と見なされる場合があります。
頂点ストリーム分割
また、頂点属性ストリームが適切に分割されているかどうかを調査することもできます。モバイル GPU などのタイル レンダリング アーキテクチャでは、まず頂点の位置がビニングパスで使用され、各タイルで処理されるプリミティブのビンが作成されます。頂点属性が単一のバッファにインターリーブされる場合、頂点位置のみが使用される場合でも、すべての頂点データがキャッシュに読み取られビニングされます。
頂点の読み取りメモリ帯域幅を減らし、キャッシュの効率を向上させ、ビニングパスに費やす時間を短縮するには、頂点データを 2 つの別々のストリーム(頂点の位置用と他のすべての頂点属性用)に分割する必要があります。
頂点属性が適切に分割されているかどうかを調べるには:
目的のドローコールを選択し、そのドローコール番号をメモします。
これには、シーンの一般的な描画呼び出し、多数の頂点を伴う描画呼び出し、複雑なキャラクターモデルの描画呼び出し、またはその他の種類の描画呼び出しがあります。
[Pipeline] ペインに移動し、入力アセンブリの [IA] をクリックします。これにより、GPU に渡される頂点の頂点形式が定義されます。
頂点属性のバインディングを確認します。通常は、直線的に増加します(0、1、2、3 など)。ただし、常にそうであるとは限りません。通常、頂点位置はリストの最初の頂点属性です。
[State] ペインで
LastDrawInfos
を探し、一致する描画呼び出し番号を展開します。次に、この描画呼び出しのBoundVertexBuffers
を展開します。前述の頂点属性バインディングと一致するインデックスを使用して、指定された描画呼び出しの間にバインドされた頂点バッファを確認します。
描画呼び出しの頂点属性のバインディングを展開し、バッファを展開します。
バッファの
VulkanHandle
を確認します。これは、頂点データソースの基盤となるメモリを表します。VulkanHandle
が異なる場合、属性は異なる基盤となるバッファに由来することを意味します。VulkanHandle
が同じでもオフセットが大きい場合(100 より大きいなど)、属性が異なるサブバッファから発生している可能性がありますが、さらなる調査が必要です。
![描画呼び出しの入力アセンブリとバインドされた頂点バッファを示す状態のフレーム プロファイリング ビュー](https://developer.android.com/static/images/agi/vertex-formats-images/sample_attributestreams.png?authuser=8&hl=ja)
頂点ストリーム分割の詳細と、さまざまなゲームエンジンでこれを解決する方法については、この件に関するブログ投稿をご覧ください。