GPU專欄(四) 基於塊的渲染(Tile Based Rendering)


IMG使用了基於塊的渲染管線,而且是更進一步,名為TBDR, 在這之前,我們先來了解一下TBR, 這些都是移動端GPU常用到的技術。

Q1:什么是TBR, 以及為什么要用TBR?

我覺得要回答這個問題,前提是要先了解一下,GPU的顯存、GPU內部的on-chip color buffer, 以及系統內存之間的關系;

顯存,類似於系統的內存,但它是顯卡專用的內存。顯存主要用來緩存 GPU 處理過的或者即將提取的渲染數據。顯存主要包括容量、頻率和位寬這三個參數。

帶顯存的GPU一般是桌面端PC專享,因為不需考慮功耗,可着高性能使勁造就行;也正是配合着支持大帶寬的顯存,桌面端才肆無忌憚的使用IMR技術。比如之前片元着色完成后,假設后面會有alpha blending, 那么就不可避免的會有大量的讀改寫過程。

for draw in renderPass:
    for primitive in draw:
        for vertex in primitive:
            execute_vertex_shader(vertex)
        for fragment in primitive:
            execute_fragment_shader(fragment)

 

 所謂IMR就是,無腦對每一次drawcall都執行,這樣的情況下,即使遠處的物體被近處的物體覆蓋而無法顯示,但是還是會被過繪制,缺點是顯而易見的,對gpu的性能可能帶來不必要的浪費。

以往這些都是依賴消耗GPU大量的顯存帶寬來完成(上圖中Framebuffer Working Set的部分),在移動端GPU中,顯然不可能有這種享受。移動端GPU要考慮性能功耗的平衡,而且沒有顯存可用,只能和CPU共用系統內存,所以沒辦法,只能想辦法優化。首先是硬件上搞了個片上內存,也就是IMG文檔中的那個on-chip color buffer, 然后呢,這個片上內存顯然不會很大,但是速度很快,比系統內存要快;基於這種特性,按照分塊來處理着色過程就是很自然的想法了。首先是每個draw call,只執行vertex shader, 確定好圖元的位置后,並不直接執行frag shader, 而是開始進行分塊,也就是Tilling, tile大小大概是16x16, 然后呢,每個tile中會由一個list記錄在此tile中的所有片元,所有的這些完成后才會進行光柵化以及進入frag shader的處理,然后frag shader就會遍歷每個tile, 然后再對每個tile中的片元執行着色,以及做alpha blending等,所有這些都是在片上內存中完成的,減少了對系統內存的大量讀寫操作。最終所有tile處理完,才寫入DDR中。這么一搞,就節省了系統帶寬,降低了功耗而且減少了性能的浪費。上述過程對應的偽代碼就是:

# Pass one
for draw in renderPass:
    for primitive in draw:
        for vertex in primitive:
            execute_vertex_shader(vertex)
        append_tile_list(primitive)

# Pass two
for tile in renderPass:
    for primitive in tile:
        for fragment in primitive:
            execute_fragment_shader(fragment)

 

 基於tile的渲染還可以結合FBC技術進一步壓縮帶寬【比如IMG的TFBC技術】,這大概也就是為什么你看到了IMG的FBC也是分塊的原因吧。

當然,上述方式要說缺點也是有的,那就是增加了Geometry Working Set的開銷,所以還是有關於權衡的藝術。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM