天天看點

【Vulkan】學習筆記1畫一個三角形流程

畫一個三角形流程

1、執行個體和實體裝置選擇

Vulkan應用程式首先通過VkInstance(VkInstance instance;),建立執行個體後可查詢支援的硬體,可以選擇一個或者多個VkPhysicalDevice(VkPhysicalDevice physicalDevice = VK_NULL_HANDLE).

2、邏輯裝置和隊列系列

選擇要使用的正确硬體裝置後,建立一個VkDevice(VkDevice device),還需要指定要使用的隊列系列。大多數使用 Vulkan 執行的操作,如繪制指令和記憶體操作,都是通過将它們送出給一個異步執行的VkQueue(VkQueue graphicsQueue;).

3、 視窗表面和交換鍊

需要建立一個視窗來呈現渲染圖像。需要2個元件來實際渲染到一個視窗:①VkSurfaceKHR(VkSurfaceKHR surface;),②VkSwapchainKHR(VkSwapchainKHR swapChain;)。KHR字尾意味着這些對象是Vulkan擴充的一部分。

Surface 是對要渲染到的視窗的跨平台抽象,通常通過提供對本機視窗句柄的引用來執行個體化,例如

HWND

在 Windows 上。

交換鍊是渲染目标的集合。它的基本目的是確定我們目前渲染的圖像與目前螢幕上的圖像不同。這對于確定隻顯示完整圖像很重要。每次我們想要繪制一個幀時,我們都必須要求交換鍊為我們提供要渲染的圖像。當我們完成繪制幀時,圖像将傳回到交換鍊,以便在某個時候顯示在螢幕上。渲染目标的數量和将完成的圖像呈現到螢幕上的條件取決于目前模式。

4、圖像視圖和幀緩沖區

要繪制從交換鍊擷取的圖像,我們必須将其包裝到一個 VkImageView(std::vector swapChainImageViews;)和VkFramebuffer(std::vector swapChainFramebuffers;)中。

5、渲染通道

僅描述圖像類型。

6、圖形流水線

Vulkan 中的圖形管道是通過建立一個

VkPipeline

(VkPipeline graphicsPipeline;)對象來設定的。它描述了圖形卡的可配置狀态,如視口大小和深度緩沖區操作以及使用

VkShaderModule

(VkShaderModule shaderModule;)對象的可程式設計狀态。這些

VkShaderModule

對象是從着色器位元組代碼建立的。驅動程式還需要知道管道中将使用哪些渲染目标,我們通過引用渲染通道來指定。

7、指令池和指令緩沖區

如前所述,我們要執行的 Vulkan 中的許多操作(例如繪圖操作)需要送出到隊列。這些操作首先需要記錄到a

VkCommandBuffer

(std::vector commandBuffers;)中才能送出。這些指令緩沖區是從

VkCommandPool

(VkCommandPool commandPool;)與特定隊列系列關聯的隊列中配置設定的。要繪制一個簡單的三角形,我們需要使用以下操作記錄一個指令緩沖區:

  • 開始渲染過程
  • 綁定圖形管道
  • 繪制3個頂點
  • 結束渲染過程

因為幀緩沖區中的圖像取決于交換鍊将給我們的特定圖像,是以我們需要為每個可能的圖像記錄一個指令緩沖區,并在繪制時選擇正确的圖像。

8、主循環

我們首先使用 擷取交換鍊中的圖像

vkAcquireNextImageKHR

。(VkResult result = vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);)解釋如下:

device:Vulkan邏輯裝置

swapChain:Vulkan交換鍊

UINT64_MAX:逾時時間,表示不逾時。

imageAvailableSemaphores[currentFrame]:信号量,用于同步交換鍊中的圖像。

VK_NULL_HANDLE:沒有可用的圖像。

&imageIndex:指向整數類型的指針,用于存儲擷取到的圖像索引。

然後我們可以為該圖像選擇适當的指令緩沖區并使用

vkQueueSubmit

. (if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences[currentFrame]) != VK_SUCCESS) {

throw std::runtime_error(“failed to submit draw command buffer!”);

})

最後,我們将圖像傳回到交換鍊以顯示到螢幕上

vkQueuePresentKHR

。(result = vkQueuePresentKHR(presentQueue, &presentInfo)😉

繼續閱讀