【技術(shù)美術(shù)百人計(jì)劃】移動(dòng)端GPU的 TB(D)R 架構(gòu)基礎(chǔ)
一、移動(dòng)端GPU概況
前言:雖然移動(dòng)端gpu型號(hào)很多,但市場(chǎng)上的廠家主要就三家:adrno、Mali、PowerVR
移動(dòng)端和桌面端功耗對(duì)比
主流性能平臺(tái),功耗一般300w,游戲主機(jī),一般為150-200w
旗艦游戲本100w,主流筆記本50w-60w
旗艦手機(jī)5-8w,主流手機(jī)3-5w
移動(dòng)端和桌面端帶寬對(duì)比

????桌面端是將近100起步,最多可到400左右
????移動(dòng)端相比之下就少的可憐(驍龍888的移動(dòng)帶寬是32
二、名詞解釋
SOC(System On Chip)
SOC是把CPU、GPU、內(nèi)存、通信基帶、GPS等模塊整合在一起的芯片的稱呼。
Sistem Memory
SOC中GPU和CPU共用一塊片內(nèi)LPDDR物理內(nèi)存,就是我們常說(shuō)的手機(jī)內(nèi)存,也叫SystemMemory,大概幾個(gè)G。
此外CPU和GPU還分別有自己的高速SRAM的Cache緩存,也叫OnchipMemory,一般幾百k到幾M。
不同距離內(nèi)存訪問(wèn)存在不同的時(shí)間消耗,距離越近消耗越低。
OnChipMemory
在TB(D)R架構(gòu)下會(huì)存儲(chǔ)Tile顏色、深度和模板緩沖,讀寫(xiě)速度都非???/p>
Stall
當(dāng)一個(gè)GPU核心的兩次計(jì)算結(jié)果之間有依賴關(guān)系而必須串行時(shí),等待的過(guò)程便是Stall
FillRate
像素填充率=ROP運(yùn)行的時(shí)鐘頻率 x ROP的個(gè)數(shù) x 每個(gè)時(shí)鐘ROP可以處理的像素個(gè)數(shù)
什么是TB(D)R?
TB(D)R全名是Tile Based (Deferred)Rendering,是目前主流的移動(dòng)GPU渲染架構(gòu),對(duì)應(yīng)一般PC上的GPU渲染架構(gòu)則是IMR(ImmediateModeRendering)
TB(D)R簡(jiǎn)單意思
屏幕被分塊渲染。(16*16像素或32*32像素)
TBR:VS-Defer-RS-PS
TB(D)R:VS-Defer-RS-Defer-PS
三、立即渲染(IMR)

先經(jīng)由VertexShader處理,再進(jìn)過(guò)一個(gè)類似管道(先進(jìn)先出)的順序,最終提交給Fragment Shader,F(xiàn)ragment Shader最終將結(jié)果刷到FrameBuffer里

虛線框:系統(tǒng)內(nèi)存區(qū)
用戶數(shù)據(jù)經(jīng)過(guò):頂點(diǎn)處理 → 剔除,投影 → 光柵化 → Early Visibility Test → Alpha Test → Late Visibility Test → Alpha Blend 最終將結(jié)果刷到FrameBuffer里
整個(gè)過(guò)程直接和系統(tǒng)內(nèi)存進(jìn)行交互
TB(D)R宏觀上分為兩個(gè)階段:
第一階段執(zhí)行所有和幾何相關(guān)的處理,并生成PrimitiveList(圖元列表),并確定每個(gè)tile上面有哪些Primitive
第二階段逐塊執(zhí)行光柵化及其后續(xù)處理,并在完成后將FrameBuffer從TileBufffer寫(xiě)回到SystemMemory中
四、基于塊元的渲染TB(D)R
1、簡(jiǎn)述
TB(D)R(Tile-Based(Deferrde)Rendering),是目前主流移動(dòng)GPU的渲染架構(gòu),對(duì)應(yīng)一般PC上的GPU架構(gòu)則為IMR
TBDR簡(jiǎn)單的意思
屏幕被分塊(16*16 or 32*32)渲染
2、TBR和TBDR的區(qū)別
TBR:VS - Defer - RS - PS
TBDR:VS - Defer1 - RS - Defer2 - PS
//RS=光柵化 ?PS=片元shader
通過(guò)這第二個(gè)Defer,PowerVR的渲染架構(gòu)真正最大程度上實(shí)現(xiàn)了“延后(Defer)PS的執(zhí)行”,以避免執(zhí)行不必要的PS計(jì)算與相關(guān)資源調(diào)用的帶寬開(kāi)銷,以達(dá)到最少的性能消耗和最高的渲染效率。
????????注意:
????????有些文章會(huì)將TBR叫作TBDR,所以看資料的時(shí)候,要搞清楚它說(shuō)的"D"是指第一個(gè)Defer還是第二個(gè)。
????????現(xiàn)在的手機(jī)基本都是TBDR架構(gòu)了,但是受到提出TBDR的PowerVR公司的產(chǎn)權(quán)保護(hù)限制,大家都不敢說(shuō)是TBDR架構(gòu)。
3、Defer的理解
????????defer
????????字面上是:延遲
????????渲染數(shù)據(jù)角度來(lái)看,Defer就是“阻塞+批處理”(GPU累積一幀的多個(gè)數(shù)據(jù),最后一起處理)
五、TB(D)R硬件渲染順序
1、TBDR詳細(xì)的渲染流程
第一階段
執(zhí)行所有與幾何相關(guān)的處理,并生成Primitive List(圖元列表)
并且確定每個(gè)Tile(塊)上有哪些Primitve(圖元)
第二階段
執(zhí)行光柵化及后續(xù)處理
并在完成后,將FrameBuffe從Tile Buffe寫(xiě)會(huì)到System Memory中
理解:
第一階段:
進(jìn)行“分圖”元操作
第二階段:
相比傳統(tǒng)的IMR架構(gòu),不是直接寫(xiě)回System Memory中,而是寫(xiě)到片上內(nèi)存(OnChipMemory)中
2、示意圖
a.簡(jiǎn)略示意圖

pipeline:
數(shù)據(jù)通過(guò)Vertex shader的處理 → 經(jīng)過(guò)Tiler(圖元分好的塊) → 刷到一塊On-chip Memory(每個(gè)塊元的內(nèi)存)上
第一階段(Pass one)
對(duì)每個(gè)renderpass里的DrawCall,每個(gè)DrawCall里的圖元,先進(jìn)行Vertex shader處理
關(guān)鍵在于:分清楚每個(gè)塊元(Tile)上有哪些圖元(Primitve)
第二階段(Pass two)
對(duì)每個(gè)塊元執(zhí)行每個(gè)renderpass
對(duì)每個(gè)塊元上的圖元進(jìn)行Fragment Shade處理
個(gè)人總結(jié):
理解的重點(diǎn)在于搞清楚什么是塊元(Tile),什么是圖元(Primitve)
b.TBDR詳細(xì)示意圖

【上邊虛線框】On-Chip Buffer(Memory),代表片上的內(nèi)存
【下邊虛線框】System Memory ,是系統(tǒng)內(nèi)存
個(gè)人理解:
頂點(diǎn)shader統(tǒng)一渲染后,將其分為多個(gè)塊元(如16*16像素大?。糠趾靡粋€(gè)便寫(xiě)入內(nèi)存,全部分好后再傳入GPU統(tǒng)一進(jìn)行包括片元著色在內(nèi)的其他操作。操作完成后的塊元,傳入OnChipBuffer,拼合成完整的圖像,再傳入內(nèi)存。
本質(zhì)上是因?yàn)槭謾C(jī)的GPU與CPU共用內(nèi)存,且GPU的On-Chip Memory內(nèi)存過(guò)小,為了在使用共用內(nèi)存時(shí)減少通信延遲所使用的方法
與IMR的區(qū)別
TBDR架構(gòu)中,多了一步Tiling的過(guò)程,這一步是:將頂點(diǎn)處理經(jīng)過(guò)剔除、投影的幾何數(shù)據(jù)刷到系統(tǒng)內(nèi)存(System Memory)上
經(jīng)過(guò)光柵化(Raster)等流水線fragment shader、ROP等,最終把結(jié)果刷在片內(nèi)存(On Chip Memory)上
最終片內(nèi)存上的會(huì)刷到FrameBuffer上(FrameBuffer在System Memory上)
//仔細(xì)多看幾遍圖,概念對(duì)應(yīng)上,都在圖上了
c.總結(jié)TBR
????????核心目的
????????為了降低帶寬,減少功耗,但渲染幀率上并不比IMR快
????????優(yōu)點(diǎn)
????????給消除OverDraw提供了機(jī)會(huì):
????????PowerVR有HSR技術(shù),Mali有Forward Pixel Killing技術(shù),都有為了最大限度減少被遮擋的pixel的texturing和shading
????????緩存友好(Cache friendly),在cache的讀寫(xiě)速度要比全局內(nèi)存中快得多(以降低幀率為代價(jià),降低帶寬、功耗)
????????缺點(diǎn)
????????binning過(guò)程是在vertex階段之后,將輸出的數(shù)據(jù)寫(xiě)到系統(tǒng)內(nèi)存(DDR)上,然后才能被fragment shader讀取。
????????這樣一來(lái)幾何數(shù)據(jù)過(guò)多的管線,容易在此處有性能瓶頸
????????如果某些三角形疊加在數(shù)個(gè)tile(塊)上,會(huì)被繪制數(shù)次。
????????這樣就意味著:總渲染時(shí)間多于IMR
六、IMR和TB(D)R對(duì)比
TBR、IMR簡(jiǎn)化版示意圖

圖(a)TBR架構(gòu)
????幾何處理數(shù)據(jù)形成了FrameData(放在SystemMemory上)
????這些Frame Data經(jīng)過(guò)片段處理,結(jié)果放在了TileBuffer上(片的內(nèi)存上)
????最后的結(jié)果會(huì)刷到FrameBuffer中(SystemMemory上)
圖(b)IMR架構(gòu)
????對(duì)比TBR有以下兩種區(qū)別
????幾何處理數(shù)據(jù)直接到片段處理,沒(méi)有中間數(shù)據(jù)(Frame Data)
????直接刷到System Memory上了,沒(méi)有經(jīng)過(guò)片內(nèi)存(On-Chip Memory)
七、Binning過(guò)程(第一個(gè)Defer)
目的:確定哪些圖元屬于哪些塊元渲染

注釋:
第二幅圖里的紅色三角形,只用一個(gè)塊元就能渲染,所以它只會(huì)被分配到一個(gè)塊元中
第四幅圖里的棕色三角形,需要多個(gè)塊元才能渲染,所以它需要分配到9個(gè)塊元中一起渲染
一些參考:一款老的驍龍gpu調(diào)試器下的binning參數(shù)

紅線代表tile的范圍,可以顯示每個(gè)塊元的性能參數(shù)
binning過(guò)程的耗時(shí)占比參考

如果你的項(xiàng)目中binning過(guò)程相比其他耗時(shí)長(zhǎng)的話,就要考慮一下是不是幾何數(shù)據(jù)過(guò)多了
八、不同GPU的Early-Depth-Test(第二個(gè)Defer)
Android
QualcommAdreno采用外置模塊LRZ。
在正常渲染管線前,先多執(zhí)行一次VS,生成低精度的DepthTexture,以提前剔除不可見(jiàn)的triangels。
說(shuō)白了,就是用硬件做occlusion culling,功能類似軟光柵遮擋剔除。
Mail的FPK
Arm Mail采用的是Forward Pixel Kill技術(shù)
管線位置位于Early-Z之后,是一個(gè)先進(jìn)先出的隊(duì)列。
隊(duì)列中有4個(gè)Quad(可以理解為2×2像素的平面),每個(gè)Quad有屏幕上位置的數(shù)據(jù)和Z數(shù)據(jù)
Z越大代表離攝像機(jī)越遠(yuǎn)
根據(jù)屏幕上相同位置(pos)的不同z,對(duì)不透明的像素進(jìn)行替換(有近的就不渲染遠(yuǎn)的),這個(gè)過(guò)程叫作killed
PVR的HSR
HSR = Hide Surface Removal隱形面剔除
大體實(shí)現(xiàn)原理:虛擬出一個(gè)射線,當(dāng)它遇到第一個(gè)不透明的物體時(shí)就會(huì)停下來(lái),這樣就會(huì)打斷后面三角形的后續(xù)ps處理
九、優(yōu)化建議
在不使用FrameBuffer的時(shí)候clear或discard
主要是清空在TileBuffer上的中間數(shù)據(jù),所以在unity中對(duì)RenderTexture的使用也特別描述了在不使用此RT前,調(diào)用一次Discard。在OpenGL ES上善用glClear,gllnvalidateFrameBuffer避免不必要的Resolve行為。(Resolve就是TileBuffer(片內(nèi)存)刷新到SystemMemory(系統(tǒng)內(nèi)存))
不要在一幀內(nèi)頻繁切換FrameBuffer的綁定
本質(zhì)上是減少TileBuffer和SystemMemory之間的stall操作
對(duì)于移動(dòng)平臺(tái)上,建議使用AlphaBlend,而不是AlphaTest。
在實(shí)際使用中,你應(yīng)該分析比較Alpha測(cè)試和Alpha混合的表現(xiàn),這取決于具體內(nèi)容。因此你需要測(cè)量,通常在移動(dòng)平臺(tái)上應(yīng)避免使用AlphaBlend來(lái)實(shí)現(xiàn)透明。需要進(jìn)行Alpha混合時(shí),嘗試縮小混合區(qū)域的覆蓋范圍。
當(dāng)手機(jī)上必須要AlphaTest時(shí),先做一遍DepthPrepass
參考Alpha Test 的雙pass優(yōu)化思路
圖片盡量壓縮,如ASTC,ETC2
圖片盡量走M(jìn)ipmap
盡量使用從VertexShader傳來(lái)的Varying變量uv值采樣貼圖(連續(xù)的)
盡量不要在FragmentShader里動(dòng)態(tài)計(jì)算貼圖的uv值(非連續(xù)的),否則CacheMiss
在延遲渲染中盡量使用TileBuffer
參考傳統(tǒng)延遲渲染和TBDR
如果你在Unity里調(diào)整ProjectSetting/Quality/Rendering/TextureQuality不同的設(shè)置,或者不同的分辨率下,幀率變化較大,那么十有八九是帶寬出現(xiàn)問(wèn)題。
MSAA在TBDR下反而是非常快速的
MSAA是硬件上的,是發(fā)生在片上的。相比FSAA,MSAA在手機(jī)上無(wú)疑是更快的
少在FragmentShader使用discard函數(shù),調(diào)用gl_FragDepth從而打斷Early-DT(HLSL中為clip,GLSL中為discard)
在shader里使用浮點(diǎn)精度,有目的的區(qū)分float和half。
帶寬會(huì)減少
GPU使用周期減少,因?yàn)橹骶幾g器可以優(yōu)化你的代碼以提高并行化程度
要求的統(tǒng)一變量寄存器數(shù)量減少,這反過(guò)來(lái)又降低了寄存器數(shù)量溢出的風(fēng)險(xiǎn)。具體有哪些數(shù)據(jù)類型適合用half或float或fixed,參考【熊大的優(yōu)化建議】和【shader數(shù)學(xué)計(jì)算優(yōu)化技巧】
在移動(dòng)端TB(D)R架構(gòu)上,頂點(diǎn)處理部分,容易成為瓶頸,
避免使用曲面細(xì)分shader置換貼圖等負(fù)操作,提倡使用模型LOD,本質(zhì)上減少FrameData的壓力,unity中盡早在應(yīng)用階段借助umbra遮擋剔除,參考【occlusion-culling-tutorial】【天涯明月刀手游優(yōu)化】
十、參考鏈接
[GPU性能指標(biāo)]
????https://www.gpuinsight.com/gpu_performance/
[三星的GPU-FrameBuff指導(dǎo)]
????https://developer.samsung.com/galaxy-gamedev/resources/articles/gpu-framebuffer.html
[英偉達(dá)的TBR教學(xué)文章]
????https://www.techpowerup.com/231129/on-nvidias-tile-based-rendering
[ARM的TBR教學(xué)文章]
????https://developer.arm.com/solutions/graphics-and-gaming/developer-guides/learn-the-basics/tile-based-rendering/single-page
[蘋(píng)果OpenGL程序開(kāi)發(fā)指南]
????https://developer.apple.com/library/archive/documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/Performance/Performance.html
[OpenGL Insights]
????https://www.seas.upenn.edu/~pcozzi/OpenGLInsights/OpenGLInsights-TileBasedArchitectures.pdf
[知乎文章:Tile-based和Full-screen方式的Rasterization相比有什么優(yōu)劣]
????https://www.zhihu.com/question/49141824
[移動(dòng)設(shè)備GPU架構(gòu)知識(shí)匯總]
????https://zhuanlan.zhihu.com/p/112120206
[再議移動(dòng)平臺(tái)的AlphaTest效率問(wèn)題]
????https://zhuanlan.zhihu.com/p/33127345
[移動(dòng)平臺(tái)GPU硬件學(xué)習(xí)與理解]
????https://zhuanlan.zhihu.com/p/347001411
[PowerVR開(kāi)發(fā)者指南]
????http://cdn.imgtec.com/sdk-documentation/Introduction_to_PowerVR_for_Developers.pdf
[Performance Tunning for Tile-Based Architecture Tile-Based架構(gòu)下的性能調(diào)校]
????https://www.cnblogs.com/gameknife/p/3515714.html
[TBDR的HSR流程細(xì)節(jié)和使用AlphaBlend的效率提升程度]
????https://www.zhihu.com/question/49141824
[當(dāng)我們談優(yōu)化時(shí),我們談些什么]
????https://zhuanlan.zhihu.com/p/68158277
????https://edu.uwa4d.com/course-intro/1/179
[Alpha Test的雙pass 優(yōu)化思路]
????https://zhuanlan.zhihu.com/p/58017068
[個(gè)人收藏]
????https://github.com/killop/anything_about_game#gpu-architecture
[Adreno Hardware Tutorial 3: Tile Based Rendering]
????https://www.youtube.com/watch?v=SeySx0TkluE&pbjreload=101
[Mali GPU的獨(dú)有特性]
????https://www.cnblogs.com/hamwj1991/p/12404551.html
[Mali-T880]
????http://grmanet.sogang.ac.kr/ihm/cs170/20/HC27.25.531-Mali-T880-Bratt-ARM-2015_08_23.pdf
[熊大的優(yōu)化建議]
????http://www.xionggf.com/post/unity3d/shader/u3d_shader_optimization/
[GPU畫(huà)像素的順序是什么]
????https://zhuanlan.zhihu.com/p/22232448
[Tile-based Rasterization in Nvidia GPUs with David Kanter of Real World Tech]
????https://www.youtube.com/watch?v=Nc6R1hwXhL8&t=973s&pbjreload=101