17Vulkan——緩衝區資源和RenderPass

1.緩衝區資源

  緩衝區資源以線性方式表示連續的數據陣列。 緩衝區資源通常用來存儲屬性數據信息,如頂點座標,紋理座標,關聯顏色等。 Vulkan 中的緩衝區資源由 VkBuffer 對象表示,與視圖形式(圖像視圖,VkImageView)表示的圖像資源(VkImage)不同,緩衝區資源可以直接用作頂點數據的源,或者可以通過着色器利用描述符進行訪問。 需要把它們顯式轉換爲緩衝區視圖(VkBufferView)以允許着色器以格式化的格式使用緩衝區數據的內容。

使用 Vulkan API 創建緩衝區資源(VkBuffer)的步驟說明

  1. 創建緩衝區對象:使用 vkCreateBuffer()API 創建緩衝區對象(VkBuffer)。 此 API 會用到 VkCreateBufferInfo 結構對象,該對象指定了用於創建緩衝區對象的一些重要緩衝區元數據。 緩衝對象的 VkCreateBufferInfo 包含必要的內存信息,例如格式,用法,大小,創建標誌等。 這個信息用於從設備分配物理內存。 您可以認爲在此初始階段的緩衝區對象沒有後端的內存支持,即沒有分配實際的物理存儲。 創建緩衝區對象並不意味着物理分配在幕後自動完成;必須手動完成,這會在下一步中介紹。
  2. Allocating buffer memory 分配緩衝內存
  • 獲取內存需求:使用 vkGetBufferMemoryRequirements()API 收集所需的內存信息。 在緩衝區資源的分配過程中,此信息有助於分配所需的適當大小的內存。 這個 API 使用到了第一步中創建的 VkBuffer。
  • 確定內存類型:與圖像資源類似,從可用的內存類型中獲取合適的內存類型,並選擇與用戶所需屬性匹配的內存類型。
  • 分配設備內存:使用 vkAllocateMemory()API 分配設備內存(VkDeviceMemory)。
  • 暫存:分配物理內存後,需要使用 vkMapMemory()將其映射到本地主機,以便將幾何圖形的數據從主機內存上載到物理設備內存。 一旦數據被複制到物理設備內存中,就需要使用 vkUnmapMemory()來取消映射。
  • 綁定分配的內存:使用 vkBindBufferMemory()API 將設備內存(VkDeviceMemory)綁定到緩衝區對象(VkBuffer)。

下圖總結了完整的緩衝區資源創建的工作流程:

2RenderPasss渲染通道

  在Vulkan中,繪製命令會被組織成Render Pass,可以說是一組SubPass的集合,每個子通道描述的是如何使用color attachments 等圖像資源,RenderPass管理子通道之間的依賴關係和繪製順序:

渲染通道告訴我們關於渲染時要使用的幀緩衝附件和子通道的信息 渲染通道主要由兩種類型的組件組成:附件和子通道。

附件 Attachments

附件是指渲染命令時使用的表面區域(例如顏色,深度 / 模板或用來執行解析操作的解析附件)。 這裏描述了五種類型的附件:

  • 顏色附件:Color attachment,顏色附件表示在其上繪製渲染圖元的、用來繪圖的目標圖像。
  • 深度附件:Depth attachment,深度附件存儲深度信息並將其用於深度 / 模板測試操作。
  • 解析附件:Resolve attachment, 解析附件自動從多采樣附件一直向下採樣到子通道末尾相應的單採樣附件。 解析附件對應於多重採樣的顏色附件,並且表現得好像子通道末尾有一個 vkCmdResolveImage,從彩色附件到相應的解析附件。 一個例外是驅動程序可能會做得更好,例如同時對一個貼片 tiler 執行溢出 spill 和解析 resolve 操作。
  • 輸入附件:Input attachment,這個附件由着色器共享的附件列表組成。 輸入附件類似於受限紋理,其中着色器可以執行的唯一操作是紋素的提取(texture(tex,uv)) - 即從紋素讀取(對應於當前正被着色的像素)。 明顯的例子是一觸式後(期)處理過濾器(無模糊等),經典的延遲渲染器的光照階段就是從 G 緩衝區中讀取等。
  • 保留附件:Preserve attachment,在整個過程中,在給定的子通道中,保留附件內的內容保持不變。 保留附件根本不在其他 API 中表達。 他們表示要求保留一些附件的內容(因爲它將在以後使用),但不應該被當前的子通道所觸及。 這在桌面 GPU 上根本沒有意義,其中渲染目標寫入操作會直接進入內存。 然而,對於平鋪器 tiler 來說,這就顯得非常有趣:在子通道期間,片上內存的附件部分可以被重新使用以代替某些其他附件,而不必將其內容泄漏回內存。

子通道 Subpasses

