Vulkan 是一套革命性的高性能 3D 圖形、計(jì)算 API恼蓬,適用于現(xiàn)代 GPU 管線系統(tǒng)惊完,用來滿足社區(qū)的苛刻要求。 這套 API 提供了一種全新的方式來克服現(xiàn)有傳統(tǒng) API 的復(fù)雜性和差異性处硬。
Vulkan 是一套“顯式”的 API小槐,承諾可預(yù)測(cè)的行為,并允許您在不引起延遲或拖尾的情況下?lián)碛衅交匿秩編省?本章將對(duì) Vulkan API 以及相對(duì)于它的前身 OpenGL API 來說一些獨(dú)特的功能進(jìn)行一下簡(jiǎn)單的概述荷辕。 我們首先來了解一下 Vulkan 的生態(tài)系統(tǒng)凿跳,并理解它的圖形系統(tǒng)。
所以我們將涵蓋以下主題:
- Vulkan 及其演變
- Vulkan 與 OpenGL
- 在我們開始之前重要的話題
- 學(xué)習(xí) Vulkan 的基礎(chǔ)知識(shí)
- 了解 Vulkan 應(yīng)用程序
- Vulkan 編程模型入門
Vulkan 及其演變
距有名的 OpenGL API 誕生已有將近四分之一世紀(jì)的時(shí)間疮方,而且還在不斷發(fā)展中控嗜, 在其內(nèi)部,它是一個(gè)純粹的狀態(tài)機(jī)骡显,包含多個(gè)工作在二進(jìn)制狀態(tài)下(開狀態(tài) / 關(guān)狀態(tài))的開關(guān)疆栏。 這些狀態(tài)用于在驅(qū)動(dòng)程序中構(gòu)建依賴關(guān)系的映射,實(shí)現(xiàn)資源的管理并以最優(yōu)的方式控制資源惫谤,從而獲得最佳的性能壁顶。 這種狀態(tài)機(jī)隱式地進(jìn)行自動(dòng)化資源的管理,但是對(duì)于捕獲應(yīng)用程序的邏輯來說溜歪,還不夠智能若专,而這恰恰正是資源管理背后的驅(qū)動(dòng)力, 因此蝴猪,可能會(huì)出現(xiàn)一些意想不到的情況调衰,例如實(shí)現(xiàn)中斷,即使應(yīng)用程序未請(qǐng)求重新編譯著色器拯腮,也會(huì)導(dǎo)致重新編譯著色器窖式。 另外,OpenGL API 可能還會(huì)受到其他因素的影響动壤,例如不可預(yù)知的行為萝喘,多線程可伸縮性,渲染故障等。 在本章的后續(xù)內(nèi)容中阁簸,我們將比較 OpenGL 和 Vulkan API爬早,以了解兩者之間的區(qū)別。
Vulkan API 于 2016 年由 Khronos 推出启妹,是一種具有革命性的架構(gòu)筛严,充分利用了現(xiàn)代圖形處理器單元,用來生成高性能的圖形和計(jì)算應(yīng)用程序饶米。 如果您不知道 Khronos桨啃,它是一個(gè)多個(gè)會(huì)員和組織的協(xié)會(huì),專注于為免授權(quán)費(fèi)的 API 制定開放標(biāo)準(zhǔn)檬输。 有關(guān)更多信息照瘾,請(qǐng)參閱 https://www.khronos.org。
Vulkan 的最初概念是由 AMD 根據(jù)其專有的 Mantle API 設(shè)計(jì)和開發(fā)的丧慈。 該 API 通過幾款游戲展示了先進(jìn)的功能析命,從而證明了其革命性的方法并滿足了行業(yè)的所有競(jìng)爭(zhēng)需求。 AMD 將他們的 Mantle API 開源并將其捐贈(zèng)給 Khronos逃默。 Khronos 聯(lián)盟在許多其他硬件和軟件供應(yīng)商的幫助下鹃愤,共同努力發(fā)布 Vulkan。
Vulkan 并非唯一的次世代 3D 圖形 API; 還有一些競(jìng)爭(zhēng)對(duì)手完域,比如微軟的 Direct-X 12 和蘋果的 Metal软吐。 但是,Direct-X 僅限于 Windows 系統(tǒng)筒主,而 Metal 只適用于 Mac 系統(tǒng)(OS X 和 iOS)关噪。 Vulkan 在這方面比較與眾不同鸟蟹。 其跨平臺(tái)特性支持幾乎所有可用的操作系統(tǒng)平臺(tái)乌妙,其中包括 Windows(XP,Vista建钥,7,8 和 10)藤韵,Linux,Tizen熊经,SteamOS 以及 Android泽艘。
Vulkan 對(duì)比 OpenGL
以下是 Vulkan 中的特性和改進(jìn),相較于 OpenGL 具有更多的優(yōu)勢(shì):
降低驅(qū)動(dòng)程序的開銷以及 CPU 使用率:Vulkan 旨在更接近底層的圖形硬件镐依。 因此匹涮,它為上層的應(yīng)用程序員提供了對(duì)主機(jī)計(jì)算資源的直接控制,以使 GPU 盡可能快地進(jìn)行渲染槐壳, 這種方式同時(shí)也允許軟件直接訪問圖形處理器然低,從而獲得更好的性能。
多線程可擴(kuò)展性:OpenGL 中的多線程擴(kuò)展效果非常差,要想利用線程的特性雳攘,從而更好地利用 CPU 是一件非常困難的事带兜。 然而,Vulkan 對(duì)此進(jìn)行了專門設(shè)計(jì)吨灭,用于允許終端用戶以一種非常透明的方式充分利用 CPU 的多線程特性刚照,不存在隱式的全局狀態(tài)。 從創(chuàng)建作業(yè)以及提交作業(yè)(用于執(zhí)行)時(shí)開始喧兄,不同線程下的作業(yè)之間會(huì)保持分離无畔。
一套“顯式”的 API:OpenGL 是一套“隱式”的 API,其中的資源管理是驅(qū)動(dòng)程序的責(zé)任吠冤。 驅(qū)動(dòng)程序需要應(yīng)用程序的提示并跟蹤資源的狀態(tài)檩互,這是一種不必要的開銷。Vulkan 是一套“顯式”的 API; 在這里咨演,驅(qū)動(dòng)程序不負(fù)責(zé)跟蹤資源以及它們之間的關(guān)系闸昨, 把這項(xiàng)任務(wù)分配給了應(yīng)用程序。 這種干凈的方法更可預(yù)測(cè)薄风;驅(qū)動(dòng)程序不會(huì)在幕后執(zhí)行某些操作來管理資源(就像在 OpenGL 中一樣)饵较。 因此,作業(yè)的處理簡(jiǎn)化且直接遭赂,從而實(shí)現(xiàn)最佳性能和可預(yù)測(cè)的行為循诉。
預(yù)編譯的中間著色語言:與需要著色器 shader 作為 OpenGL 著色語言(GLSL)源代碼提供的 OpenGL 不同,SPIR-V(Standard Portable Intermediate Language :標(biāo)準(zhǔn)可移植中間語言)是 Vulkan 用于并行計(jì)算和圖形操作的標(biāo)準(zhǔn)中間語言撇他。
注意茄猫!
用于源語言的編譯器,例如 GLSL困肩,HLSL 或 LLVM 必須符合 SPIR-V 規(guī)范划纽,并提供實(shí)用的工具程序來提供 SPIR-V 的輸入。 Vulkan 采用 Vulkan 這種即時(shí)執(zhí)行的二進(jìn)制中間輸入形式并會(huì)在著色器階段使用锌畸。
- 驅(qū)動(dòng)程序?qū)雍蛻?yīng)用程序?qū)樱涸?OpenGL 中勇劣,與驅(qū)動(dòng)程序?qū)酉啾龋瑧?yīng)用程序?qū)痈√对妫驗(yàn)轵?qū)動(dòng)程序的自動(dòng)化考慮了資源管理和狀態(tài)跟蹤比默,Vulkan 正好與此相反。 它會(huì)確保驅(qū)動(dòng)程序更接近底層的硬件且開銷更小盆犁。 管理邏輯命咐、資源和狀態(tài)是應(yīng)用程序的責(zé)任。 下圖顯示了這兩個(gè) API 的驅(qū)動(dòng)程序和應(yīng)用程序代碼庫的厚度:
內(nèi)存控制:Vulkan 能夠在系統(tǒng)上暴露若干種內(nèi)存類型谐岁,并要求應(yīng)用程序開發(fā)人員為每個(gè)資源的預(yù)期用途選擇適當(dāng)?shù)膬?nèi)存類型醋奠。 相比之下瓮下,OpenGL 驅(qū)動(dòng)程序則會(huì)根據(jù)內(nèi)部啟發(fā)模式?jīng)Q定資源的放置位置,不同供應(yīng)商之間的啟發(fā)模式存在一定的差異钝域,如果稍后驅(qū)動(dòng)程序移動(dòng)了資源讽坏,OpenGL 可能會(huì)產(chǎn)生次優(yōu)的放置或出現(xiàn)意外的故障。
可預(yù)測(cè)性:與 OpenGL 相比例证,Vulkan 具有高度的可預(yù)測(cè)性路呜;它在渲染時(shí)不會(huì)導(dǎo)致任何滯后或掛起。 一旦將作業(yè)提供給驅(qū)動(dòng)程序织咧,就會(huì)立即提交作業(yè)胀葱,而 OpenGL 作業(yè)提交過程不是預(yù)先提供的,而是受到驅(qū)動(dòng)程序調(diào)度程序的支配笙蒙。
一套 API:OpenGL 為桌面 API(OpenGL)和嵌入式 API(OpenGL ES)提供了不同的版本抵屿。 Vulkan 很干凈,只有一套適用于所有平臺(tái)的 API捅位。 Vulkan 支持移動(dòng)平臺(tái)作為一等公民轧葛,對(duì)所有的平臺(tái)一視同仁,而 OpenGL 并非如此艇搀。 通常尿扯,OpenGL 實(shí)現(xiàn)首先出現(xiàn)在基于桌面的版本上,隨后才是可用于嵌入式的 OpenGL ES API焰雕。
直接訪問 GPU:Vulkan 通過公開其功能和硬件設(shè)施衷笋,為應(yīng)用程序用戶提供了很多控制權(quán)。 它公開了各種可用的物理設(shè)備矩屁、內(nèi)存類型辟宗、命令緩沖區(qū)隊(duì)列以及擴(kuò)展。 這種行為可以確保軟件層更接近真實(shí)的硬件吝秕。
錯(cuò)誤檢查和驗(yàn)證:當(dāng)使用 OpenGL 時(shí)泊脐,運(yùn)行良好的應(yīng)用程序在檢查錯(cuò)誤的時(shí)候會(huì)付出一些代價(jià),而錯(cuò)誤在執(zhí)行的時(shí)候根本就不會(huì)觸發(fā)郭膛。 相比之下晨抡,Vulkan 將這些檢查和驗(yàn)證作為附加服務(wù)來提供氛悬,可以在需要時(shí)啟用和禁用则剃。 這些檢查是可選的,可以通過啟用錯(cuò)誤檢查和其他的驗(yàn)證層注入到運(yùn)行時(shí)如捅。 因此棍现,通過避免不必要的檢查,可以減少 CPU 開銷镜遣。 理想情況下己肮,這些錯(cuò)誤和驗(yàn)證層必須在開發(fā)階段的調(diào)試期間打開,并在發(fā)布期間關(guān)閉谎僻。
支持各種 GPU 硬件:Vulkan 支持移動(dòng)設(shè)備光柵化器和桌面光柵器作為實(shí)現(xiàn)的集成部分。 它支持嵌入式平臺(tái)的基于瓦片或延期的光柵化器以及本地基于平鋪的前反饋光柵化器诱鞠。
在我們開始之前重要的話題
在深入探討基本細(xì)節(jié)之前挎挖,先來看看 Vulkan 中用到的一些比較重要技術(shù)術(shù)語。 隨著我們的進(jìn)一步深入航夺,本書還會(huì)涵蓋更多的技術(shù)術(shù)語蕉朵。
物理設(shè)備和設(shè)備:系統(tǒng)可能包含多個(gè)具有 Vulkan 功能的物理硬件設(shè)備。 物理設(shè)備表示唯一的設(shè)備阳掐,而設(shè)備 device 則是指應(yīng)用程序中物理設(shè)備的邏輯表示始衅,即邏輯設(shè)備紊册。
隊(duì)列:隊(duì)列表示執(zhí)行引擎和應(yīng)用程序之間的接口杖挣。 物理設(shè)備始終包含一個(gè)或多個(gè)隊(duì)列(圖形隊(duì)列却嗡、計(jì)算隊(duì)列酣栈、DMA 隊(duì)列 / 傳輸隊(duì)列等)有序。 隊(duì)列的職責(zé)是收集作業(yè)(命令緩沖區(qū))并將其分派給物理設(shè)備進(jìn)行處理通砍。
內(nèi)存類型:Vulkan 公開了各種內(nèi)存類型厕宗。 在更廣泛的層面上觉增,有兩種類型的內(nèi)存:主機(jī)內(nèi)存和設(shè)備內(nèi)存彻亲。 在我們繼續(xù)閱讀本章時(shí)孕锄,我們就會(huì)介紹這些內(nèi)容。
-
命令:命令是做某種行為的指令苞尝。 命令可以大致分為動(dòng)作畸肆,設(shè)置狀態(tài)或者同步。
動(dòng)作命令:這些命令可用于繪制圖元宙址、清除表面轴脐、復(fù)制緩沖區(qū),查詢 / 時(shí)間戳操作以及開始 / 結(jié)束子通道操作抡砂。 這些命令能夠更改幀緩沖區(qū)附件大咱,讀取或?qū)懭雰?nèi)存(緩沖區(qū)或圖像)以及編寫查詢池。
設(shè)置狀態(tài)命令:這些命令用來綁定管線注益、描述符集和緩沖區(qū)碴巾;它們還用于設(shè)置動(dòng)態(tài)狀態(tài)并渲染通道 / 子通狀態(tài)。
同步命令:同步有助于滿足兩個(gè)或多個(gè)操作命令的要求丑搔,這些操作命令可能會(huì)爭(zhēng)奪資源或具有一些內(nèi)存依賴性厦瓢。 其中包括設(shè)置事件提揍、等待事件,插入管線屏障以及渲染通道或子通道的依賴關(guān)系煮仇。
命令緩沖區(qū):命令緩沖區(qū)是一組命令劳跃;它會(huì)記錄這些命令并將它們提交給隊(duì)列。
在下一節(jié)中浙垫,我們會(huì)對(duì) Vulkan 進(jìn)行闡述售碳,以幫助我們了解它的工作模式以及一般的基礎(chǔ)知識(shí)。 我們還會(huì)理解其命令的語法規(guī)則绞呈,通過簡(jiǎn)單地查看它們的聲明來了解 API 命令的概念贸人。
學(xué)習(xí) Vulkan 的基礎(chǔ)知識(shí)
本節(jié)將會(huì)介紹 Vulkan 的基礎(chǔ)知識(shí)。 這里我們將討論以下內(nèi)容:
- Vulkan 的執(zhí)行模型
- Vulkan 的隊(duì)列
- 對(duì)象模型
- 對(duì)象生命周期和命令語法
- 錯(cuò)誤檢查和驗(yàn)證
Vulkan 的執(zhí)行模型
具有 Vulkan 功能的系統(tǒng)能夠查詢并顯示系統(tǒng)上可用的物理設(shè)備的數(shù)量佃声。 每個(gè)物理設(shè)備會(huì)暴露一個(gè)或多個(gè)隊(duì)列艺智。 這些隊(duì)列分為不同的族,每個(gè)族都有特定的功能圾亏。 例如十拣,這些功能可能包括圖形、計(jì)算志鹃、數(shù)據(jù)傳輸以及稀疏內(nèi)存管理夭问。 隊(duì)列族的每個(gè)成員都可以包含一個(gè)或多個(gè)類似的隊(duì)列,從而使它們相互兼容曹铃。 例如缰趋,給定的實(shí)現(xiàn)可能支持同一隊(duì)列上的數(shù)據(jù)傳輸和圖形操作。
Vulkan 允許開發(fā)人員通過應(yīng)用程序?qū)?nèi)存控制進(jìn)行顯式的管理陕见, 它公開了設(shè)備上可用的各種類型的堆秘血,其中的每個(gè)堆屬于不同的內(nèi)存區(qū)域。 Vulkan 的執(zhí)行模式非常簡(jiǎn)單直接评甜, 此處灰粮,命令緩沖區(qū)會(huì)被提交到隊(duì)列中,然后由物理設(shè)備使用忍坷,以便進(jìn)行各種處理粘舟。
Vulkan 應(yīng)用程序負(fù)責(zé)控制各種 Vulkan 設(shè)備,這是通過把大量的命令記錄到命令緩沖區(qū)并將它們提交到隊(duì)列中實(shí)現(xiàn)的佩研。 該隊(duì)列由驅(qū)動(dòng)程序讀取柑肴,驅(qū)動(dòng)程序會(huì)按提交的順序預(yù)先執(zhí)行作業(yè)。 命令緩沖區(qū)的構(gòu)建非常昂貴韧骗, 因此嘉抒,一旦構(gòu)建完成,就可以對(duì)它進(jìn)行緩存以及將其提交到隊(duì)列中袍暴,以便根據(jù)具體的需求執(zhí)行若干次些侍。 此外,在應(yīng)用程序中政模,可以使用多線程同時(shí)并行構(gòu)建多個(gè)命令緩沖區(qū)岗宣。
下圖顯示了執(zhí)行模型的簡(jiǎn)化圖示:
在這里,應(yīng)用程序記錄了兩個(gè)包含多個(gè)命令的命令緩沖區(qū)淋样。 然后根據(jù)工作性質(zhì)將這些命令提供給一個(gè)或多個(gè)隊(duì)列耗式。 隊(duì)列將這些命令緩沖區(qū)作業(yè)提交給設(shè)備進(jìn)行處理。 最后趁猴,設(shè)備處理結(jié)果并將其顯示在輸出顯示屏上刊咳,或?qū)⑺鼈兎祷亟o應(yīng)用程序進(jìn)行進(jìn)一步的處理。
在 Vulkan 中儡司,應(yīng)用程序負(fù)責(zé)以下內(nèi)容:
為成功執(zhí)行命令提供所有必要的先決條件:這其中可能包括準(zhǔn)備資源娱挨、預(yù)編譯的著色器以及將資源附加到著色器、指定渲染狀態(tài)捕犬、構(gòu)建管線以及繪制調(diào)用跷坝。
內(nèi)存管理
-
同步
- 主機(jī)和設(shè)備之間的同步
- 設(shè)備上可用的不同隊(duì)列之間的同步
危害管理
Vulkan 的隊(duì)列
隊(duì)列是 Vulkan 中的媒介,就是通過它將命令緩沖區(qū)送入設(shè)備的碉碉。 命令緩沖區(qū)會(huì)記錄一個(gè)或多個(gè)命令并將它們提交到所需的隊(duì)列柴钻。 設(shè)備也可能會(huì)公開多種隊(duì)列,因此垢粮,應(yīng)用程序有責(zé)任將命令緩沖區(qū)提交給正確的隊(duì)列贴届。
可以將命令緩沖區(qū)提交給以下幾項(xiàng):
- 一個(gè)隊(duì)列
- 命令緩沖區(qū)的提交順序以及執(zhí)行、回放都將保持不變
- 命令緩沖區(qū)以串行方式執(zhí)行
- 多個(gè)隊(duì)列
- 允許在兩個(gè)或多個(gè)隊(duì)列中并行執(zhí)行命令緩沖區(qū)蜡吧。
- 除非明確指定粱腻,否則無法保證命令緩沖區(qū)的提交和執(zhí)行順序, 同步它們的順序是應(yīng)用程序的責(zé)任斩跌;如果沒有進(jìn)行同步绍些,執(zhí)行的順序可能完全超出預(yù)期。
Vulkan 提供了幾種同步方式耀鸦,使您可以在單個(gè)隊(duì)列或跨越多個(gè)隊(duì)列對(duì)作業(yè)的執(zhí)行進(jìn)行相對(duì)控制柬批。 這些同步方式有:
-
信號(hào)量(Semaphore):
該同步機(jī)制可以跨多個(gè)隊(duì)列進(jìn)行同步,或在單個(gè)隊(duì)列中同步粗粒度的命令緩沖區(qū)提交袖订。 -
事件(Events):
事件用來控制細(xì)粒度的同步并且被應(yīng)用于單個(gè)隊(duì)列氮帐,允許我們對(duì)提交給單個(gè)隊(duì)列的一個(gè)命令緩沖區(qū)或若干個(gè)命令緩沖區(qū)序列之間進(jìn)行同步工作。 宿主機(jī)也可以參與基于事件的同步洛姑。 - 柵欄(Fences) :該方式能夠在主機(jī)和設(shè)備之間進(jìn)行同步操作上沐。
- 管線屏障(Pipeline barriers): 管線屏障是一個(gè)插入指令,用于確保在在該命令緩沖區(qū)中楞艾,在管線屏障之前的命令必須在被指定的参咙、管線屏障之后的命令之前執(zhí)行龄广。
對(duì)象模型
在應(yīng)用程序級(jí)別,所有的實(shí)體(包括設(shè)備蕴侧、隊(duì)列择同、命令緩沖區(qū)、幀緩沖區(qū)净宵、管線等)都稱為 Vulkan 對(duì)象敲才。 在內(nèi)部,在 API 級(jí)別择葡,這些 Vulkan 對(duì)象用句柄進(jìn)行識(shí)別紧武。 這些句柄有兩種類型:可分發(fā)句柄和不可分發(fā)句柄。
- 可分發(fā)句柄(A dispatchable handle):這是一個(gè)指針敏储,指向了內(nèi)部不透明形狀的實(shí)體(opaque-shaped entity)阻星。 不透明的類型不允許您直接訪問這種結(jié)構(gòu)的字段。 只能使用 API 例程訪問這些字段虹曙。 每個(gè)可分發(fā)句柄都有一個(gè)關(guān)聯(lián)的可分發(fā)類型(dispatchable type)----- 用于在 API 命令中作為參數(shù)傳遞迫横。 下面是一些示例:
VkInstance | VkCommandBuffer | VkPhysicalDevice | VkDevice | VkQueue |
---|
- 不可分發(fā)句柄(Non-dispatchable handles):這些是 64 位整型類型的句柄,可以包含對(duì)象信息本身酝碳,而不是指向結(jié)構(gòu)的指針矾踱。 示例如下:
VkSemaphore | VkFence | VkQueryPool | VkBufferView |
---|---|---|---|
VkDeviceMemory | VkBuffer | VkImage | VkPipeline |
VkShaderModule | VkSampler | VkRenderPass | VkDescriptorPool |
VkDescriptorSetLayout | VkFramebuffer | VkPipelineCache | VkCommandPool |
VkDescriptorSet | VkEvent | VkPipelineLayout | VkImageView |
對(duì)象生命周期和命令語法
在 Vulkan 中,根據(jù)每個(gè)應(yīng)用程序的邏輯疏哗,都要顯式創(chuàng)建和銷毀對(duì)象呛讲,并且應(yīng)用程序要負(fù)責(zé)管理這些對(duì)象。
Vulkan 中的對(duì)象使用 Create 創(chuàng)建并使用 Destroy 命令銷毀:
- 創(chuàng)建語法:對(duì)象是使用 vkCreate *形式的命令創(chuàng)建的返奉;這類命令接受一個(gè) Vk * CreateInfo 結(jié)構(gòu)作為輸入?yún)?shù)贝搁。
- 銷毀語法:對(duì)應(yīng)的,使用 vkCreate*命令生成的對(duì)象要使用 vkDestroy *進(jìn)行銷毀芽偏。
作為現(xiàn)有對(duì)象池或堆的一部分而創(chuàng)建的對(duì)象要使用 Allocate 命令創(chuàng)建并使用 Free 命令從池或者堆中進(jìn)行釋放雷逆。
- 分配語法:作為對(duì)象池的一部分創(chuàng)建的對(duì)象使用 vkAllocate *形式的命令,并且使用 Vk * AllocateInfo 作為輸入?yún)?shù)污尉。
- 銷毀語法:相應(yīng)的膀哲,使用 vkFree *命令把對(duì)象釋放回池或者內(nèi)存中。
使用 vkGet *命令可以輕松訪問任何給定的實(shí)現(xiàn)信息被碗。 vkCmd *形式的 API 實(shí)現(xiàn)用于在命令緩沖區(qū)中記錄命令某宪。
錯(cuò)誤檢查和驗(yàn)證
Vulkan 專為提供高性能而設(shè)計(jì),這是通過保持錯(cuò)誤檢查和驗(yàn)證功能作為一種可選項(xiàng)的形式實(shí)現(xiàn)的锐朴。 在運(yùn)行時(shí)兴喂,錯(cuò)誤檢查和驗(yàn)證的部分少之又少,從而使得構(gòu)建命令緩沖區(qū)和提交變得更加高效。 這些可選功能可以通過 Vulkan 的分層體系結(jié)構(gòu)來實(shí)現(xiàn)衣迷,該分層體系結(jié)構(gòu)允許把各種層(調(diào)試層和驗(yàn)證層)動(dòng)態(tài)注入到正在運(yùn)行的系統(tǒng)中畏鼓。
了解 Vulkan 應(yīng)用
本節(jié)將為您提供有助于構(gòu)建 Vulkan 應(yīng)用程序的各種組件的概述。
以下框圖顯示了系統(tǒng)中不同組件模塊以及對(duì)應(yīng)的聯(lián)系:
驅(qū)動(dòng)程序
具有 Vulkan 功能的系統(tǒng)至少包含一個(gè) CPU 和 GPU蘑险。 IHV 的供應(yīng)商為其專用 GPU 架構(gòu)提供了指定 Vulkan 規(guī)范實(shí)現(xiàn)的驅(qū)動(dòng)程序滴肿。 驅(qū)動(dòng)程序充當(dāng)應(yīng)用程序和設(shè)備本身之間的接口岳悟。 它為應(yīng)用程序提供了一些高級(jí)設(shè)施佃迄,以便能夠與設(shè)備進(jìn)行通信。 例如贵少,驅(qū)動(dòng)程序通知了系統(tǒng)上可用的設(shè)備數(shù)量呵俏、它們的隊(duì)列和隊(duì)列功能、可用的堆及其相關(guān)屬性等滔灶。
應(yīng)用程序
應(yīng)用程序是指用戶編寫的程序普碎,旨在利用 Vulkan API 來執(zhí)行圖形或計(jì)算任務(wù)。 應(yīng)用程序從硬件和軟件的初始化開始录平,它會(huì)檢測(cè)驅(qū)動(dòng)程序并加載所有的 Vulkan API麻车。 展示層(presentation layer)使用 Vulkan 的 窗口系統(tǒng)集成 ---Window System Integration ---(WSI)API 進(jìn)行初始化;WSI 將用于渲染期間在顯示表面(display surface)上繪制圖形圖像斗这。 應(yīng)用程序創(chuàng)建資源并使用描述符(descriptors)將它們綁定到著色器階段(shader stage)动猬。 描述符集布局(descriptor set layout)用于把創(chuàng)建的資源綁定到創(chuàng)建的底層管線對(duì)象 pipeline object(圖形或計(jì)算類型 graphics or compute type)。 最后表箭,記錄命令緩沖區(qū)并將其提交到隊(duì)列進(jìn)行處理赁咙。
WSI
窗口系統(tǒng)集成 WSI(Windows System Integration )是來自 Khronos 的一組擴(kuò)展,用于跨平臺(tái)(如 Linux免钻,Windows 和 Android)彼水。
SPIR-V
SPIR-V 提供了一種預(yù)編譯的二進(jìn)制格式,用于指定 Vulkan 著色器极舔。 編譯器可用于各種著色器語言凤覆,其中包括能夠生成 SPIR-V 的 GLSL 和 HLSL 變種。
LunarG SDK
LunarG 的 Vulkan SDK 包含了各種工具和資源拆魏,用以輔助 Vulkan 應(yīng)用程序的開發(fā)盯桦。 這些工具和資源包括 Vulkan 加載程序、驗(yàn)證層稽揭、跟蹤和回放工具俺附、SPIR-V 工具、Vulkan 運(yùn)行時(shí)安裝程序溪掀、文檔事镣,示例以及演示,請(qǐng)參閱第 3 章“與設(shè)備握手”查看詳細(xì)的介紹,以便開始使用 LunarG SDK璃哟。 你可以在 http://lunarg.com/vulkan-sdk 閱讀關(guān)于它的更多信息氛琢。
Vulkan 編程模型入門
我們來詳細(xì)討論一下 Vulkan 的編程模型。 在本章随闪,考慮到了一些讀者可能是初學(xué)者阳似,因此使用循序漸進(jìn)的方式。各位看官在這里將會(huì)理解以下一些概念:
- Vulkan 編程模型
- 渲染執(zhí)行模型铐伴,將使用偽代碼逐步驟的方式進(jìn)行描述
- Vulkan 工作原理
下圖顯示了 Vulkan 應(yīng)用程序編程模型自頂向下的方法撮奏;我們會(huì)詳細(xì)了解這一過程,并深入研究各個(gè)子組件及其功能:
硬件初始化
當(dāng) Vulkan 應(yīng)用程序啟動(dòng)的時(shí)候当宴,它的第一個(gè)工作就是硬件的初始化畜吊。 在這個(gè)階段,應(yīng)用程序通過與加載器進(jìn)行通信來激活 Vulkan 驅(qū)動(dòng)程序户矢。 下圖展示了一個(gè)加載器 Loader 及其子組件的框圖:
Loader: 加載程序是應(yīng)用程序啟動(dòng)時(shí)使用的一段代碼玲献,可以跨平臺(tái)、以一種統(tǒng)一的方式在系統(tǒng)中定位 Vulkan 驅(qū)動(dòng)程序梯浪。 以下是加載程序 Loader 的職責(zé):
- 定位驅(qū)動(dòng)程序 Locating drivers: 作為其主要的任務(wù)捌年,加載程序知道在給定系統(tǒng)中到哪里搜索驅(qū)動(dòng)程序。 它會(huì)找到正確的驅(qū)動(dòng)程序并加載挂洛。
- 不依賴平臺(tái) Platform-independent: 初始化 Vulkan 在所有平臺(tái)上都是一致的礼预。 這與 OpenGL 不同,OpenGL 創(chuàng)建上下文需要針對(duì)每個(gè)環(huán)境(EGL抹锄,GLX 和 WGL)使用不同的窗口系統(tǒng) API逆瑞。 Vulkan 中的平臺(tái)差異以擴(kuò)展名表示。
- 可注入的層 Injectable layers:加載器支持層次化的體系結(jié)構(gòu)并提供在運(yùn)行時(shí)注入各層的能力伙单。 最大的改進(jìn)就是驅(qū)動(dòng)程序在確定應(yīng)用程序?qū)?API 的使用是否有效時(shí)不需要執(zhí)行任何工作获高,也不會(huì)保留執(zhí)行該工作所需的任何狀態(tài)。 因此吻育,建議在開發(fā)階段根據(jù)應(yīng)用要求打開選定的可注入層念秧,并在部署階段將其關(guān)閉。 例如布疼,可注入層可以提供以下內(nèi)容:
- 跟蹤 Vulkan API 命令
- 捕獲要渲染的場(chǎng)景并在稍后執(zhí)行場(chǎng)景的渲染
- 用于調(diào)試目的的錯(cuò)誤檢查和驗(yàn)證
Vulkan 應(yīng)用程序首先執(zhí)行與加載程序庫的握手并初始化 Vulkan 具體實(shí)現(xiàn)的驅(qū)動(dòng)程序摊趾。 加載程序庫會(huì)動(dòng)態(tài)加載 Vulkan API。 加載程序還提供了一種機(jī)制游两,允許將特定的層自動(dòng)加載到所有 Vulkan 應(yīng)用程序中砾层;這被稱為隱式啟用層。
一旦加載程序找到驅(qū)動(dòng)程序并成功鏈接到 API贱案,應(yīng)用程序就要負(fù)責(zé)以下操作:
- 創(chuàng)建一個(gè) Vulkan 實(shí)例
- 查詢物理設(shè)備的可用隊(duì)列
- 查詢擴(kuò)展并將它們存儲(chǔ)為函數(shù)指針肛炮,如 WSI 或特殊功能的 API
- 啟用可注入層,進(jìn)行錯(cuò)誤檢查、調(diào)試或驗(yàn)證操作
窗口展示表面 Window presentation surfaces
一旦加載器找到 Vulkan 具體實(shí)現(xiàn)的驅(qū)動(dòng)程序侨糟,我們就可以用 Vulkan API 繪制一些東西碍扔。 為此,我們需要一個(gè)圖像來執(zhí)行繪圖任務(wù)秕重,并將其放在展示窗口中進(jìn)行顯示:
構(gòu)建展示圖像和創(chuàng)建窗口是特定于具體平臺(tái)的操作不同。 在 OpenGL 中,窗口更是和平臺(tái)密切相關(guān)的溶耘;窗口系統(tǒng)的幀緩沖區(qū)與上下文或設(shè)備一起創(chuàng)建二拐。 與 GL 的最大區(qū)別在于,Vulkan 中的上下文或者設(shè)備的創(chuàng)建根本不需要涉及窗口系統(tǒng)汰具;它會(huì)通過窗口系統(tǒng)集成Window System Integration(WSI)進(jìn)行管理卓鹿。
WSI 包含一組跨平臺(tái)的窗口管理擴(kuò)展:
- 針對(duì)大多數(shù)平臺(tái)(如 Windows菱魔,Linux留荔,Android 和其他操作系統(tǒng))的獨(dú)有跨平臺(tái)實(shí)現(xiàn)。
- 一致的 API 標(biāo)準(zhǔn)澜倦,可輕松創(chuàng)建表面并在無需深入細(xì)節(jié)的情況下顯示表面聚蝶。
WSI 支持 Wayland,X 和 Windows 等多種窗口系統(tǒng)藻治,并且通過交換鏈管理圖像的所有權(quán)碘勉。
WSI 提供了交換鏈機(jī)制,這允許以這樣的方式使用多個(gè)圖像桩卵,即當(dāng)窗口系統(tǒng)顯示一個(gè)圖像時(shí)验靡,應(yīng)用程序可以準(zhǔn)備下一個(gè)圖像。
以下屏幕截圖顯示了雙緩沖交換圖像的過程雏节。 它包含名為第一幅圖像和第二幅圖像的兩個(gè)圖像胜嗓。 在 WSI 的幫助下,這些圖像在 Application 和 Display 之間交換:
WSI 作為 Display 和 Application 之間的接口钩乍。 它確保兩個(gè)圖像都是通過顯示 Display 和應(yīng)用程序 Application 以互斥的方式獲取的辞州。 因此,當(dāng)應(yīng)用程序 Application 在第一張圖像上工作時(shí)寥粹,WSI 將切換第二張圖像以顯示其內(nèi)容变过。 一旦應(yīng)用程序 Application 完成繪畫第一張圖片,它將其提交給 WSI涝涤,并作為回報(bào)獲得第二張圖片媚狰,反之亦然。
此時(shí)阔拳,請(qǐng)執(zhí)行以下任務(wù):
- 創(chuàng)建一個(gè)本地窗口(如 Windows 操作系統(tǒng)中的 CreateWindow 方法)
- 創(chuàng)建一個(gè) WSI 表面并附加到窗口
- 創(chuàng)建交換鏈崭孤,用于呈現(xiàn)到表面
- 從創(chuàng)建的交換鏈請(qǐng)求繪圖圖像
設(shè)置資源
設(shè)置資源意味著將數(shù)據(jù)存儲(chǔ)到內(nèi)存區(qū)域,資源可以是任何類型的數(shù)據(jù),例如裳瘪,頂點(diǎn)屬性土浸,如位置、顏色或圖像類型彭羹、名稱黄伊。 當(dāng)然,為了 Vulkan 能歐訪問到這些數(shù)據(jù)派殷,它們已經(jīng)存儲(chǔ)在了內(nèi)存中还最。
與使用提示在背后管理內(nèi)存的 OpenGL 不同,Vulkan 提供了完全底層的訪問和內(nèi)存控制毡惜。 Vulkan 發(fā)布了可以在物理設(shè)備上使用的各種內(nèi)存類型拓轻,這為應(yīng)用程序提供了一個(gè)很好的機(jī)會(huì)來顯式管理這些不同類型的內(nèi)存。
本地主機(jī):這是一種較慢的內(nèi)存類型
本地設(shè)備:這是一種高帶寬的內(nèi)存经伙;速度更快
堆內(nèi)存可以根據(jù)其內(nèi)存類型配置進(jìn)一步劃分:
-
本地設(shè)備:
- 這種類型的內(nèi)存物性地連接到物理設(shè)備:
- 對(duì)設(shè)備可見扶叉,對(duì)主機(jī)不可見
-
本地設(shè)備,主機(jī)可見:
- 此類內(nèi)存也物理性地連接到設(shè)備:
- 對(duì)設(shè)備可見帕膜,對(duì)主機(jī)可見
-
本地主機(jī)枣氧,主機(jī)可見:
- 這是指主機(jī)的本地內(nèi)存,但比本地設(shè)備慢:
- 對(duì)設(shè)備可見垮刹,對(duì)主機(jī)可見
在 Vulkan 中达吞,資源由應(yīng)用程序顯式處理,并獨(dú)占內(nèi)存管理的控制權(quán)荒典。 以下是資源管理的過程:
資源對(duì)象:對(duì)于資源設(shè)置酪劫,應(yīng)用程序負(fù)責(zé)為資源分配內(nèi)存;這些資源可以是圖像或緩沖區(qū)對(duì)象寺董。
分配和二次分配:當(dāng)剛創(chuàng)建資源對(duì)象時(shí)覆糟,只有邏輯地址與它們相關(guān)聯(lián);并沒有實(shí)際可用的物理空間支持螃征。 應(yīng)用程序會(huì)分配物理內(nèi)存并將這些邏輯地址綁定到物理內(nèi)存搪桂。 由于分配存儲(chǔ)空間是一個(gè)昂貴的過程,因此二次分配是管理內(nèi)存的有效方式盯滚;它會(huì)立即分配一大塊物理內(nèi)存并將不同的資源對(duì)象放入其中踢械。 二次分配是應(yīng)用程序的責(zé)任。 下圖顯示了分配的大量物理內(nèi)存中魄藕,二次分配對(duì)象的情況:
-
提示
稀疏內(nèi)存 Sparse memory:對(duì)于非常大的圖像對(duì)象内列,Vulkan 完全支持稀疏內(nèi)存及其所有功能。 稀疏內(nèi)存是一項(xiàng)特殊功能背率,可讓您存儲(chǔ)大型圖像資源话瞧;圖像在內(nèi)存中的存儲(chǔ)容量遠(yuǎn)大于實(shí)際的存儲(chǔ)容量嫩与。 這種技術(shù)是將圖像分解為圖塊,并僅加載適合應(yīng)用程序邏輯的圖塊交排。
暫存緩沖區(qū) Staging buffers:使用暫存的方式完成對(duì)對(duì)象和圖像緩沖區(qū)的填充划滋,其中使用兩個(gè)不同的內(nèi)存區(qū)域用于物理存儲(chǔ)的分配。 主機(jī)可能無法看到資源的理想內(nèi)存布局埃篓。 在這種情況下处坪,應(yīng)用程序必須首先將資源填充到主機(jī)可見的暫存緩沖區(qū)中,然后將其轉(zhuǎn)移到理想的位置架专。
異步傳輸 Asynchronous transfer:使用圖形隊(duì)列或 DMA 隊(duì)列 同窘、傳輸隊(duì)列之類的異步命令異步傳輸數(shù)據(jù)。
物理內(nèi)存分配很昂貴部脚;因此想邦,一個(gè)好的做法是分配一個(gè)大的物理內(nèi)存,然后在其中二次分配對(duì)象委刘。
相比之下丧没,OpenGL 資源管理不提供對(duì)內(nèi)存的精細(xì)控制。 沒有主機(jī)內(nèi)存和設(shè)備內(nèi)存的概念钱雷;驅(qū)動(dòng)程序在后臺(tái)中秘密地做了所有的分配工作骂铁, 而且,這些分配和二次分配的過程并非完全透明罩抗,并且不同的驅(qū)動(dòng)程序之間可能還會(huì)對(duì)這個(gè)操作進(jìn)行調(diào)整,從而產(chǎn)生一些差異灿椅。 缺乏一致性以及隱藏的內(nèi)存管理會(huì)導(dǎo)致不可預(yù)知的行為套蒂。 而另一方面,Vulkan 在所選內(nèi)存中分配對(duì)象茫蛹,使其具有高度的可預(yù)測(cè)性操刀。
因此,在資源設(shè)置階段婴洼,您需要執(zhí)行以下任務(wù):
- 創(chuàng)建資源對(duì)象骨坑。
- 查詢適當(dāng)?shù)膬?nèi)存實(shí)例并創(chuàng)建內(nèi)存對(duì)象,比如緩沖區(qū)和圖像柬采。
- 獲取分配的內(nèi)存要求欢唾。
- 在其中再次分配空間并存儲(chǔ)數(shù)據(jù)。
- 將內(nèi)存與我們創(chuàng)建的資源對(duì)象綁定粉捻。
管線設(shè)置
管線是由應(yīng)用程序邏輯定義的礁遣、固定序列中發(fā)生的一組事件。 這些事件包含以下內(nèi)容:提供著色器肩刃,將它們綁定到資源并管理狀態(tài):
描述符集和描述符池
描述符集是資源和著色器之間的接口祟霍。 這是一個(gè)簡(jiǎn)單的結(jié)構(gòu)杏头,用于將著色器與資源信息(如圖像或緩沖區(qū))綁定。 它關(guān)聯(lián)或綁定著色器將要使用的資源內(nèi)存沸呐。 以下是與描述符集相關(guān)的特征:
頻繁變化:本質(zhì)上醇王,描述符集會(huì)經(jīng)常變化;一般而言崭添,它包含諸如材質(zhì)厦画、紋理等屬性。
描述符池:考慮到描述符集的性質(zhì)滥朱,它們是從描述符池中分配的根暑,而不引入全局同步。
多線程可伸縮性:這允許多個(gè)線程同時(shí)更新描述符集徙邻。
提示
在 Vulkan 渲染中排嫌,更新或更改描述符集是改善性能最關(guān)鍵的途徑之一。 因此缰犁,描述符集的設(shè)計(jì)是實(shí)現(xiàn)性能最大化的一個(gè)重要方面淳地。 Vulkan 支持在場(chǎng)景(低頻更新),模型(中頻更新)和繪圖級(jí)別(高頻更新)的多個(gè)描述符集的邏輯分區(qū)帅容。 這確保了高頻更新描述符不影響低頻率描述符資源颇象。
使用 SPIR-V 的著色器
在 Vulkan 中指定著色器或計(jì)算核心的唯一方法是通過 SPIR-V。 以下是與之相關(guān)的一些特性:
多種輸入:生成的 SPIR-V 編譯器適用于各種源語言并徘,包括 GLSL 和 HLSL遣钳。 這些編譯工具可用于將人類可讀的著色器轉(zhuǎn)換為 SPIR-V 中間表示形式。
離線編譯:Shaders / 內(nèi)核被離線編譯并預(yù)先注入麦乞。
glslangValidator:LunarG SDK 提供 glslangValidator 編譯器蕴茴,可用于從等效的 GLSL 著色器創(chuàng)建 SPIR-V 著色器。
多個(gè)入口點(diǎn):著色器 shader 對(duì)象提供了多個(gè)入口點(diǎn)姐直。 這對(duì)于減少 SPIR-V 著色器的打包尺寸(和加載尺寸)非常有利倦淀。 著色器的各種變體還可以打包成一個(gè)模塊。
管線管理
物理設(shè)備包含一系列的硬件設(shè)置声畏,用于確定提交的撞叽、給定的幾何圖形需要的輸入數(shù)據(jù)如何解釋和繪制。 這些設(shè)置統(tǒng)稱為管線狀態(tài) pipeline states插龄。 這其中包括光柵器狀態(tài)愿棋、混合狀態(tài)和深度模板狀態(tài);它們還包括提交幾何體的基本拓?fù)漕愋停c(diǎn) / 線 / 三角形)以及要用于渲染的著色器辫狼。 有兩種狀態(tài)類型:動(dòng)態(tài)和靜態(tài)初斑。 管線狀態(tài)用于創(chuàng)建管線對(duì)象(圖形對(duì)象或計(jì)算對(duì)象),這是一個(gè)性能優(yōu)化關(guān)鍵點(diǎn)膨处。 因此见秤,我們不想一次又一次地重復(fù)創(chuàng)造管線對(duì)象砂竖;我們希望創(chuàng)建一次并對(duì)其進(jìn)行重用。
Vulkan 允許您使用管線對(duì)象以及管線緩存對(duì)象 Pipeline Cache Object (PCO)和管線布局 pipeline layout來控制狀態(tài):
管線對(duì)象 Pipeline objects:管線的創(chuàng)建非常昂貴鹃答,其中包括著色器重新編譯乎澄、資源綁定、渲染傳遞测摔、幀緩沖區(qū)管理以及其他的相關(guān)操作置济。 管線對(duì)象的狀態(tài)可能有成百上千之多;因此锋八,每個(gè)不同的狀態(tài)組合都存儲(chǔ)為一個(gè)單獨(dú)的管線對(duì)象浙于。
PCO:管線的創(chuàng)建非常昂貴;因此一旦創(chuàng)建挟纱,就可以對(duì)該管線進(jìn)行緩存羞酗。 當(dāng)請(qǐng)求新的管線時(shí),驅(qū)動(dòng)程序可以尋找比較接近的匹配并使用基本管線創(chuàng)建新的管線紊服。
管線緩存是不透明的檀轨,并且驅(qū)動(dòng)程序使用它們的細(xì)節(jié)也并未做詳細(xì)說明。 如果應(yīng)用程序希望在運(yùn)行時(shí)重用緩存欺嗤,并且在創(chuàng)建管線時(shí)提供合適的緩存(如果應(yīng)用程序希望獲得潛在的好處)参萄,則應(yīng)用程序要對(duì)這個(gè)緩存負(fù)責(zé)持久化。
- 管線布局:管線布局描述了要與管線一起使用的描述符集煎饼,指示著色器中每個(gè)綁定槽所連接的資源類型讹挎。 不同的管線對(duì)象可以使用相同的管線布局。
在管線管理階段腺占,會(huì)發(fā)生如下操作:
應(yīng)用程序?qū)⒅骶幾g為 SPIR-V 格式淤袜,并在管線著色器狀態(tài)中指定這種格式的著色器。
描述符幫助我們將這些資源連接到著色器本身衰伯。 應(yīng)用程序從描述符池中分配描述符集,并將傳入或傳出的資源連接到著色器中的綁定槽积蔚。
應(yīng)用程序創(chuàng)建管線對(duì)象意鲸,其中包含靜態(tài)和動(dòng)態(tài)狀態(tài)配置,用來控制硬件的設(shè)置尽爆。 應(yīng)該從管線緩存池創(chuàng)建管線以獲得更好的性能怎顾。
錄制命令
錄制命令是命令緩沖區(qū)形成的過程。 命令緩沖區(qū)是從命令池存儲(chǔ)空間中進(jìn)行分配的漱贱。 命令池也可以用于多個(gè)分配槐雾。 在由應(yīng)用程序定義的給定的起始和結(jié)束范圍內(nèi),通過提供命令來記錄命令緩沖區(qū)幅狮。 下圖說明了繪圖命令緩沖區(qū)的記錄情況募强,如您所見株灸,它包含許多以自上而下的順序記錄的命令,負(fù)責(zé)對(duì)象的繪制擎值。
注意
請(qǐng)注意慌烧,命令緩沖區(qū)中的命令可能因作業(yè)要求而異。 此圖只是一個(gè)說明鸠儿,其中包括了繪制元素時(shí)所執(zhí)行的最常見步驟屹蚊。
繪圖的主要部分覆蓋以下幾個(gè)方面:
范圍:范圍定義了命令緩沖區(qū)記錄的開始和結(jié)束。
渲染通道:它定義了可能影響幀緩沖區(qū)緩存作業(yè)的執(zhí)行過程进每。 其中可能包含附件汹粤,子通道以及這些子通道之間的依賴關(guān)系。 附件是指在哪個(gè)圖像上執(zhí)行繪圖操作田晚。 在子通道中嘱兼,類似附件的圖像可以被子通道化,用于進(jìn)行多重采樣解析肉瓦。Render Pass 還控制著在通道開始時(shí)如何處理幀緩沖區(qū):其或者會(huì)保留有關(guān)它的最后一個(gè)信息遭京,或是使用給定的顏色對(duì)其進(jìn)行清除。 同樣泞莉,在 Render Pass 結(jié)束時(shí)哪雕,結(jié)果會(huì)被丟棄或存儲(chǔ)。
管線:包含由管線對(duì)象表示的狀態(tài)(靜態(tài) / 動(dòng)態(tài))信息鲫趁。
描述符:這會(huì)將資源信息綁定到管線斯嚎。
綁定資源:指定頂點(diǎn)緩沖區(qū)、圖像或其他幾何相關(guān)的信息挨厚。
視口:這決定了要在繪圖表面的哪個(gè)區(qū)域執(zhí)行圖元渲染堡僻。
裁剪器:這定義了一個(gè)矩形的空間區(qū)域,超出這個(gè)范圍就不會(huì)繪制任何東西疫剃。
繪圖:繪圖命令指定幾何緩沖區(qū)的屬性钉疫,例如開始索引、總計(jì)數(shù)等巢价。
提示
創(chuàng)建命令緩沖區(qū)是一個(gè)昂貴的操作牲阁;它被認(rèn)為是性能關(guān)鍵的所在。 如果許多幀需要進(jìn)行相同的操作壤躲,則它可以重復(fù)使用很多次想罕。 命令緩沖區(qū)可以重新提交而無需重新錄制咪奖。 此外囱挑,可以使用多個(gè)線程同時(shí)生成多個(gè)命令緩沖區(qū)赁还。 Vulkan 是專門為利用多線程的可伸縮性而設(shè)計(jì)的。 如果在多線程環(huán)境中使用漏麦,則命令池確保不存在鎖定競(jìng)爭(zhēng)客税。
下圖顯示了一個(gè)具有多核和多線程方法的况褪、可擴(kuò)展的命令緩沖區(qū)創(chuàng)建模型。 該模型使用多核處理器的特性提供了真正意義上的并行性霎挟。
在這里窝剖,每個(gè)線程都使用一個(gè)獨(dú)立的命令緩沖池,同時(shí)該命令緩沖池又分配了一個(gè)或多個(gè)命令緩沖區(qū)酥夭,不允許與資源鎖沖突赐纱。
隊(duì)列提交
一旦構(gòu)建了命令緩沖區(qū),就可以將它們提交到隊(duì)列進(jìn)行處理熬北。 Vulkan 向應(yīng)用程序公開了不同類型的隊(duì)列疙描,例如圖形隊(duì)列、DMA 隊(duì)列讶隐、傳輸隊(duì)列以及計(jì)算隊(duì)列起胰。 用于提交的、隊(duì)列的選擇在很大程度上取決于作業(yè)的性質(zhì)巫延。 例如效五,圖形相關(guān)的任務(wù)必須提交給圖形隊(duì)列。
同樣炉峰,對(duì)于計(jì)算操作畏妖,計(jì)算隊(duì)列就是最佳的選擇。 提交的作業(yè)以異步方式執(zhí)行疼阔。 命令緩沖區(qū)可以被 push 到獨(dú)立的兼容隊(duì)列中戒劫,并允許并行執(zhí)行。 應(yīng)用程序負(fù)責(zé)命令緩沖區(qū)或隊(duì)列之間的所有類型的同步婆廊,即使在主機(jī)和設(shè)備本身之間也是如此迅细。
隊(duì)列提交會(huì)執(zhí)行以下工作:
- 從交換鏈中獲取下一幀要被繪制的圖像,即在該圖像上進(jìn)行繪制淘邻。
- 部署所有同步機(jī)制(如信號(hào)量和 fence 欄柵)需要收集的命令緩沖區(qū)并將其提交到所需的設(shè)備隊(duì)列進(jìn)行處理茵典。
- 請(qǐng)求在輸出設(shè)備上顯示完成的、繪制好的圖像宾舅。
總結(jié)
本章對(duì) Vulkan 進(jìn)行了介紹性的描述敬尺,以便讓初學(xué)者更容易理解。 在本章中贴浙,我們了解了 Vulkan 的發(fā)展歷程,并了解了其背后的歷史和人物署恍。 然后崎溃,我們將這套 Vulkan API 與 OpenGL 進(jìn)行了一些對(duì)比區(qū)分,并理解了 Vulkan 在現(xiàn)代計(jì)算時(shí)代存在的原因盯质。 我們還查看了與此 API 關(guān)聯(lián)的袁串、重要技術(shù)術(shù)語的簡(jiǎn)單定義概而。 Vulkan API 的基本原理為其工作模型提供了精確以及豐富的概述。 我們還看到了 Vulkan 生態(tài)系統(tǒng)的基本組成部分囱修,并了解它們?cè)诨ミB方面的作用和責(zé)任赎瑰。 最后,在本章的末尾破镰,我們了解到 Vulkan 如何使用易于理解的分步操作的偽代碼編程模式的方法餐曼。
完成本章的學(xué)習(xí)后,您會(huì)對(duì) Vulkan API 及其詳細(xì)的工作模型會(huì)有一個(gè)基本的理解鲜漩,并熟悉了其技術(shù)術(shù)語源譬,以便在 Vulkan 編程中邁出第一步。
在下一章中孕似,我們將使用偽代碼的方式開始 Vulkan 編程踩娘。 我們將創(chuàng)建一個(gè)簡(jiǎn)單的示例,但不會(huì)涉及太多細(xì)節(jié)喉祭,不過仍會(huì)涵蓋重要的核心方面养渴、Vulkan API 的基礎(chǔ)知識(shí)和數(shù)據(jù)結(jié)構(gòu),以此來了解 Vulkan 中圖形管線編程的完整流程泛烙。