最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

Vulkan 01 簡介

2023-03-25 08:31 作者:rabanastre  | 我要投稿

這一章介紹Vulkan,然后看看怎么繪制第一個三角形。后面的章節(jié)會詳細(xì)介紹。


Vulkan的起源

和之前的圖形接口OpenGL一樣,Vulkan也是一個跨平臺的GPU接口。以前的接口的問題是它們局限于固定功能。編程人員必須用標(biāo)準(zhǔn)的格式提交頂點(diǎn)數(shù)據(jù),且只能靠GPU制造商提供的光照和著色選項。

隨著顯卡的發(fā)展,它們已經(jīng)能提供更多的可編程能力。在不推翻原有API構(gòu)架的基礎(chǔ)上,通過增補(bǔ)來提供新的API,結(jié)果是一個導(dǎo)致一個越來越不不理想的接口。最近幾年移動端GPU使用Tile Based Rendering可以降低功耗。舊的API的另一個問題是它們對多線程渲染支持不好。

Vulkan重新設(shè)計了一套圖形接口。編程人員可以清楚的指定GPU的工作,并且多個線程并行的創(chuàng)建和提交命令。Vulkan只使用一個專門的offline著色器編譯器,減少了各個廠商自行實現(xiàn)的on the fly編譯器的不一致性。最后,它把graphics functionality和compute functionality合并成為一套統(tǒng)一的API。


如何繪制一個三角形

簡要介紹vulkan如何初始化和繪制第一個三角形。


1 - 實例(Instance)和物理設(shè)備選擇

Vulkan程序始于VkInstance(),它創(chuàng)建一個vulkan實例。

實例創(chuàng)建后,就可以查詢機(jī)器上支持vulkan的硬件,并且選擇一個或多個VkPhysicalDevice來使用。你可以查詢?nèi)鏥Ram大小、設(shè)備能力,最后選擇你喜歡的設(shè)備,例如優(yōu)先選擇獨(dú)顯。


2 - 邏輯設(shè)備和queue family

決定選哪個設(shè)備后,你應(yīng)該創(chuàng)建一個VkDevice(邏輯設(shè)備),來代表那個設(shè)備。

你還需要指定要使用那個queue family。vulkan可以執(zhí)行的操作,如繪制命令命令、內(nèi)存操作,都是提交到VkQueue之后異步執(zhí)行的。圖形命令,計算命令,內(nèi)存?zhèn)鬏敳僮?,都有各自對?yīng)的隊列類型。顯卡可以只支持某些類型的隊列而不是全部,但是現(xiàn)在的顯卡基本都支持所有的隊列類型了。


3 - window surface和swap chain

除非你只想做離屏渲染(offscreen rendering),你都需要創(chuàng)建一個窗體來顯示渲染結(jié)果。

你可以用操作系統(tǒng)提供的API創(chuàng)建窗口,也可以用封裝后的庫例如GLFW和SDL。

我們將使用GLFW。

我們需要這兩個組件:window surface(VkSurfaceKHR)和 swap chain(VkSwapChainKHR)。

注意后綴KHR,它表示這些類型是vulkan的擴(kuò)展部分。因為vulkan api本身是和平臺無關(guān)的,所以我們需要使用標(biāo)準(zhǔn)的WSI(Window System Interface)擴(kuò)展來和窗口交互。Surface是一個跨平臺的對窗體的抽象,它在初始化時需要一個本地類型的窗口handle作參數(shù),例如windows的HWND。好消息是GLFW已經(jīng)幫我們處理了平臺相關(guān)的細(xì)節(jié)。

Swap chain是一系列的render target。它的基本目的是保證當(dāng)我們在渲染到一個緩存區(qū)時,這個緩沖區(qū)沒有被用來顯示。這很重要,這樣才能保住只有已經(jīng)渲染完了的圖像會被用來顯示。

當(dāng)我們渲染完一幀后,這個圖像被返還給swap chain等待顯示。Render target的數(shù)量和present條件取決于當(dāng)前設(shè)置的模式。通常的模式是雙緩沖(vsync)以及三層緩沖。


4 - image view和framebuffer

要在從swap chain得到一個image上繪制,你必須把它包裹進(jìn)VkImageView和VkFrameBuffer。Image view用來指定image的那個部分將被使用,framebuffer用來包裝用于渲染的顏色view、深度view和stencil view。因為swap chain里面可能有很多image,我們預(yù)先給它們各自都創(chuàng)建image view和framebuffer,然后在繪圖時選擇對應(yīng)的那個。


5 - render pass

Vulkan的render pass用來描述渲染操作中使用的image類型,它們會如何被使用,如何對待它們的內(nèi)容。在我們的第一個渲染三角形的程序中,我們將告訴vulkan我們會只使用一個image作為color target。


6 - graphics pipeline

創(chuàng)建一個VkPipeline對象,它代表顯示卡的那些可配置的狀態(tài),例如viewport size和深度緩沖的參數(shù)。創(chuàng)建一個VkShaderModule對象,來代表著色器。

