Vulkan(v1.0.68)について個人的にまとめたものです。内容には間違いが含まれている場合があります。
キュー
- 異なるキューにサブミットされるコマンドバッファ間には暗黙の順序制約がない
- 順序制約を明示する場合、セマフォやフェンスを使う
- 同じキューにサブミットされるコマンドバッファ間には暗黙の順序制約がある
コマンドバッファ
- 長期間リセットしないコマンドプール以外では
VK_COMMAND_POOL_CREATE_TRANSIENT_BITを立てて生成する- これにより、ドライバはフラグメンテーションへの対策を取ることができる
- フレーム単位でリセットするコマンドプールでは
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BITを立てて記録する- この場合、コマンドバッファ実行が完了したときに実行可能状態に戻らず無効状態になる
vkQueueSubmitはできるだけひとまとめにして呼び出す- 「オーバーヘッドが大きくなり得る」と仕様書に明記されている
メモリ
- メモリを解放するとき、マップ状態ならば、暗黙的にアンマップされる
リソース
- 以下のリソースは少なくとも1つの
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BITメモリにアタッチできるVK_BUFFER_CREATE_SPARSE_BINDING_BITを付けずに生成されたバッファVK_IMAGE_TILING_LINEARで生成されたイメージ
- いかなるリソースも少なくとも1つの
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BITメモリにアタッチできる - バッファが対応するメモリタイプはバッファ生成時の
flagsとusageにより一意に決まるusageがあるもののサブセットならそのメモリタイプもサブセットになる
- バッファが必要とするアライメントはバッファ生成時の
flagsとusageにより一意に決まる - カラーフォーマットのイメージが対応するメモリタイプはイメージ生成時の
tilingとVK_IMAGE_CREATE_SPARSE_BINDING_BITの有無とVK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BITの有無により一意に決まる - 深度ステンシルフォーマットのイメージが対応するメモリタイプはイメージ生成時の
formatとtilingとVK_IMAGE_CREATE_SPARSE_BINDING_BITの有無とVK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BITの有無により一意に決まる - UniformTexelBuffer、UniformBuffer、StorageBufferは
vkBindBufferMemoryのmemmoryOffsetにそれぞれの追加のアライメントVkPhysicalDeviceLimits::min*OffsetAlignmentを満たさなければならない - 隣接する線形リソースと非線形リソースがエイリアシングを回避するには、
bufferImageGranularityの粒度がなければならないbufferImageGranularityを単位として重複していないことを確認する
レンダパス
デスクリプタセットレイアウト
- メモリを無駄にしないために、できるだけコンパクトにする
- ドライバはダミー用のバインディングスロットにもメモリを使うかもしれないので
パイプラインレイアウト
- デスクリプタセットは変更頻度の低い順に0から配置する
- 仕様書のnoteにそう書かれている
生成と破壊
- Vulkanドライバはアロケーションが高頻度で発生すると仮定して実装することができる
- プールオブジェクトを介して効率的に確保できるため
VkDeviceMemoryはプールオブジェクトを持たないので例外- とはいえ、これに対応するかはドライバ次第なので過度に期待しないこと
VKShaderModuleとVkPipelineCacheはパイプラインを生成し終わった段階で破壊できるVkPipelineLayoutやVkDescriptorSetLayoutはそれを使って生成されたオブジェクトが使われている間は破壊してはならない- なので、基本的にはそれを使って生成されたパイプラインと一緒に寿命管理すればよい
Vk*Poolを破壊すると、その子オブジェクトが暗黙的に解放されるVk*Poolから割り当てられるオブジェクトは必要であれば親オブジェクトに渡されたホストメモリアロケータを用いる
外部同期
- ほとんどの
vkCmd*関数において、VkCommandBufferを割り当てたVkCommandPoolもそのVkCommandBufferと同じくexternally synchronizedでなければならない- なので、
VkCommandPoolはスレッド間で共有しない
- なので、
有効性
vkDestroy*やvkFree*にNULLを渡すことは(仕様上では)有効である- その場合、特に何もしない
- ただし、なにぶん細かい所なので、ドライバが準拠しているかどうかは要確認
拡張
VK_KHR_shader_draw_parameters- OpenGLでいう
gl_DrawIDなどが利用可能になる - Vulkan 1.1でコア入り
- OpenGLでいう
VK_KHR_maintenance1- 互換性のため、ビューポートの上下反転が可能になる
- Vulkan 1.1でコア入り
VK_AMD_draw_indirect_count- MDIのドロー数もGPUバッファから参照可能になる