在現(xiàn)代渲染環(huán)境中,很多情況下在一個數(shù)據(jù)幀期間會產(chǎn)生計算負(fù)荷。在GPU上計算通常(非固定功能)是并行編程的,通常用于具有挑戰(zhàn)性,完全不可能或僅通過標(biāo)準(zhǔn)圖形管道(頂點/幾何/細(xì)化/柵格/碎片)實現(xiàn)的效率低下的技術(shù)。一般情況下,計算在實現(xiàn)技術(shù)方面提供了幾乎絕對的靈活性。但是這種普遍性帶來了其他挑戰(zhàn):在同步渲染任務(wù)方面,GPU可以做出的假設(shè)要少得多,尤其是在我們嘗試優(yōu)化GPU并使負(fù)載飽和的情況下。 無需過多的討論,保持GPU的占用率至關(guān)重要。實際上,這是最重要的性能因素。如果GPU沒有做任何事情,或者沒有被充分利用,而我們的幀速率目標(biāo)尚未實現(xiàn),那么嘗試對應(yīng)用程序進(jìn)行微優(yōu)化實際上是毫無意義的。 另一方面,當(dāng)達(dá)到我們的最大幀速率指標(biāo)時,這種情況會逆轉(zhuǎn):如果我們已經(jīng)在分配的最小幀時間內(nèi)渲染了我們需要渲染的所有內(nèi)容——換句話說是顯示了我們需要的盡可能多的數(shù)據(jù)幀——我們應(yīng)該允許GPU處于空閑狀態(tài),從而減少功耗并釋放更少的熱量。但是這不是沒有正確同步的借口,如果同步不正確將不會很好的吸收小的負(fù)載峰值并可能導(dǎo)致不必要的FPS波動。 要在Vulkan中進(jìn)行同步,從概念上講我們需要清楚不同操作之間的依賴關(guān)系。Vulkan在這方面非常靈活且功能強(qiáng)大。但是這種靈活性可以說是一把雙刃劍,隨著同步變得復(fù)雜和冗長,該任務(wù)可能會變得艱巨并且要推理出最佳路徑也不是一個簡單的任務(wù)。用于同步的工具有barriers、Events、Semaphore (信號量)和Fences(柵欄),每個都在不同情況下強(qiáng)制執(zhí)行操作順序。最常見且最輕量級的是barrier,它僅在GPU本身之前和之后強(qiáng)制執(zhí)行指定類型的命令。 本質(zhì)上,barrier通常是用來搞清楚源程序和目標(biāo)程序的依賴關(guān)系。具體可描述為:“對于到目前為止已記錄的所有圖形命令,確保至少已執(zhí)行其片段步驟,在開始執(zhí)行頂點步驟之前記錄此點后續(xù)的圖形命令數(shù)。 例如,一個通道的彩色附件(color attachment)被用于另一個通道的輸入附件(input attachment)(不考慮subpass dependencies的特殊情況)。 然后將包含此barrier的渲染命令緩沖區(qū)提交到隊列中,它將對該隊列中的所有命令生效(對后文的提示)。如果我們需要在不同的隊列中使用這種效果,正確的原語是一個semaphore(信號量)。如果需要同步以等待CPU的事件,則可以使用fence或event(事件)。如果我們想在CPU/GPU之間進(jìn)行任意的同步則可以使用event(事件)。 在我們特定的案例中,barrier的作用如下:
“對于到目前為止已記錄的所有計算命令確保他們執(zhí)行完成,在開始頂點步驟之前記錄后續(xù)的圖形命令數(shù)量?!蔽覀儗⑵浞Q為計算——圖形barrier。
首要的事情:工具選擇
在PowerVR平臺上進(jìn)行任何性能調(diào)整時,你最好的朋友是PVRTune。PVRTune是我們的GPU分析應(yīng)用程序,可提供絕對全面的信息。這包括在GPU上實時執(zhí)行的所有任務(wù),大量硬件計數(shù)器,負(fù)載等級,處理速率等。我們不能對此施加太大壓力——PVRTune應(yīng)該始終是在設(shè)備上對應(yīng)用程序進(jìn)行性能分析的第一站和最后一站。它支持所有PowerVR平臺,因此請確保下載PVRTune和所有其他免費(fèi)的PowerVR工具。
關(guān)于圖表的注釋
對于本文中下面的所有示例,為了簡單起見我們將忽略tiler任務(wù)(在圖表中標(biāo)記為TN)。
Tiler在這里指的是與頂點(Vertex)任務(wù)相同的處理階段,這兩個術(shù)語可以互換使用。 渲染器(Renderer)指的是相同的處理階段碎片/像素任務(wù),這些術(shù)語可以互換使用。 總的來說,我們在本文中所指的內(nèi)容可以擴(kuò)展到“頂點任務(wù)”,但是頂點任務(wù)通常更容易處理,因為它們傾向于自然的重疊中間幀計算任務(wù),這是此處討論的最困難的情況,通常與片段階段有依賴性。 但是如果你具有計算(compute)->vertex(甚至是vertex->compute)的barrier,則頂點任務(wù)可能會發(fā)生具有完全相同解決方案的類似情況。關(guān)于多緩沖(multi-buffering)的說明在臺式機(jī)上雙倍緩沖(double-buffering,在交換鏈中使用兩個幀緩沖圖像)似乎是目前的標(biāo)準(zhǔn)。 但是雙緩沖(double-buffering)實際上不允許你在移動設(shè)備上重疊來自不同幀的操作。PowerVR是基于分塊延遲渲染(TBDR)的體系結(jié)構(gòu),可以充分利用并行處理多個幀的功能。根據(jù)Vulkan規(guī)范,如果不夠詳細(xì),通常就無法渲染在當(dāng)前屏幕上呈現(xiàn)的幀緩沖區(qū)圖像。這意味著在任何的時間點GPU都只能主動渲染“空閑狀態(tài)”的圖像(后臺緩沖區(qū))。 因此強(qiáng)烈建議使用三個幀緩沖圖像創(chuàng)建交換鏈,特別是在啟用垂直同步(Vsync)的情況下(或在Android平臺上強(qiáng)制啟用)。這種技術(shù)通常被稱為三重緩沖,并且可以提供比雙緩沖更高的性能。 與雙緩沖相比三重緩沖的缺點是它引入了額外的幀延遲,在某些延遲敏感的情況下(如臺式機(jī)上高FPS的競爭類游戲)這可能是不允許的,但在移動設(shè)備上很少出現(xiàn)此問題。 但是本文不是關(guān)于多緩沖的文章,因此我們將不做進(jìn)一步的詳細(xì)說明,僅說明本文假設(shè)你正在使用三個幀緩沖圖像來利用這種并行性即可。如果你使用的是PowerVR SDK和其他可能的解決方案則默認(rèn)為是三重緩沖模式。
瑣碎情況
對于計算和圖形負(fù)載而言,一個瑣碎(但不常見)的案例在并行處理方面可能是令人尷尬的:彼此完全獨(dú)立并且可以完全并行執(zhí)行。如果我們在每一幀中都有一些無關(guān)的任務(wù),例如為兩個彼此不交互的屏幕渲染兩個不同的工作負(fù)載就會發(fā)生這種情況。在這些之間通常不需要發(fā)生任何barrier(或其他同步原語),因此GPU可以并行的調(diào)度它們。
在API方面調(diào)用如下所示: 計算調(diào)度->繪制->展示 在PVRTune中計算和圖形任務(wù)可能如下所示: (數(shù)字表示不同框架中的任務(wù)) ————————
計算負(fù)載:B0 B1 B2 B3....
圖形負(fù)載:A0 A1 A2 A3....

