search
尋找貓咪~QQ 地點 桃園市桃園區 Taoyuan , Taoyuan

Vulkan 教程--Overview

Step 4 - Image views and framebuffers

先使用VkImageView和VkFrameBuffer將image包裹起來,然後才能將內容畫到image上。imageView 引用一個image要被使用的特定部分,而framebuffer引用imageView ,把它當做color 、depth和stencil的目標使用。因為swap chain里可以有多個image ,所以我們先發制人:為每一個image 創建一個imageView和framebuffer ,然後在繪畫階段選擇一個正確的來使用。

Step 5 - Render passes

Render pass描述了在渲染階段要使用的image類型、如何使用以及如何處理image的內容。在我們的示例三角形應用中,我們告訴Vulkan,要使用一個image 作為color的目標,並且希望它在繪畫操作前被塗成純色。請注意,Render pass只是描述要使用的image類型,而framebuffer( 通過綁定image )才是要使用的image實體。

Step 6 - Graphics pipeline

在Vulkan中Graphics Pipeline 通過創建VkPipeline對象來建立。它描述了一些顯卡不可編程部分的可配置狀態(configurable state ),比如viewport的大小和depth buffer操作等,以及用VkShaderModule表示的可編程部分。VkShaderModule對象用著色器的位元組碼來創建。驅動需要知道哪些渲染目標將在pipeline中使用,而這些目標就是我們在Render pass中定義的image。

Vulkan和現存的其他圖形API最顯著地區別就是:幾乎所有不可編程部分的配置都要在pipeline創建前提前完成。這就意味著如果你想換一個著色器(shader)或者僅僅改變一些頂點的布局(vertex layout) ,那麼你必須重新創建pipeline 。這也意味著你必須提前創建很多pipeline,來應對渲染過程中不同組合的配置。只有很少的一些配置你可以動態改變,比如viewport 的大小和celar 的顏色等。Pipeline中所有的配置狀態你必須顯示的進行定義,比如,顏色混合就沒有為你提供默認的配置。

它給我們帶來的一個好處就如同提前編譯和當場編譯一樣,驅動將有更多優化的機會和對運行時性能做更多的預測。

Step 7 - Command pools and command buffers

之前也提到,Vulkan中的命令(原文是operation )必須提交到對應的隊列才能執行。這些命令首先要記錄到VkCommandBuffer中,然後才能提交的到隊列。這些commandBuffer來自於一個commandPool,而CommandPool關聯一種具有特定命令的隊列。

畫一個三角形,我們需要以下幾個步驟來記錄commandBuffer:

開始render pass

綁定graphics pipeline

畫三個頂點

結束render pass。

FrameBuffer中的image取決於swap chain返回給我們的是哪一個,所以我們必須為每一個可能的image記錄一個commandBuffer,然後在繪畫階段選擇正確的那個來運行。另外一種方法是每一幀都記錄一個commandBuffer,但這種方法性能不高。

Step 8 - Main loop

現在繪畫命令已經放在CommandBuffer中, Main loop就變得非常簡單了。首先使用 vkAcquireNextImageKHR.從swap chain里獲取一個image ,然後根據這個image選擇對應的commandBuffer ,使用vkQueueSubmit執行這個commandBuffer ,最後使用vkQueuePresentKHR將這個Image 返回到swap chain準備顯示。

隊列中的命令採用非同步的方式來執行,因此我們必須採用像信號量(semaphore)這樣的同步對象,來確保程序執行的正確順序。繪畫操作必須在獲取image完成後才能進行,否則就會出現當前渲染和顯示共用一個image的情況。vkQueuePresentKHR必須等待渲染結束才能進行交替使用, 這就需要我們再使用一個semaphore來等待渲染結束。

Summary

通過上述大致的講解,想必你已經對畫三角形的過程有了基本的認識。然而我們真正的程序卻包含更多的步驟,像分配vertex buffer和uniform buffer 以及上傳紋理圖片等,我們將在後續的章節一一介紹它們。因為vulkan具有相當陡峭的學習曲線,我們打算先從簡單入手。這裡我們將耍點小計倆,打算先把頂點坐標硬編碼到Shader里,而不是直接使用veretx buffer ,因為管理vertex buffer 需要你先對command buffer 有一定了解。

總之,為了畫這個三角形,我們需要:

創建VkInstance。

選擇一個顯卡(VkPhysicalDevice)

為繪畫和顯示創建一個VkDevice和VkQueue。

創建一個window、window surface 和 swap chain。

用image view 包裹swap chain里的image。

創建一個render pass ,用它來定義渲染目標和目標的用法。

為render pass 創建一個frameBuffer。

創建graphics pipeline。

為每一個可能的swap chain image 繪畫命令分配和記錄command buffer。

通過獲取的image 來draw frame,提交正確的繪畫command buffer,最後將繪畫結果(image)返回到swap chain。

API concepts

Coding conventions

Vulkan的所有函數、枚舉變數和結構體都定義在vulkan.h里,而且包含在Vulkan SDK中 。函數以小寫的vk為前綴,枚舉類型和結構體以Vk為前綴,而枚舉值以VK為前綴。Vulkan API嚴重依賴結構體作為函數參數。例如,對象的創建將遵循如下方式:

VkXXXCreateInfo createInfo = {};

createInfo.sType = VK_STRUCTURE_TYPE_XXX_CREATE_INFO;

createInfo.pNext = nullptr;

createInfo.foo = ...;

createInfo.bar = ...;

VkXXX object;

if (vkCreateXXX(&createInfo, nullptr, &object) != VK_SUCCESS) {

std::cerr << "failed to create object" << std::endl;

return false;

}

在Vulkan中很多結構都要你定義它的類型sType。pNext 指向一個擴展的結構,在本教程中它總是nullptr。創建和銷毀對象的函數要求一個 VkAllocationCallbacks,我們也將它置位nullptr。

所有函數的返回值是一個 VkResult 類型的枚舉,它要麼是VK_SUCCESS表示成功,要麼是其他錯誤值。

Validation layers

(後面有一節專門講Validation layers, 這裡只提取了原文的主要意思)

之前也說過 Vulkan是高性能低驅動負擔的API,這也就意味著它的錯誤檢測十分有限。如果你做錯了什麼事,他就會直接crash掉,而不是返回一個錯誤碼。Vulakn允許你為錯誤檢測添加擴展,這就是Validation layers。它像是嵌套在你方法調用里的代碼片段一樣,跟蹤參數和內存安全。你可以編寫自己的Validation layers ,但Vulkan SDK 為你提供了一些標準的Validation layers供你開發使用。所以其實它比OPengl 和Direct3D 更容易查找到錯誤。



熱門推薦

本文由 yidianzixun 提供 原文連結

寵物協尋 相信 終究能找到回家的路
寫了7763篇文章,獲得2次喜歡
留言回覆
回覆
精彩推薦