[Siggraph15] GPU-Driven Rendering Pipelines
GPU-Driven Rendering Pipelines
GPU來掌控哪些實際渲染的物體
-切換viewport/frustum
-GPU更細粒度的Visibility
-不需要CPU/GPU的來回傳遞數據
動機:
RedLynx
User generated content(UGC)
-內容伺服器下載,需要精簡尺寸
-沒法預烘焙
-非常細小的module組合
-超遠視距
-shadowmap造成dp膨脹
-物理模擬/腳本系統CPU開銷大
Assassin』s Creed Unity
-超多幾何物體
-內部建築無縫讀圖
-大量人群
-模塊化半自動生成內容(大量dp)
Mesh Cluster Rendering
-Fixed topology (64 vertex strip,64 thread per wavefront)
-重整所有mesh來適應cluster(包括degenerated triangle)
-從vs中讀取shared buffer來獲取頂點(不需要setVB/IB)
-DrawInstancedIndirect(節省大量CPU time)
-GPU culling輸出cluster list以及drawcall參數
-一個dp任意多的模型
-GPU使用cluster bounds來cull
-cluster可以做depth sorting來避免overdraw
Cons:
-Memory increase due to degenerate triangles
-Non-deterministic cluster order(會造成z-fighting)
Overview
1. CPU使用coarse quad tree culling
2.CPU update GPU數據
-instance data:
*比如transform/LOD factor/…
*每個instance使用8 offsets去索引數據,比如vb location/extents/transform
*對於static mesh,這些數據是永久的
-對於非instance data建立hash
*比如material/renderstate/…
-使用這些hash來merge drawcall
*merge之前,會sort by distance drawcall
3. Batch Drawcall
4. Instance culling
-instance stream包含了GPU-buffer per instance的數據,比如transform/instance bounds等(ExecuteIndirect)
-GPU做frustum和occlusion,對於通過的instance生成cluster chunk
5. Cluster chunk expansion
-使用中間數據chunk的原因是,每個instance展開的cluster數量方差太大(1-1000),直接展開會造成wavefront計算資源不平均,每個chunk可以展開64個clusters
6. Cluster culling
這一步使用instance的transform和每個cluster的bounds去做frustum和occlusion culling。對於每個cluster,會在之前預烘焙cluster的view-dependent的朝向mask做backface culling。通過culling的cluster會導出index compact job,其中包含triangle mask和r/w offsets,這些offset根據關聯的instance primitive使用atmoic操作生成
7.Index compaction
Index buffer之前在cpu上create的,所以每個mesh的ib都是full unculled。因為compact ib比較小(8MB),所以一次場景渲染可能沒法完全存進一個buffer。所以index compaction(ExcuteIndirect)和multi-draw(DrawIndexInstancedIndirect)是交替進行的
每個wavefront處理一個cluster,每個線程處理一個三角形,它們之間是相互獨立的。根據之前cluster culling傳遞的triangle mask和i/o offsets,每個線程計算輸出正確的寫入位置。這步通常佔用5-10%的geometry rendering(G-Buffer pass)
8.Multi-Draw
最後每個batch一個multi-draw,渲染數據
Occlusion Depth Generation
-Pre-Depth pass(~300 best occluders,使用bounds和美術設置的標記作為occluder,選擇其中最近的300個occluder)
-Full-res HiZ & EarlyZ
-使用downsample的Z(512*256)
-混合上一幀的depth
*reproject會補充occluder的空洞,但是當鏡頭移動時,可能還是會出現空洞;如果有太大的快速移動物體時,可能會出現false occlusion,reject鏡頭附近的occluder來避免這種情況
-HiZ for GPU Culling
Shadow Occlusion Depth Generation
-camera depth reprojection(64*64)
-和上一幀shadowmap混合
*有太大的快速移動物體時也會有問題,但是基本上沒有
-Hi-Z for GPU Culling
Camera depth reprojection
-會遮擋掉大部分view中被遮住的caster
Results
-CPU
*節省了1-2個數量級的drawcall
*75%的時間開銷,~10倍數量的物體
-GPU
*20-40%的三角形culled
*整體只有<10%的性能提升
*30-80% shadow三角形culled
Virtual Texturing
-256』000*256』000
-128*128 texel
-8k*8k page cache
*5 texture array:
albedo,specular,roughness,normal,etc.*BC5/BC3
GPU-Driven Rendering with VT
-所有的texture數據一次性全部準備好,只用一次texture binding
-不在需要根據texture來batch
Single Draw Call Rendering
-GPU-driven pipeline可以一次性取得所有mesh data,vt可以取得所有texture,意味著整個場景只需要一次drawcall
-Dynamic branching for different vertex animation types
-可以在cluster的細粒度來sort場景,這樣在geometry pass就相當於pre-depth
-cheap OIT using inverse sort
-複雜的材質blend和decal可以直接保存在VT中
-VT自帶cache,節省了大量的帶寬(可以讓關卡設計師隨意放置decal,任意使用大量材質,不用關心貼圖尺寸數量)
-對UGC特別友好(假設用戶沒有technical knowledge)
Virtual Deferred Texturing
-下次再說
Two-Phase Occlusion Culling
-跟精確的pixel級別culling
-不用渲染一遍occluder
-只用上一幀的full-res depth
Benchmark
-250』000物體
-1GB mesh數據
-只用兩個DrawInstancedIndirect
XB1上的數據,性能好的令人咋舌。。。
PS:15年Ubi剛出GPU-Driven的產品,結果Unity被稱為Bug最多的一款AC。。。不過Ubi在遊戲技術創新和開拓的精神真的令人 十分敬佩,當年Ubi China是可是中國遊戲的黃埔軍校啊。16年SIG上Frostbite更進一步,進行了triangle級別的culling以及index compact。NVidia有一篇類似 tech report,CPU的性能優化提升了百倍數量級,隨著DX12的到來,CPU的 計算力 算是得到了 更好的解放,不過在GPGPU方面的探索和進步還是有很多值得學習研究的地方。
推薦閱讀:
※從零開始手敲次世代遊戲引擎(四十二)
※Matrix and Transform Conversion 1/3
TAG:遊戲引擎 |