目錄
- 移動(dòng)GPU渲染架構(gòu)概述
- 真假TBDR
- PowerVR的HSR技術(shù)
- Adreno的Flex Render技術(shù)
- 基于移動(dòng)GPU的通用渲染優(yōu)化建議
- AlphaTest究竟有多耗
一、移動(dòng)GPU渲染架構(gòu)概述——TBR/TBDR與IMR
TBR(Tile-Based (Deferred) Rendering)是目前主流的移動(dòng)GPU渲染架構(gòu),對應(yīng)一般PC上的GPU渲染架構(gòu)則是IMR(Immediate Mode Renderers)。為什么移動(dòng)設(shè)備的GPU要用這樣的渲染架構(gòu),以及TBR架構(gòu)的特點(diǎn)是什么,看下面這三篇文章就行了。其中第一篇應(yīng)該是我看到過的最新最完備的中文文章了,其中用到的比喻我覺得真的是很形象也很準(zhǔn)確,我也沒必要再自己寫一遍了,直接上鏈接。
針對移動(dòng)端TBDR架構(gòu)GPU特性的渲染優(yōu)化-騰訊游戲?qū)W院?
A look at the PowerVR graphics architecture: Tile-based rendering - Imagination?www.imgtec.com
A look at the PowerVR graphics architecture: Deferred rendering - Imagination?www.imgtec.com
簡要概要的總結(jié)一下TBR的渲染框架:

