本文是該系列的最后一篇文章。該系列文章在我的網(wǎng)頁(yè)上已載有數(shù)月,由于Vulkan產(chǎn)品的發(fā)布占用了我很多時(shí)間,最后收官之作的發(fā)表可能有些晚,希望大家還能關(guān)注它。本文中,我將闡述為何Vulkan比上一代API更適合硬件,同時(shí),我還將深入PowerVR GPU的一些細(xì)節(jié),并援引具體案例。
OpenGL ES
首先,讓我們看看當(dāng)下行業(yè)領(lǐng)先的API及其問(wèn)題存在的原因。距OpenGL ES的發(fā)行已有12年多,而API是基于OpenGL ES的產(chǎn)品。OpenGL早在23年前便已設(shè)計(jì)問(wèn)世,其最初設(shè)計(jì)的硬件與當(dāng)下使用的各式硬件大為不同。
狀態(tài)機(jī)
OpenGL是一款大型的全球狀態(tài)機(jī),每次操作均需要考慮當(dāng)前狀態(tài)的各個(gè)部分,如混合模式、當(dāng)前的著色器、深度測(cè)試信息等。所有的事情看似一個(gè)簡(jiǎn)單的制動(dòng)開(kāi)關(guān)或杠桿,可以不計(jì)實(shí)際的后果隨意改變開(kāi)關(guān)狀態(tài)——它只是一個(gè)函數(shù)調(diào)用?對(duì)于現(xiàn)代硬件而言這是不切實(shí)際的——例如很多狀態(tài)會(huì)被轉(zhuǎn)化為著色代碼。
在移動(dòng)產(chǎn)品的高效性一文中,我已經(jīng)提到,考慮到掛接及渲染期間CPU的使用率,著色器修復(fù)是不確定的。還有另一個(gè)我之前未提及的問(wèn)題——著色器本身的低效率。如果必須修復(fù)著色器狀態(tài),則會(huì)出現(xiàn)優(yōu)化后編譯,即附加至剩余的著色器中是有效的。如果在編譯時(shí)狀態(tài)已知,則可以一直優(yōu)化編譯,以避免出現(xiàn)幾條指令。為解決此問(wèn)題,驅(qū)動(dòng)器可能會(huì)進(jìn)行背景的重新編譯,但這本身也是一個(gè)問(wèn)題(消耗更多的CPU時(shí)間)。
隱含同步
OpenGL ES假設(shè)很多東西是相互隱含同步的。只有引入柵欄時(shí),計(jì)算著色器及其不良反應(yīng)才被認(rèn)為是任何形式的異步工作。大部分API僅僅只是工作——事實(shí)上這可以歸結(jié)為資源跟蹤、緩存刷新和場(chǎng)景后的依賴關(guān)系鏈建設(shè)。
驅(qū)動(dòng)器不可能非常準(zhǔn)確地檢測(cè)依賴項(xiàng)——它們十分保守,以能實(shí)現(xiàn)OpenGL ES功能。這意味著將不可避免地進(jìn)行一些不必要的緩存刷新或不必要的序列化工作——換言之,硬件需要做更多的工作。
立即模式
自始至終,OpenGL ES中指定的命令應(yīng)該嚴(yán)格按照規(guī)定的先后順序來(lái)執(zhí)行。一個(gè)簡(jiǎn)單的命令如繪制調(diào)用通常被當(dāng)作一個(gè)單一的整體工作單元,其在GPU中有規(guī)定的隊(duì)列順序。這種行為即立即執(zhí)行模式——每個(gè)指定的工作以某種方式被即刻發(fā)送至GPU進(jìn)行處理。
在過(guò)去,立即渲染模式(IMR)架構(gòu)可以很好地映射到這種思維方式中,但現(xiàn)代IMR傾向于批量處理工作以提高性能。
基于區(qū)塊貼圖的渲染 (TBR)或基于區(qū)塊貼圖的延遲渲染 (TBDR)從未以這種方式工作。迄今為止存在的最多產(chǎn)的類(lèi)型是GPU架構(gòu)類(lèi)型:這些架構(gòu)類(lèi)型的主要工作單元非常大——渲染通道便是很好的詮釋——所有的繪制調(diào)用都集中在相同的幀緩沖區(qū)中。
TBR和TBDR都有兩級(jí)渲染,早期階段主要處理幾何圖形及在屏幕空間貼圖中進(jìn)行分類(lèi)排序。第二階段則將貼圖柵格化,使整個(gè)貼圖完全保存在片上幀緩沖區(qū)中——這可節(jié)省大量的帶寬,其在移動(dòng)市場(chǎng)占據(jù)優(yōu)勢(shì)。Rys Sommefeldt做了更詳細(xì)的闡述,感興趣的可以查閱他的文章。
關(guān)鍵在于,在光柵化階段,繪制調(diào)用是無(wú)意義的——一個(gè)單一的繪制調(diào)用可能產(chǎn)生多個(gè)貼圖的光柵化,每個(gè)貼圖包含了多個(gè)繪制調(diào)用的工作。如果某些信息引起繪圖之間的沖刷,則整個(gè)渲染就會(huì)分裂,這就需要對(duì)很多貼圖進(jìn)行再次渲染。在貼圖開(kāi)始和結(jié)束時(shí),必須加載幀緩沖區(qū)數(shù)據(jù)到貼圖中,并隨后進(jìn)行存儲(chǔ)——這樣重復(fù)多次后便失去了基于區(qū)塊貼圖架構(gòu)的優(yōu)勢(shì),而架構(gòu)本身是極力避免消耗此類(lèi)帶寬的。
總之,現(xiàn)代硬件傾向于批量處理工作,且提交單個(gè)繪制調(diào)用會(huì)降低效率。在OpenGL ES中有很多操作迫使驅(qū)動(dòng)器提交單個(gè)繪制調(diào)用,這一點(diǎn)大家有目共睹。在TBR或TBDR中,這會(huì)產(chǎn)生很多不必要的且驅(qū)動(dòng)器無(wú)力應(yīng)對(duì)的帶寬。
Vulkan
我可能呈現(xiàn)給大家的OpenGL ES是比較沉悶的形象,但不要灰心,不然當(dāng)今的移動(dòng)世界便不會(huì)有如此多精彩的圖像內(nèi)容。
Vulkan甚至比一個(gè)高度優(yōu)化的OpenGL ES驅(qū)動(dòng)器做的更好。我以前提過(guò),Vulkan是顯式的,且需要在應(yīng)用程序中獲取大量的信息——所有這些都是確保Vulkan可以流暢地工作,且不會(huì)產(chǎn)生很多用戶不可見(jiàn)的成本。
管線
Vulkan假定所有的狀態(tài)都將被再次啟用,因此其比OpenGL ES看起來(lái)更為靜態(tài)。管線多采用先前的動(dòng)態(tài)狀態(tài),并與著色器一起被編譯。這意味著任何先前需要著色器修復(fù)的信息現(xiàn)在可以提前被編譯。在編譯時(shí)擁有這些信息意味著可以對(duì)繪制調(diào)用即刻使用的著色器和狀態(tài)進(jìn)行完整的編譯和優(yōu)化,且不需要在渲染循環(huán)中將這些信息進(jìn)行打包處理。
很多許多情況下,一個(gè)應(yīng)用程序可能僅使用一個(gè)著色器及一組或兩組狀態(tài)——保持低成本。然而某些情況下,需要設(shè)置很多不同的狀態(tài),因此會(huì)產(chǎn)生大量的管線對(duì)象。Vulkan沒(méi)有降低管線對(duì)象數(shù)量,同時(shí),通過(guò)使用管線緩存編譯整個(gè)著色器組所花費(fèi)的時(shí)間應(yīng)該具有可比性(或更快)。創(chuàng)建一組管線時(shí),管線緩存是可以與創(chuàng)建信息一起被傳輸?shù)膶?duì)象,且緩存的是有用信息或管線所需的編譯狀態(tài)和著色器。如果兩個(gè)管線具有相同的著色器,但狀態(tài)略有不同,那么創(chuàng)建和編譯的成本將遠(yuǎn)低于單獨(dú)編譯的成本。
PowerVR GPU的管線
以混合狀態(tài)為例——眾所周知,我們沒(méi)有用于混合的固定功能硬件。通常不太需要此類(lèi)硬件——片上存儲(chǔ)非常快,直接在著色器內(nèi)核中混合會(huì)更加簡(jiǎn)單。隨后,在OpenGL ES中設(shè)置混合模式會(huì)產(chǎn)生一組指令,其表示在當(dāng)前著色結(jié)束時(shí)進(jìn)行混合修復(fù)。
正如我之前所說(shuō),著色器修復(fù)可能引起效率降低。而著色器分析顯示,混合修復(fù)則情況不會(huì)太糟,其通常只有一個(gè)或兩個(gè)指令。這看似不切實(shí)際,不然今天我們就得重新審視我們的方案,但其確實(shí)合乎情理。Vulkan在創(chuàng)建管線時(shí)就給了全方位的信息,使我們?cè)诰幾g之前就可以折疊這些指令,精簡(jiǎn)著色器的處理工作。其他狀態(tài)如幀緩沖區(qū)格式和頂點(diǎn)布局可分為相似的類(lèi)型(更瑣碎和不常見(jiàn)的狀態(tài))。
顯示同步
相比其他圖形API,該API的各操作之間有更多的同步控制。主要用“what”、“when”、“where”和“how”信息來(lái)描述內(nèi)存和執(zhí)行依賴關(guān)系。
?依賴關(guān)系中涉及的對(duì)象和操作是什么?
?依賴關(guān)系何時(shí)開(kāi)始何時(shí)結(jié)束?
?依賴關(guān)系在管線的哪個(gè)位置生成(如頂點(diǎn)著色)以及其必須在哪個(gè)位置實(shí)現(xiàn)(如片段著色)?
?相互依賴的雙方如何使用圖像?
所有這些信息可以使驅(qū)動(dòng)器建立一個(gè)全面的依賴關(guān)系鏈,且如果應(yīng)用程序可準(zhǔn)確表示依賴關(guān)系,那么便可以僅僅等待需要絕對(duì)刷新的緩存和絕對(duì)完成的操作。
PowerVR GPU的顯示同步
在基于區(qū)塊貼圖的架構(gòu)中,工作分為了兩個(gè)部分——幾何貼圖階段和光柵化階段。在OpenGL ES中,只有任務(wù)相當(dāng)繁重的手控同步——柵格、隱式同步和內(nèi)存屏障。光柵化階段無(wú)需等待,或者說(shuō)只有在貼圖階段才需要等待——驅(qū)動(dòng)器通過(guò)啟發(fā)式算法來(lái)實(shí)現(xiàn)等待或者完整的同步事件才需要等待——這將嚴(yán)重影響性能。通常,我們?cè)贠penGL ES中使用大量的啟發(fā)式算法來(lái)完成這項(xiàng)工作,但付出的代價(jià)是這樣往往過(guò)于保守,導(dǎo)致性能大為降低。
在Vulkan中,可以使用為每個(gè)同步事件描述的管線級(jí)數(shù)來(lái)決定執(zhí)行哪個(gè)硬件階段。如果在事件早期片段階段需要等待,則可以執(zhí)行貼圖階段來(lái)提前獲取繪制調(diào)用,以求得先機(jī),并在處理過(guò)程中提升性能。同樣,如果貼圖階段的任務(wù)需要等待,則表明在光柵化之前便已經(jīng)開(kāi)始執(zhí)行任務(wù)。這兩種情況都會(huì)導(dǎo)致任務(wù)之間的延遲時(shí)間縮短,并通過(guò)允許多個(gè)任務(wù)的重疊減少在GPU上不必要的空閑時(shí)間。
命令緩沖區(qū)和硬件隊(duì)列
Vulkan使用延期命令提交模型——將繪制調(diào)用記錄成許多命令緩沖區(qū),隨后應(yīng)用程序?qū)⑦@些緩沖區(qū)作為獨(dú)立的操作提交至硬件中。這樣便可以提前了解場(chǎng)景大部分的信息,并適合地優(yōu)化提交內(nèi)容,而這些曾經(jīng)在OpenGL中是很難實(shí)現(xiàn)的。
單獨(dú)的硬件隊(duì)列可以很好地映射到現(xiàn)代GPU中——其通常有一個(gè)或多個(gè)前端輸入隊(duì)列用來(lái)處理命令輸入。準(zhǔn)確地曝光這些隊(duì)列可以給應(yīng)用程序展示一個(gè)底層硬件視圖,而這個(gè)視圖本是不存在的。例如,如果GPU有一個(gè)用于圖形命令的前端——應(yīng)該在API中僅曝光一個(gè)圖形隊(duì)列。隊(duì)列提交是外部同步的,所以驅(qū)動(dòng)器在處理多個(gè)線程時(shí)不需要持有鎖,且由于有一個(gè)緊密的映射到硬件中,隊(duì)列提交是一個(gè)相對(duì)低成本的操作。
PowerVR GPU的命令緩沖區(qū)和硬件隊(duì)列
PowerVR以不同的順序運(yùn)行,這可能原本是對(duì)即時(shí)光柵化程序的預(yù)期,正如上所述。為獲得所需的硬件效率,以一個(gè)特定的方式排列操作至關(guān)重要(而不是即刻提交頂點(diǎn)和光柵任務(wù))。在Vulkan中,應(yīng)用程序提前在命令緩沖區(qū)記錄中明確布局了所有的依賴關(guān)系。記錄命令緩沖區(qū)時(shí),可確定最有效的操作序列并恰當(dāng)?shù)靥峤还ぷ魅蝿?wù)——OpenGL中的工作任務(wù)必須動(dòng)態(tài)完成。正如之前所述,繪制調(diào)用的命令緩沖區(qū)可以用于貼圖任務(wù)和光柵化任務(wù),并被硬件直接消耗。
提交這些命令緩沖區(qū)至隊(duì)列時(shí),功能的實(shí)現(xiàn)則非常簡(jiǎn)單,就如同將那些生成的任務(wù)放入應(yīng)用程序提供了信號(hào)量的硬件中一樣。硬件前端映射至API隊(duì)列的比例并非1:1的,因?yàn)閂ulkan圖像隊(duì)列由兩個(gè)硬件前端(貼圖和光柵化)表示。而這兩個(gè)前端的差別則由API的其他部分表示,如渲染通道對(duì)象和詳細(xì)的同步模型。
渲染通道
渲染通道將一組命令集分成片段。由于渲染通道在基于區(qū)塊貼圖的架構(gòu)中是有效的工作單元,這些片段的命令緩沖區(qū)非常相似。渲染通道不允許出現(xiàn)可能會(huì)導(dǎo)致貼圖中期幀沖刷的命令。其僅允許繪制調(diào)用和其他選擇命令,因?yàn)橘N圖需要渲染通道提供的信息來(lái)有效運(yùn)行。
渲染通道由多個(gè)子通道組成,每一個(gè)通道都能通過(guò)本地?cái)?shù)據(jù)給定像素位置來(lái)與后續(xù)的子通道交流信息。每個(gè)子通道可以定義其附件的加載和存儲(chǔ)操作、與其他子通道的執(zhí)行依賴關(guān)系以及從先前或已保存的通道中讀取的附件清單。
通過(guò)使用子通道信息傳輸,應(yīng)用程序可以采用簡(jiǎn)單的后處理技術(shù)如色度分級(jí)或光暈。更有趣的是,如果應(yīng)用程序使用延遲渲染技術(shù),這可能 (強(qiáng)烈推薦!)是來(lái)表述G緩沖區(qū)的子通道依賴關(guān)系和輸入附件。
在許多情況下,如果附件僅作為中間體使用(Vulkan中存在的比較延遲的分配內(nèi)存類(lèi)型)或用作瞬態(tài)附件使用,則不需要分配附件。渲染通道中任何需使用的附件(在渲染結(jié)束時(shí)沒(méi)有從外源加載或存儲(chǔ))可以被標(biāo)記為瞬態(tài),這使得延遲的內(nèi)存對(duì)象分配方案可以綁定至附件中。延遲分配的內(nèi)存對(duì)象在初次創(chuàng)建時(shí)可能不會(huì)立刻有任何實(shí)際的物理內(nèi)存支持——它們可能完全是空的,也可能是部分分配或完全分配的——這取決于架構(gòu)。在大多數(shù)情況下,它們應(yīng)該為對(duì)象生命周期保持初始狀態(tài),但如果出于某種原因需要分配更多內(nèi)存,則可以進(jìn)行后期綁定操作。需要預(yù)先了解內(nèi)存對(duì)象的最大尺寸,并查詢這些內(nèi)存對(duì)象當(dāng)前允諾的內(nèi)存。
PowerVR GPU的渲染通道
正如上所述,渲染通道禁止任何會(huì)導(dǎo)致中期幀沖刷的平鋪架構(gòu)。于我們而言的確如此,且通過(guò)渲染通道顯式地描述每個(gè)渲染和加載/存儲(chǔ)操作的開(kāi)端和結(jié)束,PowerVR GPU就能以最小的帶寬進(jìn)行操作——僅在渲染完成后才編寫(xiě)附件。
子通道依賴關(guān)系也絕對(duì)不允許存在架構(gòu)在光柵化階段發(fā)生沖刷的情況——這意味著可能要結(jié)合多個(gè)子通道和依賴關(guān)系至一個(gè)單一的渲染通道中。其結(jié)果便是不存在渲染的停止和啟動(dòng),且沒(méi)有顯式存儲(chǔ)的中間附件不需要寫(xiě)入內(nèi)存——它們可以存入貼圖內(nèi)存中。輸入附件至子通道中,當(dāng)從先前的子通道中進(jìn)行編寫(xiě)時(shí),可準(zhǔn)確地映射到硬件的片上貼圖內(nèi)存中。這一點(diǎn)你若很熟悉,可能我們?cè)诟郊?wèn)題上使用了相同的EXT_shader_pixel_local_storage或EXT_shader_framebuffer_fetch。
架構(gòu)中延遲分配的內(nèi)存開(kāi)始是未分配的,因?yàn)槲覀兪孪攘私馔ǔ](méi)有理由分配任何內(nèi)存——其僅作為一個(gè)API構(gòu)造,在渲染期間僅作為一個(gè)片上內(nèi)存的寄存器格式化塊進(jìn)行映射。偶爾,在幀緩沖區(qū)創(chuàng)建時(shí)可能分配少量的內(nèi)存,或在非常罕見(jiàn)的情況下,可能需要分配整個(gè)內(nèi)存對(duì)象。
Conclusion 總結(jié)
相比OpenGL ES,Vulkan映射對(duì)于硬件而言更具優(yōu)勢(shì)。雖然很多人關(guān)注Vulkan改善CPU性能和效率,但很多GPU性能和效率也可以進(jìn)行改善——只不過(guò)它們更精細(xì)。
談?wù)撘苿?dòng)市場(chǎng)的游戲機(jī)品質(zhì)圖像有點(diǎn)陳詞濫調(diào),但它卻無(wú)時(shí)無(wú)刻不出現(xiàn)在我們的生活中!隨著移動(dòng)GPU不斷改善且更有效率,Vulkan也成為邁向游戲機(jī)品質(zhì)圖像之路的堅(jiān)實(shí)一步。
這是本系列的最后一篇文章(有點(diǎn)晚但是完成了!),希望該系列文章可以發(fā)揮其價(jià)值。請(qǐng)關(guān)注我們Twitter (@ImaginationPR @PowerVRInsider)上來(lái)自PowerVR團(tuán)隊(duì)的最新新聞和公告。您還可以查閱Vulkan的相關(guān)博客和在線研討會(huì)獲取資訊。
Vulkan現(xiàn)已發(fā)布,其詳細(xì)信息也即將與大家見(jiàn)面。游戲開(kāi)發(fā)者大會(huì)即將召開(kāi),敬請(qǐng)期待。尤其不要錯(cuò)過(guò)開(kāi)發(fā)者的一天,屆時(shí)我們將討論Vulkan及其他PowerVR主題。我將描述如何在Vulkan中實(shí)現(xiàn)高效渲染的技術(shù),且我將加入圖形小組,討論Vulkan對(duì)圖形生態(tài)系統(tǒng)的影響。感謝您的閱讀!
評(píng)論