異?,嵥榈墓ぷ髫?fù)載,沒有同步原語會阻止
不同任務(wù)的重疊,這是瑣碎且罕見的情況。
這可以帶來巨大的好處:通過更多的任務(wù)來安排進(jìn)出時間,GPU可以隱藏延遲并提供良好的性能優(yōu)勢,而不是一個接一個的執(zhí)行這些任務(wù)。但是這種“令人尷尬的并行操作”的情況在這里并不會特別令人感興趣,也不是那么的普遍。但是它強(qiáng)調(diào)了一個有用但并不總是顯而易見的原則:僅同步所需的內(nèi)容。
簡單情況
這種情況不常見,我們對此并不感興趣。更常見的是需要圖形工作負(fù)載之前發(fā)生的計算工作負(fù)載。這可能是某種頂點處理,計算剔除,幾何圖形生成或圖像幀中要求的其他操作。通常頂點著色器需要這些數(shù)據(jù),在這種情況下我們將需要在vkCmdDispatchCompute和vkCmdDrawXXX之間插入vkCmdPipelineBarrier,以實現(xiàn)這種事前發(fā)生的關(guān)系。
調(diào)用流程看起來如下所示: 計算調(diào)度-->Barrier(源:計算,目標(biāo):圖形/頂點)->繪制->展示 或者可能正好相反,例如執(zhí)行一些計算后處理任務(wù)。但是這意味著直接通過計算(compute)寫入緩沖區(qū),這通常不是理想的情況:片段流水線為寫入幀緩沖區(qū)進(jìn)行了優(yōu)化,具有幀緩沖區(qū)壓縮等諸多優(yōu)點。 繪制->Barrier(源:圖形/片段,目標(biāo):計算)->計算調(diào)度->展示 可能會錯誤的期望會發(fā)生這樣的事情,實際上如果我們只對緩沖區(qū)進(jìn)行雙緩沖或進(jìn)行某種形式的過度同步操作,我們可能最終會失敗。 如果我們使用雙緩沖而不是三重緩沖則需要等待Vsync才能繼續(xù)渲染,因此可能會丟失很多并行操作 ———————— 計算負(fù)載:B0 B1 B2 B3 B4...
圖形負(fù)載:A0 A1 A2 A3 A4...

