NVIDIAのVulkan Device-Generated Commands拡張

NVIDIAの開発者向けサイトでVulkan Device-Generated Commandsという拡張の話が公開されています.

Vulkan Device-Generated Commands
https://developer.nvidia.com/device-generated-commands-vulkan

Vulkanでは実はDirect3D12でいうExecuteIndirectのようなGPU上のバッファで複数の描画コマンドをまとめてDrawやDispatchするような仕組みが現状なく,OpenGL時代のMulti Draw Indirectに関してもまだ機能しない状態だったりします.

vkCmdDrawIndirect(DescriptionのIf the multi-draw indirect feature is not enabled, drawCount must be 0 or 1.drawCount引数は0か1じゃないと動かない)
https://www.khronos.org/registry/vulkan/specs/1.0/man/html/vkCmdDrawIndirect.html

そこでNVIDIAの方でVK_NVX_device_generated_commandsという拡張を用意したのが上記の記事の話です.

NVIDIAの記事では下記の画像を使って,DX11スタイルのDraw Indirect,Multi Draw Indirect,Execute Indirect, VK_NVX_device_generated_commandsを紹介しています.

nvx_dgc_evolution

DX11スタイルのDraw Indirectではセットされた頂点バッファのインスタンシング描画にかかわる部分をGPUで読み書きできるバッファを使用することでCPUの関与を減らしてインスタンシング描画をすることができました.たとえば,上記記事でもありますがGPUでCompute Shaderを使用してカリングを行って,Draw Indirectカリングしないオブジェクトをインスタンシング描画するようなケースですね.Draw Indirectでは事前にバインドしている頂点バッファやインデックスバッファは1つのためインスタンシングできる形状は1種類になります.

続いてMulti Draw Indirectですが,こちらはバインドしている頂点バッファのオフセットと描画する頂点数を複数指定することができ,1つの頂点バッファにデータをつなげておけば異なる形状のインスタンシング描画を一発で行うことができます.ただし,シェーダや頂点バッファのレイアウトなどは変更することができません.

Execute IndirectではMulti Draw Indirectに比べてもう少し柔軟でDraw Callごとに入力やリソースのバインド状況を変えることで変化を出しやすくなりましたが,シェーダなどを変えることができませんでした.

VK_NVX_device_generated_commandsではExecute Indirectに加えてPipelineStateをDrawやDispatchの単位で変更できるように機能が追加されシェーダを変更したりするような機能に対応しています.これによりOcclusion cullingを異なるシェーダで描画するオブジェクトまとめてやってDrawに積んだり,異なるシェーダが適用されるオブジェクトに対してZ-sortをGPUでやるなどといったことが可能になると書かれています.

記事ではその原理と使い方が解説がされています.今のところNVIDIAの専用の拡張ですが,ほかのGPUベンダーなども採用したりVulkan標準やDirect3D12などで採用されるとレンダリングエンジンの描画コマンドの積み方に関して大きな改善につながるかもしれないですね.

サンプルとなる実装コード
https://github.com/nvpro-samples/gl_vk_threaded_cadscene/blob/master/doc/vulkan_nvxdevicegenerated.md