500個の単純なオブジェクトを持つシーンは500回の vkCmdDraw
呼び出しを要求する。それぞれがドライバーがバリデートして記録する
わずかな API オーバーヘッドだ。VK_EXT_multi_draw はそれらを
潰す。vkCmdDrawMultiEXT は {firstVertex, vertexCount} ペアの
配列を取り、すべてを1回の呼び出しで発行する。パラメータは
ホストメモリ から来る。間接バッファは不要だ。
API
multi.cpp
// 機能を有効化:VkPhysicalDeviceMultiDrawFeaturesEXT::multiDraw
vk::MultiDrawInfoEXT draws[] = {
{0, 36}, // obj0:頂点 0..35
{36, 24}, // obj1:頂点 36..59
{60, 120}, // obj2:…
};
cmd.drawMultiEXT(uint32_t(std::size(draws)), draws,
/*instanceCount*/1, /*firstInstance*/0,
/*stride*/sizeof(vk::MultiDrawInfoEXT));
// インデックス版 — 同じアイデア + pVertexOffset:
cmd.drawMultiIndexedEXT(n, idxInfos, 1, 0,
sizeof(vk::MultiDrawIndexedInfoEXT), &vtxOff);vkCmdDraw*Indirect との主な違い:
drawMulti | drawIndirect | |
|---|---|---|
| パラメータの出所 | 呼び出し内のホスト配列 | GPU 上の VkBuffer |
| 全 draw が共有 | instanceCount、firstInstance | なし — draw ごとに完全なパラメータ |
| drawCount 制限 | maxMultiDrawCount | 間接 draw カウントは無制限 |
| シェーダーが見る | draw ごとの gl_DrawID | draw ごとの gl_DrawID |
何に向いているか
- バッチ化された単純 draw——それぞれが異なる頂点スライスだが 同じインスタンス数を必要とする数百のクワッド/ビルボード/タイル。 1回の API 呼び出し、1回のバリデーションパス。
gl_DrawIDによる draw ごとのデータ——シェーダー内でgl_DrawIDが SSBO/UBO にインデックスし、バッチ内の各 draw が 自分のトランスフォーム/マテリアルを取得できる。これが「1回の 呼び出し、N オブジェクト」の得方だ。- N draw より少ない CPU、間接より単純——埋める GPU バッファが
なく、カウント用の
vkCmdFillBufferもない。パラメータは インラインだ。
drawid.vert
layout(set=0, binding=0) readonly buffer Xforms { mat4 m[]; } xf;
void main() {
// マルチバッチのどの draw か?
mat4 m = xf.m[gl_DrawID];
gl_Position = m * vec4(pos, 1);
}制限
VkPhysicalDeviceMultiDrawPropertiesEXT::maxMultiDrawCountが配列を 制限する。一般に2048以上。巨大バッチに依存する前に確認する。- すべての draw が
instanceCount/firstInstanceを共有する。 オブジェクトが異なるインスタンス数を必要とするなら別々の 呼び出しが依然必要。 - draw ごとの first-instance 変化はない。多様性には
gl_DrawIDによるデータバッファへのオフセットを組み合わせる。
実践的なルール
- 「同じマテリアル、異なるメッシュスライス」——
drawMultiが スイートスポット。パラメータがとにかく CPU にあるなら間接より 安い。 - 「GPU が draw を決める」(カリングがリストを書く)——代わりに
vkCmdDrawIndirect*が欲しい。パラメータは GPU 生成でなければ ならない。 gl_DrawIDにはVK_KHR_shader_draw_parametersが必要(1.1 で コア)。バッファを draw ごとにインデックスする標準的な方法だ。- バッチごとに依然1パイプライン。マルチドローは異なるパイプラインを 融合しない。パイプライン 内 でバッチし、間で切り替える。
この記事が役に立った場合は、TechOverflow での新しい記事の調査と公開を支援するため、「Buy Me a Coffee」でのご支援、または PayPal 経由でのご寄付をご検討ください