- 緩存所有繪制指令直到最后才開始進(jìn)行真正繪制
- 首先對所有圖元執(zhí)行VS,把相關(guān)的所有繪制數(shù)據(jù)保存起來
- 計(jì)算每個(gè)tile都包含哪些圖元
- 開始繪制一個(gè)tile
- 依次繪制tile中的每個(gè)圖元
- 把繪制好的tile拷貝到framebuffer對應(yīng)的位置上
二、真假TBDR
早年間有這樣一個(gè)說法:
PowerVR的GPU是TBDR架構(gòu),別的移動(dòng)GPU是TBR架構(gòu)。
這個(gè)說法是對的。從官方的表述上來看,只有PowerVR稱自己的GPU架構(gòu)是TBDR,而Adreno和Mali稱自己的GPU架構(gòu)是TBR。這是沒有任何的疑問與含糊的地方的。
但是也還有很多技術(shù)文章通常會(huì)將移動(dòng)GPU渲染架構(gòu)都統(tǒng)稱為TBDR。這種說法從某種程度上來說也沒有錯(cuò)。因?yàn)闊o論是PowerVR的GPU還是Adreno或者M(jìn)ali的GPU,無論是所謂的TBR還是TBDR,相比于IMR來說都是延遲渲染架構(gòu)。都是將Rasterize/PS的處理延后到了處理完所有VS之后,而不是像IMR一樣VS后馬上Rasterize/PS(還有一些中間步驟就省略了,不要缸)。所以說TBR架構(gòu)也是個(gè)延遲渲染架構(gòu)。
那么為什么只有PowerVR的GPU稱其渲染架構(gòu)為TBDR呢?其他的移動(dòng)GPU也是Tile-Based也有Defer,怎么就只能叫做TBR呢?原因在于PowerVR的渲染架構(gòu)中還多了一步Rasterize到PS的延遲,PowerVR為處理這一步延遲的組件起名叫HSR(Hidden Surface Removal)并申請了專利。HSR在下面一部分會(huì)進(jìn)行詳細(xì)的說明,這里簡單直接的描述一下PowerVR的TBDR架構(gòu)與其他移動(dòng)GPU的TBR架構(gòu)的區(qū)別:
- TBR:VS - Defer - RS - PS
- TBDR:VS - Defer - RS - Defer - PS
第一個(gè)Defer大家都有,而且通過第一篇鏈接的文章我們可以明白,第一個(gè)Defer是Tile-Based渲染架構(gòu)所必須的,沒有這個(gè)Defer,Tile-Based優(yōu)勢就無從發(fā)揮。而第二個(gè)Defer則是Power VR的TBDR架構(gòu)所特有。通過這第二個(gè)Defer,PowerVR的渲染架構(gòu)真正最大程度上實(shí)現(xiàn)了“延后(Defer)PS的執(zhí)行”,以避免執(zhí)行不必要的PS計(jì)算與相關(guān)資源調(diào)用的帶寬開銷,以達(dá)到最少的性能消耗和最高的渲染效率。
TBDR是由PowerVR所提出的說法,意在于表示自己的架構(gòu)是基于TBR架構(gòu)的改進(jìn),并實(shí)現(xiàn)了最大程度的DR。因此要嚴(yán)格論起來,其他移動(dòng)GPU是沒有資格稱其架構(gòu)為TBDR的,他們只是TBR。分享一個(gè)文章鏈接,其中PowerVR控訴其他芯片廠商偷換TBDR的定義以混淆這二者,以此掩蓋TBR與TBDR僅從設(shè)計(jì)上的就產(chǎn)生的巨大性能差異。
總結(jié)一下,當(dāng)你在各種技術(shù)文章中看到TBDR的表述時(shí),一定要弄清楚這其中的D代表什么意思。如果文章是在討論任意一種移動(dòng)GPU與PC GPU的對比,那么這時(shí)候的D所強(qiáng)調(diào)的是VS與RS之間的延遲,不太嚴(yán)謹(jǐn)?shù)脑捠强梢源硭械囊苿?dòng)GPU框架。而如果文章是在對比PowerVR的GPU與其他移動(dòng)GPU的渲染架構(gòu)的話,此時(shí)的D所強(qiáng)調(diào)的是RS與PS步驟間的延遲,此時(shí)TBDR只代表PowerVR GPU的渲染架構(gòu)。
三、PowerVR的HSR技術(shù) —— 硬件實(shí)現(xiàn)的Overdraw優(yōu)化
HSR(Hidden Surface Removal)技術(shù)的概念和原理其實(shí)真的非常簡單,沒有多深?yuàn)W。
介紹HSR之前先簡述一下EarlyZ。EarlyZ優(yōu)化已經(jīng)是現(xiàn)代GPU的標(biāo)準(zhǔn)流程了,簡單來說就是當(dāng)不透明的圖元從Rasterize階段開始逐像素進(jìn)行處理時(shí),首先進(jìn)行Depth Read & Test,通過后直接Write,后續(xù)再執(zhí)行該像素上的PS程序,否則就可以停下來休息等待下一個(gè)要處理的像素了。后續(xù)又進(jìn)一步對于那些在PS階段會(huì)改變深度寫入的圖元(有discard/clip指令或有ZOffset)加入了 Depth Read & Test -> PS -> Depth Read & Test & Write 流程??傊唵我痪湓捑褪牵L制前先做深度檢測,減少不必要的繪制。
這也是為什么我們在渲染不透明物體時(shí)要按從近到遠(yuǎn)的順序去繪制,因?yàn)榻幍奈矬w先繪制好之后,其寫入的深度會(huì)阻擋住后面物體的ZTest,也就避免了后面物體無意義的渲染開銷。
基于EarlyZ是無法完全的避免Overdraw的。這是因?yàn)槲覀冊谡嬲龑σ粋€(gè)復(fù)雜場景去渲染的時(shí)候是不可能進(jìn)行嚴(yán)格的由近到遠(yuǎn)的繪制的。一個(gè)面積很大的地塊與遠(yuǎn)處的物體相比誰應(yīng)該算“近”呢? 一個(gè)有凹面的物體,其上每個(gè)圖元的的渲染順序也會(huì)因視角不同而會(huì)出現(xiàn)先繪制遠(yuǎn)處三角面再繪制近處的情況。想把物體拆碎?那意味著drawcall增加。完全嚴(yán)格的前后物體排序?那很可能意味著Shader切換次數(shù)的增加。
基于硬件EarlyZ特性對渲染物體進(jìn)行排序優(yōu)化對于移動(dòng)GPU也是同樣適用的 —— 除了PowerVR,因?yàn)槿思艺嬲腡BDR渲染框架能做得更好。

