GPU架构杂乱备忘——IMR、TBR、TBDR
原文:https://juejin.cn/post/6844904132864655367
GPU架構(gòu)雜亂備忘——IMR、TBR、TBDR
之前覺(jué)得涉及到gpu架構(gòu)相關(guān)的問(wèn)題只需要知道個(gè)大概就好,畢竟在圖形api的層面上應(yīng)該把硬件的細(xì)節(jié)給隱蔽掉,gpu的架構(gòu)千千萬(wàn)萬(wàn),每家廠商每個(gè)型號(hào)都不一樣,開(kāi)發(fā)者沒(méi)必要掉進(jìn)這個(gè)細(xì)節(jié)里面。但是最近重看Metal,特別是2.0之后新增的功能,逐漸深刻意識(shí)到一個(gè)事實(shí)——圖形api已經(jīng)迎來(lái)了真正的第三代。當(dāng)然DX12、Vulkan和Metal在誕生時(shí)就打出了“現(xiàn)代圖形api”的旗號(hào),與傳統(tǒng)api劃出界限,我也只算是后知后覺(jué)。這些現(xiàn)代圖形api的一個(gè)特點(diǎn)就是開(kāi)放更多操縱硬件的細(xì)節(jié),全權(quán)交給開(kāi)發(fā)者來(lái)定奪。不過(guò)真正讓我覺(jué)得有必要深入了解一下gpu架構(gòu)的原因卻是Metal在面對(duì)桌面級(jí)gpu和移動(dòng)級(jí)gpu給出了差異相當(dāng)大的兩套api,這也讓桌面端和移動(dòng)端的圖形編程變得截然不同。
桌面級(jí)gpu架構(gòu)——IMR(Immediate Mode Rendering)
IMR就是我們普遍熟悉和使用的gpu架構(gòu),以n卡為例從Tesla發(fā)展到Turing依舊還是IMR架構(gòu)。這種架構(gòu)也和之前的圖形api與渲染管線天然契合。每一個(gè)繪圖的指令來(lái)到顯卡,顯卡便立即執(zhí)行,從頭到尾跑完整個(gè)管線,最終將結(jié)果輸入到Frame Buffer中。但是這種架構(gòu)有一個(gè)問(wèn)題,在開(kāi)啟深度測(cè)試后,每個(gè)fragment的輸出都要和Depth Buffer中的深度值進(jìn)行深度測(cè)試,如果通過(guò)測(cè)試則需要更新Depth Buffer和Frame Buffer。這個(gè)過(guò)程包括了對(duì)System Memory的一次讀取和兩次寫(xiě)入,而fragment的數(shù)量巨大,這樣就帶來(lái)了很大的訪問(wèn)System Memory的壓力。而IMR的解決辦法則是給gpu配備足夠大緩存和足夠大的帶寬。不過(guò)代價(jià)卻是顯卡為了容納下更多緩存使得主板越來(lái)越大,并且頻繁大量的帶寬訪問(wèn)造成巨大的耗電與發(fā)熱而不得不增加單獨(dú)的風(fēng)扇。這些代價(jià)在桌面電腦上尚能接受,可到了移動(dòng)端就變成了洪水猛獸。無(wú)論是物理空間還是耗電對(duì)于移動(dòng)設(shè)備來(lái)說(shuō)都彌足珍貴,也因此不得不推出一種全新的gpu架構(gòu)
移動(dòng)級(jí)gpu架構(gòu)——TBR(Tile Based Rendering)
TBR架構(gòu)在gpu很近的位置增加了一片高速緩存,通常被稱(chēng)為T(mén)ile Memory(圖中也叫On-Chip Buffer)。受限于成本、耗電等原因這塊緩存不會(huì)很大,大概幾十k這個(gè)量級(jí)。首先整個(gè)屏幕的畫(huà)面會(huì)被分割成無(wú)數(shù)個(gè)小塊,被稱(chēng)為tile,通常32*32大小,這樣Tile Memory中足夠容納得下這個(gè)tile的相關(guān)數(shù)據(jù)。當(dāng)一個(gè)繪圖指令抵達(dá)顯卡時(shí),不在像IMR一樣立即完成渲染,而是將通過(guò)vertex shader和裁剪后的頂點(diǎn)數(shù)據(jù),根據(jù)所在tile進(jìn)行分組,并將分組后數(shù)據(jù)存儲(chǔ)到System Memory中,這塊緩存也被稱(chēng)為Parameter Buffer (PB, 圖中Primitive List和Vertex Data),然后處理下一個(gè)繪制指令。當(dāng)所有繪制指令的頂點(diǎn)數(shù)據(jù)都做好處理存進(jìn)PB或是PB達(dá)到一定容量之后才開(kāi)始進(jìn)行管線的下一步,即顯卡會(huì)以tile為單位從PB中取回相應(yīng)的頂點(diǎn)數(shù)據(jù),進(jìn)行光柵化、fragment shader以及逐片元處理。原本在逐片元處理中需要頻繁的訪問(wèn)System Memory變?yōu)榇鷥r(jià)極低的對(duì)Tile Memory的訪問(wèn)。直到這個(gè)tile的frament將數(shù)據(jù)全部更新到Tile Memory上之后,再將該Tile Memory中的數(shù)據(jù)寫(xiě)回System Memory,然后執(zhí)行下一個(gè)tile的處理。相比于imr零碎的大量的不可估計(jì)的對(duì)于System Memory的讀寫(xiě)操作,TBR中變?yōu)榱擞邢薜?#xff08;和tile數(shù)量一致)整塊的寫(xiě)操作。雖然PB也在System Memory上,但是對(duì)于PB的訪問(wèn)是頂點(diǎn)數(shù)量級(jí)的(顯然vertex要遠(yuǎn)小于fragment)且數(shù)據(jù)會(huì)經(jīng)過(guò)特殊的壓縮處理,所以這個(gè)置換依舊值當(dāng)。
不過(guò)這種架構(gòu)也帶來(lái)了一些問(wèn)題,因?yàn)殇秩竟芫€會(huì)在中途中斷,這就導(dǎo)致在這時(shí)切換Frame Buffer變得異常麻煩。TBR的做法是會(huì)將緩存的渲染數(shù)據(jù)全部強(qiáng)制繪制,繪制完畢后再些換到新的Frame Buffer,這無(wú)形中就增加Tile Memory和System Memory之間數(shù)據(jù)的拷貝。也因此在移動(dòng)設(shè)備上切換Frame Buffer的使用要十分慎重。但從另一方面來(lái)看那些渲染數(shù)據(jù)并沒(méi)有立刻渲染,而是緩存了起來(lái),這也帶來(lái)了很大的優(yōu)化空間。
更強(qiáng)的移動(dòng)級(jí)gpu架構(gòu)——TBDR(Tile Based Deferred Rendering)
將TBDR放在這里可能會(huì)造成一種誤解,認(rèn)為T(mén)BDR是TBR的升級(jí)版。事實(shí)上,TBDR的是Imagination公司所獨(dú)有的一種移動(dòng)級(jí)gpu架構(gòu),被廣泛應(yīng)用于旗下PowerVR等產(chǎn)品中。由于其相比同時(shí)期其他TBR架構(gòu)的顯著優(yōu)勢(shì)受到蘋(píng)果公司的青睞,而被搭載到iphone上。近幾年iphone已經(jīng)開(kāi)始使用完全自研的A系列處理器也依舊是延續(xù)著TBDR架構(gòu)。TBDR的優(yōu)勢(shì)在于利用PB中緩存的頂點(diǎn)數(shù)據(jù),提前對(duì)流入到管線剩余部分的片段進(jìn)行了篩選,來(lái)解決傳統(tǒng)渲染管線的一個(gè)老大難問(wèn)題——過(guò)度繪制(over draw),而實(shí)現(xiàn)這一步的關(guān)鍵就在于HSR(Hidden Surface Removal)技術(shù)。
如上圖所示Image Synthesis Processor (ISP)從PB中逐圖元的取回當(dāng)前tile的頂點(diǎn)數(shù)據(jù)(只有頂點(diǎn)數(shù)據(jù)),ISP會(huì)對(duì)數(shù)據(jù)進(jìn)行差值并對(duì)差值得到的片元數(shù)據(jù)計(jì)算深度,并進(jìn)行深度和模板測(cè)試。如果通過(guò)測(cè)試,則更新片上的深度和模板緩存,同時(shí)在tag buffer中記錄該片元的圖元id。當(dāng)一個(gè)tile的所有圖元都經(jīng)過(guò)ISP的處理后,tag buffer中便會(huì)得到每個(gè)像素所對(duì)應(yīng)的唯一可見(jiàn)的圖元id。然后對(duì)這些可見(jiàn)的圖元,以圖元為單位從PB中取回頂點(diǎn)之外的其他varying數(shù)據(jù)(比如uv之類(lèi))通過(guò)TSPF進(jìn)行差值,然后傳給fragment shader。這也解釋了TBDR總流程圖中vertex data的兩條分支,*1代表流入ISP的頂點(diǎn)數(shù)據(jù),*2代表流出TSPF的其他數(shù)據(jù)。
TBDR也有一些弊端,比如那些在fragment shader中會(huì)丟棄的片元(alpha 測(cè)試)無(wú)法再fragment shader之前直到其是否需要繪制,因此對(duì)于這些片元需要通過(guò)上圖中的GCS提前提交給fragment shader并計(jì)算出確切深度后返回給ISP,這個(gè)過(guò)程阻塞掉其他片元的計(jì)算,因此是一種比較昂貴的代價(jià)。另外對(duì)于半透明物體(alpha混合)由于一個(gè)片元的顏色不僅由最近片元決定,所以此時(shí)會(huì)強(qiáng)制繪制緩存的片元,這樣便也增加了Tile Memory和System Memory之間的拷貝。因此應(yīng)該將物體分組,先開(kāi)啟深度測(cè)試?yán)L制非透明物體,再關(guān)閉深度測(cè)試?yán)L制透明物體。
雖說(shuō)HSR這種技術(shù)被Imagination申請(qǐng)了專(zhuān)利,并且在狹義上只有應(yīng)用了HSR技術(shù)的顯卡在能叫TBDR。但其他廠商也有自己針對(duì)TBR架構(gòu)的優(yōu)化,比如Arm的Forward Pixel Kill和驍龍的Flex Render都在力圖減少過(guò)度繪制。同時(shí)在軟件層面也有被稱(chēng)為T(mén)BD(Tile Based Deferred Shading)的著色管線,不過(guò)這和TBDR完全是兩個(gè)層級(jí)的概念。
再看IMR、TBR和TBDR
IMR和TBR因?yàn)檫@塊Tile Memory帶來(lái)了完全不同的渲染流程,有些原本適用的法則,在移動(dòng)端上則完全不一樣。除了上面提到過(guò)的切換FBO,alpha測(cè)試以及alpha混合等問(wèn)題。比如在IMR上,每一幀clear是完全不必要的,因?yàn)檎麄€(gè)屏幕都會(huì)被重新繪制而覆蓋掉上一幀的內(nèi)容。但對(duì)TBR來(lái)說(shuō)每一幀不clear則以為著需要在每一個(gè)tile開(kāi)始的時(shí)候?qū)⑸弦粠臄?shù)據(jù)拷貝到Tile Memory中,為防止這種完全沒(méi)必要的拷貝所以在TBR上需要每幀clear。如果考慮到TBR中Tile Memory的寶貴以及訪問(wèn)System Memory的難度,紋理采樣也變成了一種昂貴的操作。紋理數(shù)據(jù)是存儲(chǔ)在System Memory上,少量近期訪問(wèn)過(guò)的紋理會(huì)緩存在Tile Memory中,因此使用壓縮紋理可以讓有限的Tile Memory緩存更多的紋理數(shù)據(jù),同時(shí)LUT(Look-Up Table)這種不符合空間局部性的紋理數(shù)據(jù)會(huì)大幅降低緩存命中應(yīng)該少用。
TBR這樣一種為了適合移動(dòng)端種種限制而不得不誕生一種“妥協(xié)”的架構(gòu),雖有上述的種種限制,但卻也帶了意想不到威力。這塊神奇的Tile Memory不僅帶來(lái)了可以忽略的讀寫(xiě)成本,也為渲染管線提供了一塊臨時(shí)的緩存。這塊緩存的意義就在于,原本多個(gè)pass才能完成的渲染流程變成一個(gè)pass就可以。為了實(shí)現(xiàn)這種優(yōu)化,在Metal 2.0中提供ImageBlock和Tile Shader等技術(shù),允許開(kāi)發(fā)者對(duì)Tile Memory上的數(shù)據(jù)進(jìn)行編程,這也讓移動(dòng)端和桌面端渲染管線的實(shí)現(xiàn)有了極大的不同
總結(jié)
以上是生活随笔為你收集整理的GPU架构杂乱备忘——IMR、TBR、TBDR的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 通俗来理解 ARM芯片内核,架构,指令集
- 下一篇: 这篇数据库设计规范建议,我必须分享给你