當前位置: 華文問答 > 遊戲

Vulkan 1.2 Spec Notes

2021-11-22遊戲

6. Command Buffers

有兩種level的command buffer:

  • Primary Command Buffer
  • 可以送出到queue進行執行的command buffer
  • Secondary Command Buffer可以送出到Primary Command Buffer執行
  • Secondary Command Buffer
  • 不可以送出到queue執行,只能送出到Primary Command Buffer執行
  • 對應的handle:

    // Provided by VK_VERSION_1_0 VK_DEFINE_HANDLE ( VkCommandBuffer )

    Command Buffer中可以記錄的Command類別包括:

  • commands to bind pipelines and descriptor sets to the command buffer
  • commands to modify dynamic state
  • commands to draw (for graphics rendering)
  • commands to dispatch (for compute)
  • commands to execute secondary command buffers (for primary command buffers only)
  • commands to copy buffers and images
  • other commands.
  • 簡單來說,我們必須把command先record到command buffer才能進行後續的執行。另外各個Command Buffer的狀態都是自包的,互相不會影響,即使是送出到Primary的Secondary Command Buffer也不會受到目標Primary Command Buffer的影響。

    另外,一個Command Buffer在開始構建時候狀態是undefined;一個primary command buffer執行完一個secondary以後,狀態是undefined,除非是render/subpass相關的狀態資訊。

    任何和狀態無關的command(draw或者dispatch)消耗的state都應該是undefined(確保和狀態無關)。

    如果沒有明確的指明,所有送出到queue的指令的執行順序可能是任意的(除非他們之間有依賴關系),另外command的讀寫對於其他command可能不是可以直接visible的(同樣除非他們之間有顯式依賴關系)。這些設定對於即使在同一個command buffer中的指令也適用,更加別說多個command buffer之間。

    6.1. Command Buffer Lifecycle

    可能的狀態包括:

    Initial :command buffer剛開始allocate或者reset之後都會進入Initial狀態

    Recording :vkBeginCommandBuffer函數會使得command buffer從Initial狀態到可以接受command的recording狀態,可以使用vkCmd*各種函數來往一個command buffer進行塞command

    Executable :vkEndCommandBuffer函數可以是的Recording狀態的command buffer進入可以送出到queue的狀態,也就是Executable狀態。然後可以透過submmit到queue中。

    Pending :Submit到queue的command buffer就處於Pending狀態(或者說叫等待執行狀態,註意沒有executing狀態)。進入Pending狀態的command buffer必須不能進行修改。queue可能在隨時某個點執行某個command buffer。執行完成後command buffer可能回到Executable狀態,或者在設定一些flag後到Invalid狀態。一個synchronization command應該被使用如果想要捕捉這個結束後的狀態轉換。最後Pending狀態是唯一不用/不能使用者進行操作的狀態,全自動。

    Invalid :在某些使用者的作死操作(比如刪除執行中的command buffer的command或者resource)會使得Command Buffer進入state狀態。其實可能是錯誤狀態可能也有這個意思。處於這個狀態的command buffer只能被reset或者free掉。

    具體轉換圖:

    轉換成表格的話

    Initial Recording Executable Pending Invalid
    Initial Begin
    Recording Reset End Invalidate
    Executable Reset Submission Invalidate
    Pending Completion Completion
    Invalid Reset

    還是很稀疏的。

    6.1.1. Primary & Secondary Command Buffer

    Secondary透過vkCmdExecuteCommands送出到Primary,隨後:

  • 當Primary執行時候也會同時執行Secondary
  • Primary結束時候Secondary也表明執行完成了
  • Primary和Secondary結束後會各自進入目標的最終狀態(Executable or Invalid)
  • 如果Secondary最後是Invalid,那麽Primary也會是Invalid
  • Reset或者Free一個Primary會刪除相關Secondary的Link關系,但是不涉及清楚Secondary的內容
  • 6.2. Command Pools

    Commnand Pools是執行緒不安全的,對應的handle:

    // Provided by VK_VERSION_1_0 VK_DEFINE_NON_DISPATCHABLE_HANDLE ( VkCommandPool )

    和構建函數:

    // Provided by VK_VERSION_1_0 VkResult vkCreateCommandPool ( VkDevice device , const VkCommandPoolCreateInfo * pCreateInfo , const VkAllocationCallbacks * pAllocator , VkCommandPool * pCommandPool );

    熟悉的base + create-info + allocator + hold-handle的節奏。poo還有些其他操作:

  • 透過vkTrimCommandPool進行縮小
  • vkResetCommandPool
  • vkDestroyCommandPool
  • 6.3. Comamnd Buffer Allocation and Management

    對應的函數:

    // Provided by VK_VERSION_1_0 VkResult vkAllocateCommandBuffers ( VkDevice device , const VkCommandBufferAllocateInfo * pAllocateInfo , VkCommandBuffer * pCommandBuffers );

    這裏的AllocationInfo中需要6.2中描述的pool:

    // Provided by VK_VERSION_1_0 typedef struct VkCommandBufferAllocateInfo { VkStructureType sType ; const void * pNext ; VkCommandPool commandPool ; VkCommandBufferLevel level ; uint32_t commandBufferCount ; } VkCommandBufferAllocateInfo ;

    這裏的level就兩個:primary或者secondary。對應的也有Command Buffer的一些操作:

  • vkResetCommandBuffer
  • vkFreeCommandBuffers
  • 6.4. Command Buffer Recording

    這裏可以開始記錄command了:

    // Provided by VK_VERSION_1_0 VkResult vkBeginCommandBuffer ( VkCommandBuffer commandBuffer , const VkCommandBufferBeginInfo * pBeginInfo );

    這裏的info中包含了對於command buffer類別的定義:

    // Provided by VK_VERSION_1_0 typedef struct VkCommandBufferBeginInfo { VkStructureType sType ; const void * pNext ; VkCommandBufferUsageFlags flags ; const VkCommandBufferInheritanceInfo * pInheritanceInfo ; } VkCommandBufferBeginInfo ;

    flags可以用的值包括(註意是個bitmask ):

  • VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT : 送出一次之後buffer就被reset
  • VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT:secondary buffer在render pass
  • VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT:可以反復送出
  • VkCommandBufferInheritanceInfo用在secondary command buffer上面,設定secondary和primary之間的繼承關系。

    Complete recording操作可以呼叫vkEndCommandBuffer:

    // Provided by VK_VERSION_1_0 VkResult vkEndCommandBuffer ( VkCommandBuffer commandBuffer );

    6.5 Command Buffer Submission

    可以透過vkQueueSubmit送出一個或者多個Command Buffer到一個queue:

    // Provided by VK_VERSION_1_0 VkResult vkQueueSubmit ( VkQueue queue , uint32_t submitCount , const VkSubmitInfo * pSubmits , VkFence fence );

    但註意,多個VkSubmitInfo之間的送出是不一定按照陣列順序的,可能是out-of-order的。送出完成後,所有在executable狀態的command buffer會變成pending狀態,等待執行。對應單個submit資訊:

    // Provided by VK_VERSION_1_0 typedef struct VkSubmitInfo { VkStructureType sType ; const void * pNext ; uint32_t waitSemaphoreCount ; const VkSemaphore * pWaitSemaphores ; const VkPipelineStageFlags * pWaitDstStageMask ; uint32_t commandBufferCount ; const VkCommandBuffer * pCommandBuffers ; uint32_t signalSemaphoreCount ; const VkSemaphore * pSignalSemaphores ; } VkSubmitInfo ;

    配合不同的pNext,這裏也可以進一步制定physcial device等資訊。

    6.6. Queue Forward Progress

    command buffer執行的追蹤?

    6.7. Secondary Command Buffer Execution

    因為secondary command buffer不能直接送出到queue執行,因此必須講其送出到primary,透過primary的送出來進而執行secondary:

    // Provided by VK_VERSION_1_0 void vkCmdExecuteCommands ( VkCommandBuffer commandBuffer , uint32_t commandBufferCount , const VkCommandBuffer * pCommandBuffers );

    6.8. Command Buffer Device Mask

    device mask記錄了某個command buffer中的command到底能在哪些physical device上執行的各種資訊,可以設定的點包括:

  • 開始begin command buffer填充時候pNext可以設定VkDeviceGroupCommandBufferBeginInfo
  • 呼叫獨立的vkCmdSetDeviceMask
  • 6.x Reference

  • 進擊的 Vulkan 移動開發之 Command Buffer