Skip to content
Go back

Vulkan仕様メモ

· Updated:

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メモリにアタッチできる
  • バッファが対応するメモリタイプはバッファ生成時のflagsusageにより一意に決まる
    • usageがあるもののサブセットならそのメモリタイプもサブセットになる
  • バッファが必要とするアライメントはバッファ生成時のflagsusageにより一意に決まる
  • カラーフォーマットのイメージが対応するメモリタイプはイメージ生成時のtilingVK_IMAGE_CREATE_SPARSE_BINDING_BITの有無とVK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BITの有無により一意に決まる
  • 深度ステンシルフォーマットのイメージが対応するメモリタイプはイメージ生成時のformattilingVK_IMAGE_CREATE_SPARSE_BINDING_BITの有無とVK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BITの有無により一意に決まる
  • UniformTexelBuffer、UniformBuffer、StorageBufferはvkBindBufferMemorymemmoryOffsetにそれぞれの追加のアライメントVkPhysicalDeviceLimits::min*OffsetAlignmentを満たさなければならない
  • 隣接する線形リソースと非線形リソースがエイリアシングを回避するには、bufferImageGranularityの粒度がなければならない
    • bufferImageGranularityを単位として重複していないことを確認する

レンダパス

デスクリプタセットレイアウト

  • メモリを無駄にしないために、できるだけコンパクトにする
    • ドライバはダミー用のバインディングスロットにもメモリを使うかもしれないので

パイプラインレイアウト

  • デスクリプタセットは変更頻度の低い順に0から配置する
    • 仕様書のnoteにそう書かれている

生成と破壊

  • Vulkanドライバはアロケーションが高頻度で発生すると仮定して実装することができる
    • プールオブジェクトを介して効率的に確保できるため
    • VkDeviceMemoryはプールオブジェクトを持たないので例外
    • とはいえ、これに対応するかはドライバ次第なので過度に期待しないこと
  • VKShaderModuleVkPipelineCacheはパイプラインを生成し終わった段階で破壊できる
  • VkPipelineLayoutVkDescriptorSetLayoutはそれを使って生成されたオブジェクトが使われている間は破壊してはならない
    • なので、基本的にはそれを使って生成されたパイプラインと一緒に寿命管理すればよい
  • 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でコア入り
  • VK_KHR_maintenance1
    • 互換性のため、ビューポートの上下反転が可能になる
    • Vulkan 1.1でコア入り
  • VK_AMD_draw_indirect_count
    • MDIのドロー数もGPUバッファから参照可能になる