這里HSR登場了,不需要在軟件層面對物體進(jìn)行排序,HSR在硬件上實(shí)現(xiàn)了零Overdraw的優(yōu)化。原理也超簡單,當(dāng)一個(gè)像素通過了EarlyZ準(zhǔn)備執(zhí)行PS進(jìn)行繪制前,先不畫,只記錄標(biāo)記這個(gè)像素歸哪個(gè)圖元來畫。等到這個(gè)Tile上所有的圖元都處理完了,最后再真正的開始繪制每個(gè)圖元中被標(biāo)記上能繪制的像素點(diǎn)。這樣每個(gè)像素上實(shí)際只執(zhí)行了最后通過EarlyZ的那個(gè)PS,而且由于TBR的機(jī)制,Tile塊中所有圖元的相關(guān)信息都在片上,可以極小代價(jià)去獲得。最終零Overdraw,毫無浪費(fèi),起飛。

最后說一下HSR是怎么處理AlphaTest和AlphaBlend的。HSR在設(shè)計(jì)原理上高到飛起,但前提是假定了前面的物體會(huì)擋住后面的物體,因此對于AlphaTest和AlphaBlend物體都是沒有作用的(但他倆仍然可以被EarlyZ攔?。?。不僅沒作用,反而會(huì)被其中斷Defer流程,導(dǎo)致渲染性能降低。(這里要加黑強(qiáng)調(diào)一下,所謂導(dǎo)致渲染性能降低只是與不透明物體相比較降低了,而不是說PowerVR在處理AlphaTest/Blend時(shí)比別的GPU慢。打個(gè)比方:原來大家都走路,PowerVR騎自行車,現(xiàn)在遇到AlphaTest,PowerVR會(huì)改成下來推車走)
如果在HSR處理不透明物體的過程中突然來了一個(gè)AlphaTest的圖元,那么為了保證渲染結(jié)果正確,HSR就必須要終止當(dāng)前的Defer,先把已標(biāo)記好的像素都繪制出來,再進(jìn)行后面的繪制。這顯然嚴(yán)重影響了渲染的效率,也是為什么官方文檔特意提到盡量避免AlphaTest的原因。相對應(yīng)的AlphaBlend同樣也要中斷HSR的Defer,強(qiáng)制開始繪制,但是比AlphaTest好那么一點(diǎn)點(diǎn)的是他不影響后續(xù)圖元并行地繼續(xù)開始進(jìn)行HSR處理,有興趣可以參考下面的官方技術(shù)文檔鏈接,里面詳細(xì)說明了HSR是怎么應(yīng)對AlphaBlend和AlphaTest繪制的。
Image Synthesis Processor (ISP)?docs.imgtec.com
最后總結(jié)下,在PowerVR上渲染,因?yàn)橛蠬SR的存在我們只需要把所有不透明物體放到一起扔給GPU畫就行了;在其他移動(dòng)GPU上,同樣也是要把所有不透明物體放到一起,但是還要先做個(gè)排序再交給GPU。而對于爹娘不愛的AlphaTest我們到底怎么畫才最好,文章的最后一部分會(huì)有說明。
四、Adreno的Flex Render技術(shù) —— Flex Render真的比TBDR高到不知道哪里去了么?
這一段其實(shí)可以跳過,與優(yōu)化的關(guān)系不大,可以當(dāng)個(gè)小知識看。起因是看到一位大神的上古回答導(dǎo)致我誤入歧途(也就是此段的副標(biāo)題),如果有同樣誤入歧途的小伙伴請趕快迷途知返。
PowerVR有自己專有的秘密武器HSR,并且申請了專利不讓別人用。但是不甘示弱的Adreno也搞了個(gè)叫做Flex Render的專屬武器。
這個(gè)Flex Render的功能就是智能的在某些時(shí)候?qū)秩玖鞒逃蒚BR切換為IMR,也就是直接渲染到FrameBuffer。很明顯根據(jù)TBR/TBDR的設(shè)計(jì)特點(diǎn),當(dāng)渲染目標(biāo)足夠小的時(shí)候IMR相比TBR/TBDR就有了更高的執(zhí)行效率,畢竟省去了binning(把圖元分配到關(guān)聯(lián)的Tile上)和拷貝操作。這個(gè)Flex Render的作用,就是根據(jù)渲染目標(biāo)的大小讓GPU的渲染模式在TBDR和IMR中自動(dòng)切換。
可以進(jìn)行推測的是,比如在Bloom后處理的Downsample階段,或者是生成Tonemapping LUT的階段,Adreno GPU很可能都會(huì)通過Flex Render將這些渲染過程改為IMR流程去執(zhí)行。
但是其實(shí)在討論渲染優(yōu)化的一般情況下,我們都是針對TBR/TBDR來進(jìn)行分析。Flex Render與在應(yīng)用層利用硬件特性去優(yōu)化渲染沒有什么太大關(guān)系,也沒有必要為此做深入考慮。
關(guān)于Flex Render詳情確認(rèn)可以參考官方文檔第14頁到15頁
Adreno Vulkan Developer Guide?developer.qualcomm.com
五、移動(dòng)設(shè)備渲染通用優(yōu)化建議
了解了移動(dòng)GPU的設(shè)計(jì)架構(gòu),就能明白:移動(dòng)GPU相對于桌面GPU來說最大的區(qū)別就是帶寬的開銷成本很高。因此任何有高帶寬開銷成本的操作都具有高性價(jià)比優(yōu)化的潛力。
降低Shader的復(fù)雜度固然是通用的降低GPU開銷的方式,但如果還考慮到耗電或發(fā)熱問題的話,帶寬開銷應(yīng)該是最為重點(diǎn)的關(guān)注。
針對于帶寬的優(yōu)化具體來說可以有以下幾點(diǎn):
- 貼圖格式能壓縮就壓縮。貼圖內(nèi)存越小,片上命中率就越高,總的傳輸量也少
- 能開mipmap就開mipmap(前提是能用到,UI貼圖就不用開了)。與減小實(shí)際使用的貼圖內(nèi)存是一個(gè)道理,但是會(huì)增加總貼圖的內(nèi)存占用大小,需要在內(nèi)存開銷和帶寬開銷上做一個(gè)平衡。
- 隨機(jī)紋理尋址相對于相鄰紋理尋址有顯著開銷。提高片上命中率。
- 3DTexture Sampling有顯著的開銷。3DTexture整體內(nèi)存占用大,垂直方向相鄰像素內(nèi)存不相鄰很容易cache miss,這是我個(gè)人推測。
- Trilinear/Anisotropic相對于Bilinear有顯著的開銷。Trilinear其實(shí)就相當(dāng)于tex3D了(此結(jié)論不負(fù)責(zé)任),Bilinear相對于Point幾乎沒有額外開銷(此結(jié)論負(fù)責(zé)任,texture fetch都是一次拿相鄰的四個(gè)出來),所以Bilinear能忍就盡量湊合用著吧。
- 使用LUT(look up texture)很可能是負(fù)優(yōu)化。需要對比權(quán)衡帶寬占用+texture fetch操作增加與ALU占用增加降低并行效率,另外還很可能涉及到美術(shù)工作流和最終效果,所以是個(gè)不是很好進(jìn)行操作的優(yōu)化。之前看過騰訊的技術(shù)分享將引擎中Tonemapping那步的3DLUT(UE4和Unity都是這樣的)替換為函數(shù)擬合的優(yōu)化,理論上應(yīng)該是會(huì)提升不少性能,但是要想真正應(yīng)用到生產(chǎn)環(huán)境,保證效果,還要做好擬合工具鏈,是得費(fèi)不少力氣的
- 通道圖能合并就合并,減少Shader中貼圖采樣次數(shù)。這個(gè)不多說了
- 控制Framebuffer大小。這個(gè)也不多說了
- 總頂點(diǎn)數(shù)量也是帶寬開銷的影響因素。雖然以現(xiàn)在GPU的計(jì)算能力來說,頂點(diǎn)數(shù)增多產(chǎn)生的VS計(jì)算開銷增加通常是忽略不計(jì)的。但是仍不能忽略總頂點(diǎn)數(shù)量對于VertexBuffer所消耗帶寬的影響,對于總頂點(diǎn)數(shù)的限制應(yīng)該更多的從帶寬消耗上去進(jìn)行測試和分析。
另外還有一些優(yōu)化點(diǎn),一般來說引擎都給弄好了,不是特別作應(yīng)該都碰不到,也簡單列一下:
- 任何必要情況下(比如新一幀繪制前)都應(yīng)該顯式地對FrameBuffer進(jìn)行Clear操作。
- 不要在一幀的繪制中多次更新VBO。
以上優(yōu)化建議都是適用于PowerVR、Mali、Adreno任何一款GPU的。在他們各自的文檔中都有提到,我只是做一個(gè)匯總。
PowerVR開發(fā)者指南 | Adreno開發(fā)者指南 | Mali優(yōu)化指南
六、AlphaTest究竟有多耗
寫不動(dòng)了,先放結(jié)論吧,適用于任何移動(dòng)GPU(對,沒有寫錯(cuò),對于AlphaTest的優(yōu)化與PowerVR/TBDR/HSR無關(guān))。另外也說明一下,有些結(jié)論都是我的推論,錯(cuò)了不負(fù)責(zé),歡迎指正與討論。推導(dǎo)是基于TBR/TBDR的每個(gè)流程節(jié)點(diǎn)GPU都是去并行處理圖元或像素的,如果只是基于線性的流程去進(jìn)行分析是推不出任何有意義的結(jié)果的:
只要Shader中包含discard指令的都會(huì)被GPU認(rèn)為是AlphaTest圖元(GPU對于AlphaTest繪制流程的判定是基于圖元而不是像素)
無論是PowerVR還是Mali/Adreno芯片,AlphaTest圖元的繪制都會(huì)影響整體渲染性能。
隨著芯片的發(fā)展AlphaTest圖元對于渲染性能的影響主要在于Overdraw增加而非降低硬件設(shè)計(jì)流程效率,其優(yōu)化思路與AlphaBlend一樣,就是少畫!
嚴(yán)格按照Opaque - AlphaTest - AlphaBlend的順序進(jìn)行渲染可以最大化減小AlphaTest對于渲染性能的影響。
將Opaque, AlphaTest與AlphaBlend打亂順序渲染會(huì)極大的降低渲染性能,任何情況下都不應(yīng)該這么做。
不要嘗試使用AlphaTest替代AlphaBlend,這并不會(huì)產(chǎn)生太多優(yōu)化。
不要嘗試使用AlphaTest替代Opaque,這會(huì)產(chǎn)生負(fù)優(yōu)化
不要嘗試使用AlphaBlend替代AlphaTest,這會(huì)造成錯(cuò)誤的渲染結(jié)果。
在保證正確渲染順序情況下,AlphaTest與AlphaBlend開銷相似,不存在任何替代優(yōu)化關(guān)系
增加少量頂點(diǎn)以減少AlphaTest圖元的繪制面積是可以提升一些渲染性能的。
首先統(tǒng)一繪制AlphaTest圖元的DepthPrepass,再以ZTest Equal和不含discard指令的Shader統(tǒng)一繪制AlphaTest圖元,大多數(shù)情況下是可以顯著提升總體渲染性能的(需要實(shí)際測試)