BARRIER計算->Vertex(橙色虛線)可正確防止
AN/BN重疊->其他因素可防止AN/BN+1重疊
注:此圖只是理論上的,假設(shè)滿足以下條件:
我們正在使用三重緩沖
未啟用Vsync或我們尚未達(dá)到硬件平臺的最大FPS
如果我們正確同步并以最大Vsync fps(通常為60fps)進(jìn)行同步,則這種情況變得完全有效:如果沒有足夠的負(fù)載要執(zhí)行,GPU將更加省力甚至處于空閑狀態(tài),從而節(jié)省功耗,并且任務(wù)會像這樣自然的序列化執(zhí)行。在這些情況下這是有效且可取的。此處的轉(zhuǎn)折點是對于低于最大FPS運(yùn)行的應(yīng)用程序不應(yīng)該發(fā)生這種情況。 在這種情況下我們期望的重疊要好得多,如果我們使用三重緩沖并且不過度同步通常會發(fā)生什么。GPU應(yīng)該能夠通過下一幀(N+1)的計算操作來調(diào)度這一幀(N),因為通常不會存在Barrier來阻止這種情況的發(fā)生。如前文所述我們需要這種并行性來實現(xiàn)最佳性能。
計算負(fù)載:B0 B1 B2 B3...
圖形負(fù)載:A0 A1 A2 A3....

在圖形之前計算,BARRIER計算頂點(橙色部分)可以正確方式AN-TN/BN的混疊,但允許BN+1/TN-AN的重疊 在繪制對象之前我們需要準(zhǔn)備好它們,不過在很多情況下我們不需要前一幀的渲染即可渲染后一幀,因此在這種情況下GPU可以自由的允許BN+1/AN 重疊并很好的進(jìn)行封裝以提高性能。
更加復(fù)雜難纏的情況
像往常一樣事情并非如此簡單,當(dāng)你轉(zhuǎn)向高級多通道流水線時,我們的渲染操作往往比這復(fù)雜得多。即使正確的對操作進(jìn)行了排序也很可能會在圖形操作之間插入一個計算調(diào)度的操作而使整個任務(wù)中斷,例如在使用片段著色器對屏幕畫面進(jìn)行進(jìn)一步的后處理和UI合成之前,我們可能會在幀的中間插入計算操作來計算一些優(yōu)化的Blur值。
鳥瞰圖繪制過程的簡單版本如下所示: 繪制->Barrier(源:圖形/片段,目標(biāo):計算)->計算調(diào)度->Barrier(源:計算,目標(biāo):圖形/頂點)->繪制->展示 這些情況可能會很成問題,原因很快就會顯現(xiàn)出來。 在這種情況下單個幀的任務(wù)操作如下所示:

圖形->橙色標(biāo)識的計算barrier,計算->綠色標(biāo)識的圖形barrier
在前面的示例中你應(yīng)該希望此時A1應(yīng)該在A0和C0之間并與B0重疊 不幸的是如果“正確的”與上述Barrier進(jìn)行基本同步,那將不是你所能獲取的,你得到的信息如下:
計算負(fù)載:B1 B2 B3 B4 B5
圖形負(fù)載:A1 C1 A2 C2 A3 C3 A4 C4 A5 C5...

