目前所有的移動裝置都使用的是 Tile-Based Deferred Rendering(TBDR) 的渲染架構。TBDR 的基本流程是這樣的,當送出渲染指令的時候,GPU 不會立刻進行渲染,而是一幀内所有的渲染指令積攢起來,最後統一渲染。在渲染到 FrameBuffer 的時候,也不是依次執行所有的指令将 Fragment 結果填充到 FrameBuffer 中。而是在 GPU 内部有着叫做 Tile 的高速渲染器,這些 Tiles 虛拟的将 FrameBuffer 分割成小塊(光栅化後得到很多 Fragment,很容易就能決定 Fragment 所在的 Tile),每次執行一小塊中的所有渲染指令,完成後将結果寫回 FrameBuffer。這些 Tile 一般會在 32x32 像素的大小,當然根據設計的不同而各部相同。Tile 的數量一般不足以完全平鋪整個 FrameBuffer,一次隻能覆寫一部分 FrameBuffer 的區域,是以每幀内同一個 Tile 會執行多次渲染操作。
TBDR 的渲染架構帶來了一個非常大的好處,就是 Hidden Surface Removal。當 vertex shader 執行完成後,通過插值得到很多 fragment,這個之後每個 fargment 的深度值就已經知道了,那麼就可以利用這個深度值将最終不會渲染到螢幕(被其它 fragment 遮擋)的 fragment 剔除,減少了很多 fragment shader 計算量,提高了填充率。注意,這個隻對非透明的物體有效,如果是 AlphaTest(shader 中表面為使用了 clip 或者 discard) 或者 Transparent(Alpha 不是 1),是沒有 Hidden Surface Removal 效果的。因為很簡單,透明的 fragment 無法遮擋住後面 fragment。也就是說并不是 AlphaTest 和 Blend 本身是大消耗操作,而是因為破壞了 Hidden Surface Removal。
在 TBDR 的渲染架構下還有很重要的一點需要注意。立即渲染模式下,有一個技巧是,當每一幀都不去清屏的時候是可以提高效率的,因為 clear 操作需要将值寫入 FramBuffer 中的每一個像素中,這是需要花費一定時間的。而這個技巧在 TBDR 中是行不通的,反而會起到反效果。這是因為,如果你沒有調用 clear 操作,表示你認為上一幀的内容是不能丢棄的,是以在渲染 tile 的時候,硬體會将 FrameBuffer 中資料先寫入 Tile,然後再執行渲染,這個寫入操作無形中增加了很多的負擔,有可能就會嚴重影響到程式的執行效率。
下面是幾個很好的參考資料:
OpenGLInsights-TileBasedArchitectures.pdf
Tuning Your OpenGL ES App
https://chengkehan.github.io