Vulkan 和 OpenGL 的區(qū)別
Vulkan 和 OpenGL 區(qū)別,Vulkan 與 OpenGL 相比,可以更詳細(xì)的向顯卡描述你的應(yīng)用程序打算做什么,從而可以獲得更好的性能和更小的驅(qū)動開銷。
Vulkan 的設(shè)計(jì)理念與 Direct3D 12 和 Metal 基本類似,但 Vulkan 作為 OpenGL 的替代者,它設(shè)計(jì)之初就是為了跨平臺實(shí)現(xiàn)的,可以同時在 Windows、Linux 和 Android 開發(fā)。甚至在 Mac OS 系統(tǒng)上,Khronos 也提供了 Vulkan 的 SDK,雖然這個 SDK 底層其實(shí)是使用 MoltenVK 實(shí)現(xiàn)的。
Vulkan的最大任務(wù)不是競爭DirectX,而是取代 OpenGL,所以重點(diǎn)要看和后者的對比。在高分辨率、高畫質(zhì)、需要GPU發(fā)揮的時候,Vulkan、OpenGL的速度基本差不多。
但是隨著分辨率的降低,CPU越來越重要,Vulkan逐漸體現(xiàn)了出來,尤其是看看GTX 980 Ti,最多可以領(lǐng)先OpenGL 33%之多!
基于 OpenGL 的圖形引擎性能瓶頸
基于OpenGL的圖形引擎,其渲染過程粗略可分為主機(jī)端資源加載,設(shè)備端數(shù)據(jù)交互與管線準(zhǔn)備 及 每幀循環(huán)的渲染三個部分。

資源加載
這一過程跟GPU沒有太大關(guān)系,主要是為了進(jìn)行顯示之前的圖片解碼、字體解析、3D模型解析等等。一般可以放到其他線程中執(zhí)行,避免影響顯示。
數(shù)據(jù)交互與管線準(zhǔn)備

這一過程主要是將必要的數(shù)據(jù)傳到GPU可以讀到內(nèi)存中去,以及準(zhǔn)備GPU的指令。主要包含如下三個步驟:
紋理上傳
Shader的編譯與Program的鏈接
VBO的數(shù)據(jù)上傳
每幀的圖形渲染

1?數(shù)據(jù)交互耗時。
這里主要需要設(shè)常量區(qū)的數(shù)據(jù),我們絕大部分情況都是在繪制變化的物體,而變化相關(guān)的屬性主要體現(xiàn)在常量區(qū),因此每幀渲染都需要重新設(shè)一遍常量數(shù)據(jù)。
2?調(diào)用Drawcall耗時。
DrawCall指真正執(zhí)行繪制任務(wù)的圖形API,如glDrawArrays, glDrawElements。調(diào)用這些API時,GPU驅(qū)動需要產(chǎn)生GPU硬件所能識別的任務(wù),并發(fā)送到內(nèi)核,等待調(diào)度執(zhí)行。
Vulkan 編程
詳細(xì)的Vulkan編程流程可以參考Vulkan教程:https://geek-docs.com/vulkan/vulkan-tutorial
編程流程
基本的Vulkan編程流程:

這個流程和OpenGL的使用流程很像,就是找到設(shè)備——創(chuàng)建上下文——創(chuàng)建命令隊(duì)列——準(zhǔn)備任務(wù)——發(fā)送執(zhí)行。
Vulkan的窗口系統(tǒng)(WSI)(與EGL標(biāo)準(zhǔn)類似):

注意到,在移動設(shè)備上使用OpenGL時,我們必須通過egl的API先準(zhǔn)備好Surface和Context,而在Vulkan標(biāo)準(zhǔn)里面,WSI只是為Command Buffer 提供了 VkFrameBuffer,這個是圖形渲染的輸出。
Pipeline
創(chuàng)建Command Buffer 的三個重要元素分別為 VkDescriptorSet(紋理和常量)、VkPipeline(著色器和狀態(tài))和VkBuffer(頂點(diǎn)數(shù)組)。官網(wǎng)上對Pipeline由下圖描述:

以前的GLProgram現(xiàn)在對應(yīng)于一個VkPipeline,但VkPipeline除了Program之外,還覆蓋了 blend,cull face 等狀態(tài):