和OpenGL最大的不同是,幾乎所有的可配置選項都必須預(yù)先設(shè)置。意思是,如果你需要切換到另一個著色器或者稍稍的改變頂點(diǎn)布局,你需要完全的重新創(chuàng)建graphics pipeline。這意味著你必須你將預(yù)先創(chuàng)建很多個VkPipeline的對象。只有少數(shù)一些基本的設(shè)置,如viewport size和clear color可以動態(tài)的改變,所有狀態(tài)都需要明確描述,例如沒有默認(rèn)的顏色混合模式。

好消息是,因為這樣做是ahead-of-time編譯而不是just-in-time編譯,所以驅(qū)動有更多的信息可以用于優(yōu)化,程序的性能會更高。


7 - command pool和command buffer

如前面提到的,vulkan的很多操作如繪圖命令,都是先提交到隊列。命令要先存到VkCommandBuffer中,然后才能提交。這些緩沖是使用VkCommandPool創(chuàng)建的,并且需要指定隊列類型。要繪制一個三角形,我們需要如下操作:

● 開始render pass

● 綁定graphics pipeline

● 繪制3個頂點(diǎn)

● 結(jié)束render pass

因為framebuffer中的圖像取決于swap chain給我們的image,因此我們需要為每個可能的image存一個command buffer,然后在繪制時選擇對應(yīng)的command buffer。另一個方法時在每一幀都存command buffer,但不是最有效的。


8 - 主循環(huán)

當(dāng)繪制命令包裹進(jìn)command buffer后,主循環(huán)就很直截了當(dāng)了。我們先從swap chain中獲得一個image(調(diào)用函數(shù)vkAcquireNextImageKHR)。之后我們可以選擇適合這個image的command buffer,并且用vkQueueSubmit提交命令。最后我們把image還給swap chain用于展示,用vkQueuePresentKHR函數(shù)。

提交的指令被異步的執(zhí)行。因此我們需要使用同步對象例如信號量(semaphore)來保證非沖突訪問。必須在image獲取成功后才能開始執(zhí)行command buffer,否則可能導(dǎo)致image正在被讀取用于展示,但程序卻企圖在上面繪制。另外,vkQueuePresentKHR調(diào)用需要等待渲染結(jié)束,因此我們需要第二個信號量,它在渲染結(jié)束后被產(chǎn)生信號。


Vulkan API的一些概念

所有vulkan的函數(shù),枚舉類和結(jié)構(gòu)體都定義在vulkan.h頭文件中。Vulkan SDK是由LunarG開發(fā)的。

函數(shù)帶有vk前綴,枚舉和結(jié)構(gòu)體類型有Vk前綴,枚舉類型的值有VK_前綴。

API大量使用結(jié)構(gòu)體來傳遞參數(shù)。

例如,對象創(chuàng)建基本上是如下形式:

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::err << "failed to create object" << std::endl;

? ? return false;

}

Vulkan的很多結(jié)構(gòu)體需要在sType字段指定結(jié)構(gòu)體的類型。pNext字段可能指向一個擴(kuò)展結(jié)構(gòu)但是在本教程中將一直是nullptr。創(chuàng)建和銷毀對象的函數(shù),會有一個VkAllocationCallbacks的參數(shù)允許你使用自定義的內(nèi)存分配器,本教程中也全部使用nullptr。

幾乎所有的函數(shù)都返回要么VK_SUCCESS或者一個錯誤碼。


驗證層(Validation layers)

如前面提到的,vulkan被設(shè)計成高效的和低驅(qū)動負(fù)擔(dān)的。所以它之后很有限的錯誤檢查和調(diào)試能力的。如果程序?qū)懙牟粚Γ?jīng)常會直接崩潰而不是返回錯誤代碼,可能更糟糕的是,它好像在你的顯卡可以工作但是在別的顯卡上會完全失敗。

Vulkan允許你使用驗證層來做大量的檢查工作。驗證層是插入到API和顯示驅(qū)動間的代碼,用來做檢查工作,例如函數(shù)參數(shù)檢查,跟蹤內(nèi)存管理問題。好的是你可以在開發(fā)是啟用它,然后在發(fā)布時完全關(guān)閉它使程序沒有這些額外負(fù)擔(dān)。任何人都可以編寫自己的驗證層,但是LunarG的vulkan sdk提供了一套標(biāo)準(zhǔn)的驗證層。此外,你還需要注冊一個回調(diào)函數(shù)來接收這個層返回的調(diào)試消息。

接下來只差一步就可以開始寫代碼了,那就是配置開發(fā)環(huán)境。




















Vulkan 01 簡介的評論 (共 條)

分享到微博請遵守國家法律
独山县| 涡阳县| 如东县| 巴南区| 广宁县| 安新县| 温宿县| 永年县| 渭源县| 图们市| 江津市| 屏东市| 绥棱县| 鹤壁市| 锦州市| 六盘水市| 法库县| 固始县| 吉水县| 海安县| 封开县| 巍山| 东乡县| 西藏| 阿城市| 讷河市| 鄢陵县| 北辰区| 长治市| 阿坝县| 中超| 二手房| 新营市| 东平县| 巴里| 三门峡市| 灵丘县| 忻州市| 新竹市| 太谷县| 独山县|