田 澤 張 駿 許宏杰
(西安翔騰微電子科技有限公司 西安 710068)
(航空工業(yè)西安航空計算技術(shù)研究所 西安 710068)
(集成電路與微系統(tǒng)設(shè)計航空科技重點實驗室 西安 710068)
3D 圖形處理與2D 圖形處理最顯著的區(qū)別在于引入了深度的概念,使繪制結(jié)果產(chǎn)生了有層次的空間立體真實感受。3D 幾何圖形繪制渲染過程中的一個重要步驟就是深度測試。幀緩沖區(qū)的顏色緩沖區(qū)存儲像素的顏色值,深度緩沖區(qū)存儲像素的深度值,深度測試將像素的深度值與當前深度緩沖區(qū)中對應(yīng)的值進行比較,如果大于深度緩沖區(qū)的值,則丟棄該部分的像素,否則利用這個像素對應(yīng)的深度值和顏色值分別更新深度緩沖區(qū)和顏色緩沖區(qū),這樣就實現(xiàn)了判斷該像素是否需要繪制的問題。
深度測試能避免對最終不會看到的像素點的繪制,從而提高圖形流水線的執(zhí)行效率,其功能是在圖形流水線中的片段處理階段實現(xiàn)的,在光柵化階段之后,對光柵化輸出的像素的深度數(shù)據(jù)進行比較測試,是圖形處理器(graphic processing unit,GPU)像素填充率性能指標的重要影響因素。
圖元光柵化(rasterization)將連續(xù)方式描述的幾何圖元(點、線、離散三角形和扇帶)的頂點數(shù)據(jù)轉(zhuǎn)換為由離散片元(fragment)組成的二維圖像。片元是最初級的像素,每個片元包括顏色值(RGBA)、深度值(Z)、二維屏幕坐標(X、Y)等信息,與幀緩沖中的一個像素對應(yīng)。在Nvidia、AMD 等主流圖形處理器普遍采用的IMR(immediately mode rendering)架構(gòu)[1]中,為了最終能夠正確顯示位置重疊區(qū)域圖形距離觀察者最近的圖元像素顏色,每一個像素的深度數(shù)據(jù)Z 都需要在片上進行緩存,以便進行實時深度測試來分辨當前正在繪制像素的深度值與已經(jīng)繪制完成的像素深度值之間的前后遮擋關(guān)系。深度測試頻繁的深度數(shù)據(jù)讀寫操作不但需要的存儲器數(shù)據(jù)帶寬大,而且還在很大程度上決定了GPU 的像素填充性能。為了降低深度測試對片內(nèi)存儲資源和顯存帶寬的需求,文獻[2]提出的Early-Z 技術(shù)在進行像素染色前就對像素的可見性以一種粗粒度的方式進行提前測試。據(jù)ATI 的測試結(jié)果,采用Early-Z 技術(shù)進行提前深度測試能夠提前捕捉到50%以上最終不會通過深度測試的像素點。即使這樣,目前GPU像素填充性能普遍超過30 G pixel/s,所需要的深度測試能力依然對GPU 片上Z 緩存(Z Cache)設(shè)計提出了很高的要求。
數(shù)據(jù)預(yù)取是一種提升cache 命中率的技術(shù),中央處理器(central processing unit,CPU) Cache 數(shù)據(jù)預(yù)取由來已久,但CPU 數(shù)據(jù)訪問模式隨著應(yīng)用程序行為的變化而變化,表現(xiàn)為線性、跳躍和隨機各種模式,具有不確定性,且一次數(shù)據(jù)訪問量較少,只有4~16 bytes,導致CPU 數(shù)據(jù)預(yù)取效果受制于空間局部性和時間局部性因素在一些場景下不夠理想。相比之下,GPU 普遍采用高度并行數(shù)據(jù)處理架構(gòu),通常能夠一次并行實現(xiàn)32~128 個像素的深度測試處理,單次Cache 數(shù)據(jù)訪問量達到128~512 bytes,為預(yù)取數(shù)據(jù)使用的連續(xù)性和有效性奠定了基礎(chǔ)。并且,在圖形渲染過程中,GPU 的顏色和深度數(shù)據(jù)訪問模式在局部范圍相對集中和確定,顏色和深度數(shù)據(jù)在Cache 中是局部二維排布,與幾何圖形光柵化后最終在幀緩沖區(qū)中的二維顏色和深度數(shù)據(jù)的排布精確匹配,讀入Z Cache中數(shù)據(jù)使用率通常能夠達到95%以上,空間局部性捕獲效果很好,為數(shù)據(jù)預(yù)取準確性提供了很好的前提。
GPU 深度測試對片外幀緩沖存儲器數(shù)據(jù)訪問量較大,在數(shù)據(jù)的空間局部性強而時間局部性弱的情況下,必定周期性地發(fā)生深度Cache 缺失,導致處理延遲增大。如果能根據(jù)幾何圖形光柵化實時位置及像素Tile 的屏幕坐標提前訪問外部幀緩沖存儲器,就可以及時、精確地實施GPU 深度Cache 數(shù)據(jù)預(yù)取,有效避免周期性深度Cache 缺失造成的額外延遲,提升圖形渲染效率。像素數(shù)據(jù)需要GPU 的光柵化單元、像素著色器以及光柵操作單元對其依次執(zhí)行不同的操作。如果GPU 的光柵化單元能將當前被光柵化像素Tile(由n個空間上相鄰的片元組成)的屏幕坐標(x,y)提前發(fā)送給深度測試單元,則深度測試單元能夠依據(jù)該信息提前實施精確的預(yù)取操作。
本文提出一種圖元光柵化觸發(fā)的圖形處理器高效深度數(shù)據(jù)預(yù)取機制(depth data pre-fetching based on primitive rasterizing triggering,DPRT),通過圖元光柵化過程中實時掃描到的片段塊地址來觸發(fā)Z Cache的深度數(shù)據(jù)預(yù)取。同時為了適應(yīng)不同實現(xiàn)中流水線處理延遲,保證數(shù)據(jù)預(yù)取有效性,為Z Cache 數(shù)據(jù)塊增加訪問一次標志,有效提升了深度測試Z Cache訪問命中率,降低了深度測試延遲。
GPU 研制方面,國外Nvidia、AMD(ATI)、ARM、Vivante 和Imagination[3-8],已經(jīng)形成了完整的技術(shù)體系和產(chǎn)品體系,具有完整的配套圖形庫軟件、驅(qū)動軟件、編譯軟件和相關(guān)專用知識產(chǎn)權(quán)等相關(guān)設(shè)計資源,而且具有強大的技術(shù)創(chuàng)新能力。在國內(nèi),南京航空航天大學、電子科技大學、山東大學基于OpenGL ES 設(shè)計了嵌入式圖形處理器或系統(tǒng)[9-11]。中國科學技術(shù)大學設(shè)計了一種面向移動設(shè)備的3D 圖形處理器[12]。華南理工大學使用SystemC 設(shè)計了圖形處理器模型[13]。哈爾濱工業(yè)大學、上海交通大學、華東師范大學、北大眾志微處理器研究中心、長沙景嘉微電子公司和航空工業(yè)計算技術(shù)研究所[14-17]也對嵌入式GPU 進行了深入研究和設(shè)計。
預(yù)取技術(shù)以往主要應(yīng)用于微處理器的指令和數(shù)據(jù),研究人員針對不同類型應(yīng)用程序的存儲器訪問特征以及指令和數(shù)據(jù)在內(nèi)存中的不同排布模式,提出了多種有效的順序或非順序預(yù)取策略。如針對指令預(yù)取的面向程序連續(xù)執(zhí)行的Next-Line 指令預(yù)取策略、面向程序分支的Target-Line 指令預(yù)取策略[18]、BTA 分支目標地址預(yù)取策略[19]和硬件Markov 預(yù)取[20]。針對數(shù)據(jù)預(yù)取,Jouppi[21]提出了流緩沖區(qū)的順序預(yù)取機制,Palacharla 等人[22]提出步長檢測預(yù)取機制,Sherwood 等人[23]提出面向指針密集型的馬爾可夫與步長預(yù)取結(jié)合的數(shù)據(jù)預(yù)取策略,Roth等人[24]提出了基于跳轉(zhuǎn)指針的數(shù)據(jù)預(yù)取。另外,研究人員還提出了指令和數(shù)據(jù)的主動推送技術(shù)[25-26],與預(yù)取技術(shù)由CPU 內(nèi)核或Cache 向更底層存儲器發(fā)出預(yù)取請求,然后逐級向下傳遞請求,最終由更底層存儲器響應(yīng)請求并返回數(shù)據(jù)不同,主動推送技術(shù)是由主動推送部件對內(nèi)核將要使用指令和數(shù)據(jù)的預(yù)測發(fā)出訪存請求,最終將數(shù)據(jù)向上推送到Cache 或處理器內(nèi)核中,時效性更好。
這些預(yù)取和主動推送策略已經(jīng)廣泛應(yīng)用在各類CPU 設(shè)計領(lǐng)域,能有效降低Cache 缺失率。而GPU對于各類圖形數(shù)據(jù)和存儲帶寬的需求更為巨大,且數(shù)據(jù)訪問與圖形繪制過程直接相關(guān),數(shù)據(jù)訪問模式與通用CPU 應(yīng)用數(shù)據(jù)訪問模式差異較大,需要更有針對性和有效的數(shù)據(jù)預(yù)取機制。然而,在GPU 設(shè)計領(lǐng)域,目前沒有針對GPU 深度測試和深度數(shù)據(jù)預(yù)取機制的相關(guān)研究或報道。本文提出的GPU 深度數(shù)據(jù)預(yù)取機制基于自主設(shè)計的光柵化算法過程中的自定義關(guān)鍵時間節(jié)點作為深度Cache 的觸發(fā)信號進行數(shù)據(jù)預(yù)取,其預(yù)取有效性和準確性好,能夠取得較好效果。
GPU 架構(gòu)的發(fā)展經(jīng)歷了2 個階段,即分離染色架構(gòu)和統(tǒng)一染色架構(gòu)。無論物理架構(gòu)是分離染色的還是統(tǒng)一染色的,在邏輯上都遵循一套完整的圖形處理流程,在實現(xiàn)時映射為圖形處理流水線。一般地,GPU 圖形渲染流水線需要依次完成頂點著色、幾何圖元處理、圖元光柵化、像素著色,經(jīng)過片段處理后最終寫入幀緩沖區(qū)。圖元(primitive)是頂點的集合,組成一個3D 實體。常見的3D 圖元包括點、線、離散三角形和扇帶。圖元光柵化過程就是把連續(xù)的以數(shù)學方式描述的幾何圖元映射為離散的屏幕上像素點的過程,主要涉及掃描轉(zhuǎn)換、像素插值、反走樣等算法及其硬件實現(xiàn)。與本文相關(guān)的主要是掃描轉(zhuǎn)換過程。圖元掃描轉(zhuǎn)換是通過遍歷操作,逐個或批量判定出位于圖元內(nèi)部所有有效的像素點。光柵化處理的基本圖元包括點、線和三角形圖元。無論哪種圖元,輸入到光柵化階段的圖元頂點坐標都是浮點數(shù)表示,是連續(xù)的,但是屏幕上的像素是離散的,掃描轉(zhuǎn)換算法的主要任務(wù)是如何把連續(xù)的圖元用最接近的離散的柵格表示出來。對于點的掃描轉(zhuǎn)換,可直接對其實數(shù)坐標進行四舍五入,得到最接近該點的離散坐標位置;線圖元的2 種常用掃描轉(zhuǎn)換算法是數(shù)字微分分析儀(digital differential analyzer,DDA)算法和Bresenham 算法[27]。三角形圖元的掃描轉(zhuǎn)換過程對GPU 幾何性能影響最大,相對于點和線圖元來說更加重要,包括掃描線算法(Scanline)、包圍盒算法(Bounding Box)和中心線掃描算法(Centerline)[28],遍歷的方式?jīng)Q定了三角形掃描的效率,也很大程度上確定了后續(xù)深度測試過程中對深度數(shù)據(jù)的使用順序。
對于GPU 中深度測試功能來說,像素片段的深度數(shù)據(jù)由圖元光柵化階段產(chǎn)生,并在片段處理階段根據(jù)不同的深度測試函數(shù)將每個像素片段的深度與幀緩沖區(qū)中對應(yīng)位置像素的深度數(shù)據(jù)進行比較,最終決定該像素片段是否應(yīng)該被寫入幀緩沖區(qū),即光柵化處理在前,深度測試在后。在深度測試功能開啟的情況下,所有光柵化產(chǎn)生的像素片段必然都要進行深度測試(本文不考慮Early-Z 等類似提前深度測試技術(shù)帶來的層次化深度測試效果)。根據(jù)圖形處理流水線各階段先后關(guān)系以及光柵化和深度測試的這種特性,本文提出光柵化觸發(fā)的圖形處理器高效深度數(shù)據(jù)預(yù)取機制DPRT,希望能夠根據(jù)實際光柵化區(qū)域所覆蓋幀緩沖區(qū)像素區(qū)域,在片段處理單元進行深度測試前,提前將對應(yīng)像素深度數(shù)據(jù)預(yù)取到Z Cache 中,從而達到隱藏存儲器訪問延遲的目的。
本文采用基于Tile(4×4 像素塊)的掃描線算法進行三角形圖元掃描轉(zhuǎn)換。在此基礎(chǔ)上,DPRT深度數(shù)據(jù)預(yù)取的工作機制如圖1 所示。
圖1 光柵化觸發(fā)的深度數(shù)據(jù)預(yù)取機制
圖元經(jīng)過幾何階段處理后,被送入光柵化單元進行從圖元到像素片段的轉(zhuǎn)換,輸出的像素片段格式可以根據(jù)不同設(shè)計進行選擇,通常選擇以像素片段塊(Tile)為單位進行掃描輸出,這樣不但能夠提升光柵化效率,而且更加符合Z Cache 的數(shù)據(jù)緩沖特性,訪存深度緩沖區(qū)效率也較高。光柵化每產(chǎn)生一個Tile,就根據(jù)Tile 在深度幀緩沖區(qū)中的地址形成一個深度數(shù)據(jù)預(yù)取請求發(fā)送到Z Cache,Z Cache收到預(yù)取請求后向外部顯示存儲器發(fā)出深度數(shù)據(jù)訪問請求,預(yù)取的深度數(shù)據(jù)通常會在其對應(yīng)的像素片段Tile 完成像素染色階段處理和其他片段處理前進入Z Cache 中,從而實現(xiàn)隱藏像素片段Tile 深度數(shù)據(jù)訪問延遲的目的。
在不考慮Early-Z 技術(shù)帶來的層次化深度測試效果前提下,所有光柵化單元產(chǎn)生的像素片段Tile都必然要在片段處理單元從Z Cache 中取出深度數(shù)據(jù)進行深度測試。對Z Cache TAG 數(shù)據(jù)結(jié)構(gòu)進行優(yōu)化,為每一個Cache 數(shù)據(jù)塊Tag 域增加一個訪問一次標志(once touching tag,OTT),如圖2 所示。
圖2 Z Cache TAG 數(shù)據(jù)結(jié)構(gòu)優(yōu)化
預(yù)取的深度數(shù)據(jù)進入Z Cache 后,未被讀取之前置OTT=0;當Z Cache 中的深度數(shù)據(jù)被讀取一次后,置OTT=1。每次需要進行Z Cache 替換時,基于PLRU 算法優(yōu)先選擇已經(jīng)被訪問的Cache 數(shù)據(jù)塊(OTT=1,已經(jīng)完成深度測試需要的深度數(shù)據(jù)訪問)進行替換,保留OTT=0 的Cache 數(shù)據(jù)塊,從而實現(xiàn)在訪存效率較高的情況下,保證預(yù)取回Z Cache 中深度數(shù)據(jù)不會在使用前就被替換出去,降低了Z Cache 抖動概率和訪問缺失率。
圖3 以4 路組相連Z Cache 結(jié)構(gòu)說明了DPRT機制的工作流程。光柵化模塊接收圖元光柵化任務(wù)后,開始掃描并將當前像素Tile 的坐標地址發(fā)送給Z Cache 模塊,觸發(fā)深度預(yù)取動作。深度地址和請求產(chǎn)生模塊將深度數(shù)據(jù)預(yù)取請求發(fā)送給仲裁模塊。仲裁模塊首先要測試本次預(yù)取的深度數(shù)據(jù)是否已經(jīng)存在于Z Cache 中,如果已經(jīng)存在則撤銷本次預(yù)取;否則就在通過第二級仲裁的情況下,基于PLRU 替換算法和OTT 標志位優(yōu)先選擇最近訪問次數(shù)最少且OTT=1 的Cache 數(shù)據(jù)塊進行替換,并將臟塊寫回DDR,將深度預(yù)取請求送給存儲管理單元(memory management unit,MMU),訪問外部顯示存儲器中的深度緩沖區(qū)。由于前期已經(jīng)為不命中數(shù)據(jù)準備好了空Cache 塊,當外部顯示存儲器返回預(yù)取的深度數(shù)據(jù)后,依次查找當前組中的空行,直至將該數(shù)據(jù)寫入Z Cache DATA ARRAY 中,同時更新Cache TAG。
圖3 DPRT 工作流程
數(shù)據(jù)預(yù)取有效性包括2 個關(guān)鍵要素:時效性和準確性。時效性是指數(shù)據(jù)既要在訪問請求到達前到達Cache 中,同時還不能被過早替換出去。
首先,由于進行深度測試前像素片段Tile 還需要在統(tǒng)一染色陣列上完成像素染色階段的處理和其他片段處理功能(混合、邏輯操作等),延遲較大,可以認為形成預(yù)取地址到預(yù)取完成間的延遲與形成預(yù)取地址到使用深度數(shù)據(jù)間的延遲匹配。從光柵化、像素染色和外部顯示存儲器訪問延遲來看,深度數(shù)據(jù)能夠在進行深度測試前被預(yù)取進Z Cache 中。
其次,還需要考察預(yù)取的深度數(shù)據(jù)是否能夠不被過早地替換出去。DPRT 預(yù)取方案中,預(yù)取動作的觸發(fā)條件是開始光柵化掃描或者掃描步進,而光柵化掃描持續(xù)步進的條件是以前光柵化輸出的像素片段Tile 都完成像素染色階段處理,并發(fā)送給片段處理模塊。而片段處理模塊完成像素片段Tile 處理(包括深度測試功能)前會阻塞光柵化掃描步進過程。也就是說,預(yù)取操作存入Z Cache 中的深度數(shù)據(jù)在使用完成前,不會過早發(fā)生掃描線步進動作,那么下一次深度預(yù)取就不會開始,即Z Cache 中的深度數(shù)據(jù)不會被過早替換出去。另外,為了防止訪存延遲的變化和不同類型圖元導致的預(yù)取地址特征的變化,專門在Cache Tag 域中加入了OTT 標志位,從而能夠優(yōu)先選擇最近訪問次數(shù)最少且已經(jīng)被訪問至少一次的Cache 數(shù)據(jù)塊進行替換,盡量保證未被使用過的深度數(shù)據(jù)不會被過早替換出去。
對于深度數(shù)據(jù)預(yù)取來說,準確性是指在盡量多的覆蓋確定需要的數(shù)據(jù)的前提下,要盡量少地預(yù)取非圖元覆蓋區(qū)域的像素深度數(shù)據(jù)。一次預(yù)取包括少量非圖元覆蓋區(qū)域的像素深度數(shù)據(jù)是難免的,也是被允許的,這些數(shù)據(jù)可以作為其他圖元的深度預(yù)取數(shù)據(jù)來使用,但其所占比例不能太大,否則不但浪費外部顯示存儲器帶寬,而且容易造成Z Cache 的頻繁抖動。
預(yù)取的特性決定了會取回一些當前用不到的數(shù)據(jù),但只要比例不大并且能夠覆蓋到本次需要使用到的數(shù)據(jù)即可。其他多余的數(shù)據(jù)可能會在繪制其他圖形的時候被使用到,從而提升了外部顯示存儲器的帶寬利用率,并且不會造成Z Cache 的抖動。
采用基于現(xiàn)場可編程門陣列(field programmable gate array,FPGA)構(gòu)成的原型系統(tǒng)進行驗證,包括基于FPGA 和一系列外圍的接口子卡,如PCIe 2.0 x16 子卡、VGA 顯示子卡和外部顯示存儲器存儲子卡等,如圖4所示。
圖4 FPGA 原型系統(tǒng)
將本文提出的DPRT 深度數(shù)據(jù)預(yù)取機制進行FPGA 原型系統(tǒng)測試與評估。光柵化單元以4×4的像素片段Tile 為單位進行掃描輸出,Z Cache 容量為32 kB,4 路組相連,能夠容納8192 個像素點的深度數(shù)據(jù)。進行FPGA 綜合和布線,工作頻率可達100 MHz。
由于OpenGL 協(xié)議的官網(wǎng)只提供針對性能的測試程序和面向API 功能的符合性測試程序,為了全面精準地評測深度測試的功能和性能,本文基于FPGA 平臺,在深度測試功能打開的情況下,選擇4個典型3D 游戲場景作為測試程序[29],測試場景見圖5。這些測試場景所繪制的圖元類型不同,圖元個數(shù)不同,場景中的圖元深度值、深度比較函數(shù)的設(shè)置也不同,深度測試階段的數(shù)據(jù)訪問模式也不同,能較為全面地覆蓋深度測試功能的各種測試情形。
圖5 深度測試場景
本文從Z Cache 平均命中率性能和深度測試平均延遲性能2 個方面測試和評估使用DPRT 機制的設(shè)計和沒有使用DPRT 機制的設(shè)計(GPU BASE)。其中,GPU BASE 是包括了完整3D 圖形繪制流水線,但沒有添加DPRT 機制的自主研制GPU 結(jié)構(gòu),具體包括:頂點處理階段、幾何處理階段、光柵化階段和像素處理階段。DPRT 機制的關(guān)鍵是在光柵化模塊與像素處理階段的深度Cache 之間增加預(yù)取觸發(fā)控制通路,并為深度Cache 增加數(shù)據(jù)預(yù)取功能。
相對于CPU 來說,GPU 圖形算法硬件實現(xiàn)雖然復(fù)雜,但有針對性的算法硬件優(yōu)化卻能夠取得較好的效果。相對于GPU BASE 結(jié)構(gòu)來說,使用DPRT機制后,4 個測試場景的Z Cache 命中率均有顯著提升,如圖6 所示。場景2 的Z Cache 命中率提升最高,達到11.74%,場景4 的Z Cache 命中率提升最低,達到7.82%,平均提升9.51%。
圖6 DPRT 機制對Z Cache 命中率的提升情況
在開啟深度測試的情況下,對4 個場景的深度測試延遲情況進行了統(tǒng)計。由于Z Cache 命中率的提升,相對于GPU BASE 結(jié)構(gòu)來說,使用DPRT 機制后,4 個場景的深度測試延遲均有顯著降低。如圖7所示,場景3 的深度測試延遲降低最多,達到39.87%,場景1 的深度測試延遲降低最少,達到30.83%,平均延遲降低40.43%。
圖7 DPRT 機制對深度測試延遲的降低情況
深度測試是GPU 的關(guān)鍵功能,不但對存儲帶寬需求很大,而且決定了GPU 的像素填充率性能。針對GPU 圖形渲染流水線的結(jié)構(gòu)特性和深度測試功能的訪存行為特征,本文提出一種圖元光柵化觸發(fā)的高效深度數(shù)據(jù)預(yù)取機制DPRT,使用圖元光柵化過程中實時掃描到的像素片段塊地址來觸發(fā)Z Cache 的深度數(shù)據(jù)預(yù)取,并為Z Cache 數(shù)據(jù)塊Tag 域增加訪問一次標志,保證了深度數(shù)據(jù)預(yù)取有效性。DPRT 使深度測試時Z Cache 訪問命中率平均提升9.51%,深度測試延遲平均降低40.43%,取得了較好的效果。
考慮到不同的GPU 硬件實現(xiàn)中像素染色處理和片段處理單元的處理延遲以及顯示存儲器的訪問延遲可能存在差異,未來可以進一步研究深度數(shù)據(jù)預(yù)取時機與上述幾方面處理延遲間的動態(tài)自適應(yīng)機制,使得預(yù)取數(shù)據(jù)進入Z Cache 的時機與對應(yīng)像素片段Tile 的處理延遲更加匹配,從而進一步降低Z Cache 抖動概率和深度測試延遲。