不幸但很常見的是,幀計算任務(wù)的中間部分完全不重疊... Barrier圖形->計算(橙色標(biāo)識)可防止CN與BN+1重疊,
Barrier計算->圖形(綠色標(biāo)識)可防止AN+1與BN重疊
因此我們看到一幀最開始的片段任務(wù)實際上在整個前一幀之后被完全替換。但這是為什么呢?看看上面的工作負(fù)載以及Barrier,答案變得相當(dāng)明顯: A和B之間的(橙色標(biāo)識部分)Barrier可以用英文解讀為:“無計算任務(wù),在安排好AN 之后進(jìn)行調(diào)度,然后在AN 完成執(zhí)行之前開始執(zhí)行”,嗯...這看起來很合理。 B和C之間的(綠色部分)Barrier顯示為:“無圖形任務(wù),在安排好BN之后進(jìn)行調(diào)度,在BN完成執(zhí)行之前允許開始執(zhí)行”,這個Barrier也很有意義,因為我們需要CN在BN完成后才能啟動。 但是我們還希望盡快調(diào)度AN+1(也就是圖形任務(wù)),最好在CN啟動后立即開始。但是BN/CN之間的Barrier不允許這樣做導(dǎo)致一些級聯(lián):AN+1在BN之后被置換但是由于CN已經(jīng)被調(diào)度,它甚至進(jìn)一步置換了AN+1(不同的像素任務(wù)不能彼此重疊)從而導(dǎo)致所有任務(wù)的完整序列化。 簡而言之計算/圖形Barrier不允許下一幀的早期圖形任務(wù)與計算任務(wù)同時執(zhí)行(綠色箭頭) 這是壞消息,在這種情況下USC(統(tǒng)一陰影集群,所有數(shù)學(xué)和計算都在其中發(fā)生,是PowerVR GPU的核心)極有可能未被充分利用,并且在這些任務(wù)之間的通信至少必須有一定的開銷??捎媱澋娜蝿?wù)負(fù)載越少,好的利用機(jī)會就越少。此外計算和圖形任務(wù)的組成通常不同,其中一項是受內(nèi)存和紋理限制,另一項是ALU/數(shù)學(xué)限制,并且非常適合同時調(diào)度。此外如果所有任務(wù)都是串行的,則通常也可能在它們之間引入微小的間隔(管道間隙),最后v-sync將進(jìn)一步加劇該問題,所有這些因素加起來會導(dǎo)致巨大的性能差異,我們已經(jīng)看到了這一方面的很多差異,雖然你遇到的可能會有所不同,但20%左右的概率并不常見。通過更好的重疊設(shè)計潛在的提升可達(dá)5%,而在實際應(yīng)用中我們的性能提升高達(dá)30%。 綜上所述:我們希望能夠?qū)⑾乱粠ˋN+1)開始的圖形操作放在第N幀(CN)的后面進(jìn)行調(diào)度以便它們與當(dāng)前幀(BN)的計算能夠并行執(zhí)行以實現(xiàn)更好的GPU利用率。 這是你在Vulkan中處理同步問題時可能遇到的想法,潛在的解決方案我們將在后續(xù)的文章中進(jìn)行檢驗。
-
gpu
+關(guān)注
關(guān)注
28文章
5050瀏覽量
134016 -
應(yīng)用程序
+關(guān)注
關(guān)注
38文章
3340瀏覽量
59785 -
Vulkan
+關(guān)注
關(guān)注
0文章
30瀏覽量
6068
原文標(biāo)題:Vulkan同步機(jī)制和圖形-計算-圖形轉(zhuǎn)換的風(fēng)險(一)
文章出處:【微信號:Imgtec,微信公眾號:Imagination Tech】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
基于Vulkan的端側(cè)AI運(yùn)算
EV12AS200差分輸出與同步機(jī)制詳解
Imagination GPU 全面支持 Vulkan 1.4 和 Android 16
改善光刻圖形線寬變化的方法及白光干涉儀在光刻圖形的測量
改善光刻圖形垂直度的方法及白光干涉儀在光刻圖形的測量
干貨分享 | 零基礎(chǔ)上手!TSMaster圖形信號表達(dá)式實操指南

Vulkan同步機(jī)制和圖形-計算-圖形轉(zhuǎn)換的風(fēng)險
評論