Vulkan中的 Shader 只支持 spv 的標(biāo)準(zhǔn)二進(jìn)制格式,我們所寫的glsl都必須通過官方的一個轉(zhuǎn)換器轉(zhuǎn)換為二進(jìn)制格式。這樣做就不需要GPU驅(qū)動去做語法解析等編譯前端工作了。
以前在OpenGL中用的Texture 現(xiàn)在由VkImage描述:

Command Buffer
一個用于圖形渲染的 VkCommandBuffer 制作過程如下圖:

如圖所示,Command Buffer 里面設(shè)定了圖形渲染所需要的視口、裁剪、管線(各種狀態(tài)配置和著色器)、頂點(diǎn)數(shù)組、描述(紋理、程序常量等)這些屬性,之后再發(fā)送到命令隊(duì)列(VkQueue)中就可以執(zhí)行。
Vulkan 的優(yōu)勢
效率上的提升
Vulkan在效率上的提升主要是它天然支持多線程
異步數(shù)據(jù)交互
使用OpenGL時,如果把數(shù)據(jù)交互放到另一個獨(dú)立線程中完成,將會引起沖突,這個原因是上傳資源和進(jìn)行繪制時都需要改變上下文:

用Vulkan則沒有這個問題:

并行繪制
由于繪制時要改變上下文,OpenGL的并行繪制無疑也不可能了:

Vulkan可以并行創(chuàng)建 Command Buffer,Command Buffer 提交后就都是GPU驅(qū)動怎么執(zhí)行的事了,執(zhí)行的過程沒必要也沒可能用多線程加速。

復(fù)用Command Buffer
OpenGL 每幀繪制時,都需要在驅(qū)動層重新建一個Command Buffer 傳遞下去,而 Vulkan 是在應(yīng)用層建好 Command Buffer,每幀繪制時Sub上去。
便于模塊化
雖然初看上去 Vulkan 比 OpenGL 復(fù)雜了許多,需要多寫不少代碼,但真正到軟件開發(fā)時,由于Vulkan、OpenGL大部分情況都是用來寫引擎,中間件的,維護(hù)代碼的時間會遠(yuǎn)大于開發(fā)代碼的時間,多寫那幾行代碼根本不算啥。
Vulkan更容易封裝,各子模塊之間互不影響,軟件架構(gòu)設(shè)計(jì)會輕松不少,開發(fā)維護(hù)起來更為方便。
而基于OpenGL開發(fā)的各子模塊之間總有各種各樣因?yàn)闋顟B(tài)機(jī)的緣故引發(fā)的Bug,比如:
A模塊用了VBO,B模塊沒有用,集成在一起時由于B模塊沒有把GL_ARRAY_BUFFER 重新綁定為0,出現(xiàn)段錯誤。
A模塊內(nèi)部使用了FBO,使用FBO時重新設(shè)置了裁剪區(qū)域和視口大小,使用完成后沒有恢復(fù),導(dǎo)致集成之后,后續(xù)的模塊繪制出現(xiàn)問題。如果基于Vulkan開發(fā),上述的狀態(tài)不一致的問題將會少很多。
當(dāng)然,基于Vulkan開發(fā)的引擎一般會用多線程加速,這個也會有不少坑,但為了更好的性能,也是值得的。
Vulkan對開發(fā)者的影響
OpenGL還算是對初學(xué)者比較友好的API,但到了Vulkan,由于嚴(yán)格把pipeline、descriptor、buffer分開,初學(xué)者上手難度變大了,App開發(fā)者直接調(diào)用圖形API的情況將會減少,更多地會依賴于圖形引擎。因此,Vulkan標(biāo)準(zhǔn)的漸漸普及會加速開發(fā)者的層級分劃,使用Vulkan的人將是專業(yè)研究圖形引擎或作GPGPU算法引擎的人。
對于有志于研究圖形的初學(xué)者,可以直接學(xué)習(xí)Vulkan,不用去學(xué)習(xí)OpenGL了,Vulkan標(biāo)準(zhǔn)與GPU工作原理更為貼近,學(xué)習(xí) Vulkan更有利于掌握圖形顯示的知識。
來源:https://geek-docs.com/vulkan/vulkan-tutorial/vulkan-and-opengl.html
