標籤:

[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:遊戲引擎 |