在渲染通道中,子通道讀取和寫入相關的附件。 Render Pass 執行中的當前子通道會受渲染命令的影響:

  • 一個子通道可以讀取先前被寫入的附件(它必須保存)並寫入當前與其關聯的附件。
  • 寫入顏色和深度 / 模板緩衝區也是與 Render Pass 實例關聯的子通道附件的一部分。
  • 爲了允許後續通道使用子通道附件,應用程序有責任確保信息保持有效狀態,直到信息不被使用爲止。
  • 在整個子通道的生命週期中,還有保留附件來保存附件中的內容。 子通道不能影響這些附件,因爲它們是讀 / 寫保護的。 換句話說,它們在子通道生命週期中不能被讀 / 寫。
  • 子通道描述符由 VkSubpassDescription 定義。 它描述了子通道中涉及的附件數量。

  • 子通道可以引用各種附件,如輸入,解析,顏色,深度 / 模板以及保留附件。 這是使用一個稱爲 VkSubpassDescription 的特殊控制結構來描述的

 4.實現渲染通道 Render Pass

Render Pass 實例是在創建命令緩衝區的準備階段實現的。 對於每個交換鏈圖像,都會創建一個相應的命令緩衝區對象。 這意味着,對於 n 個交換鏈圖像,我們需要創建 n 個命令緩衝區對象。

  1. 創建的顏色圖像和深度圖像需要在附件中指定。 爲這兩個圖像類型創建大小等於 2 的 VkAttachmentDescription 類型的數組。 此結構中指定的信息將決定在渲染通道 Render Pass 的開始和結束時如何處理圖像。 其中包含圖像格式,樣本數量,加載和存儲操作等。
  2. 對於這兩個附件,將 loadOp 成員設置爲 VK_ATTACHMENT_LOAD_OP_CLEAR。 這個設置的意思是在每個 Render Pass 實例開始時清除緩衝區。 對於顏色附件,將 storeOp 成員設置爲 VK_ATTACHMENT_STORE_OP_STORE,指示渲染的輸出保存在以後用於顯示它的緩衝區中。
  3. 接下來,對於這兩個附件,在 Render Pass 中指定綁定點。 這可以讓渲染通道知道在哪裏尋找一個特定的附件。 綁定點在 VkAttachmentReference 的幫助下定義;該控制結構攝入的另一條信息就是用於圖像佈局轉換的圖像佈局信息。 分別爲顏色和深度緩衝區使用 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL 和 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL 指定圖像佈局。 該佈局通知底層引擎將圖像存儲在最佳內存中以提供最佳性能。
  4. 使用 VkSubpassDescription 在子通道中指定所有附件。 在這裏,指定了顏色,深度,解析以及保存附件。 最後,所有附件和子通道特定的信息都在 VkRenderPassCreateInfo 中匯聚並傳遞給 vkCreateRenderPass()API 以創建 Render Pass 對象:
  5. 在銷燬階段,使用 vkDestroyRenderPass()API 銷燬 Render Pass 對象

3.使用 Render Pass 以及創建 framebuffer

一旦創建 Render Pass,它就被用來創建幀緩衝區 framebuffer。 理想情況下,對於每個交換鏈彩色圖像,我們需要一個與其相關的幀緩衝區。 例如,如果我們有一個雙緩衝區交換鏈圖像,那麼我們需要兩個幀緩衝區:一個用於前端緩衝區圖像,另一個用於後端緩衝區圖像。

實現幀緩衝區 framebuffer

FrameBuffer是一系列Image對象的集合,它是所有繪製操作的最終目標。

Swap Chains從窗口系統申請來的Image對象跟FrameBuffer綁定以後,繪製操作才能繪製到這些Image上面。

如果把繪製流程比作繪畫:

Swap Chains從窗口系統申請來的Image是用來作畫的紙張;

FrameBuffer就是一個可以夾住多張紙的畫板;

Renderpasses則表示每張紙要畫什麼,他們之間的繪製順序是什麼樣子的,繪製時是不是要參考前一張的繪製內容。

當繪製完成後,我們就可以把Image傳給平臺的窗口系統進行顯示了。

 

幀緩衝區的實現很簡單;按着如下步驟操作即可:

  1. 在 VulkanRenderer 類中創建以下函數和變量。 cmdFrameBuffer 聲明負責創建幀緩衝區(frameBuffer)的命令緩衝區
  2. 初始化期間,使用 createFrameBuffer()函數創建幀緩衝區:
  3. 對於每個交換鏈彩色圖像,創建其相應的幀緩衝區。 這是通過使用 vkCreateFrameBuffer()API 完成的。 此 API 使用 VkFrameBufferCreateInfo,我們在其中指定深度和彩色圖像視圖作爲附件。 此外,在此結構中還傳遞了創建的 Render Pass 對象以及 framebuffer 的尺寸:
  4. 在應用程序的銷燬階段,使用 vkDestroyFrameBuffer()API 銷燬所有的幀緩衝區:

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章