Unity - DrawCall優化相關 Batch 動態合批 靜態合批


什么是DrawCall

CPU呼叫GPU進行繪制是一次DrawCall

以 OpenGL 為例,就是調用帶有繪制功能的 API 的次數

如:DrawCall : 10 次,那就意味着調用了 glDrawXXXX 的 API 10 次


 

啥叫:Batch

Batch 直譯:批量,的意思
在 實時渲染 中,已動態合批為例(Dynamic Batch)一般理解為:為了減少 DrawCall,或是減少 SetPassCall 而將繪制時材質一樣(或是說 shader + shader 參數 + 繪制前狀態,都一樣)的 VBO,IBO,等數據打包到一個大的 VBO,或是 IBO 中,然后在調用一次 DrawCall,從而提升性能:SetPass 的 State 時,或是多次 Draw API 調用產生過多的 CPU 消耗的性能的問題
(另外還有:靜態合批(Static Batch)、Instanced 批量(GPU Instancing Batch)繪制,都算是 Batch 的方式)
所以 Batch 的目的是:將原本需要 多次 SetDrawState + 多次 DrawCall,優化為:1次 SetDrawState + 1次 DrawCall
可以簡單的理解為:批量渲染是通過減少CPU向GPU發送渲染命令(DrawCall)的次數,以及減少GPU切換渲染狀態的次數,盡量讓GPU一次多做一些事情,來提升邏輯線和渲染線的整體效率。但這是建立在GPU相對空閑,而CPU把更多的時間都耗費在渲染命令的提交上時,才有意義。

 

合批最重要的前提:材質必須相同!!!

Batch ≠ DrawCall

 


 

優化方式

相同材質的物體一同繪制

那么如何相同材質的物體一同繪制

就是把相同材質的物體的網格合並一同繪制

 

Why?

  • 底層的圖形api有一個繪制三角形的接口,這個就是CPU調用gpu繪制的接口
  • 在調用這個接口前會准備頂點數據,即網格數據
  • 把網格合並后只要進行一次繪制三角形的接口調用,減少了DrawCa

 


 

為啥要優化DrawCall

上面已經說了,Cpu叫GPU執行一次繪制渲染就是DrawCall。

傳輸數據消耗比較大,GPU的計算能力也相對較強,就可能存在CPU傳遞的指令只讓渲染一小部分,GPU執行完畢以后,但是下一條的指令還沒有過來的時候,

這就好比這條路車多了,堵車了,那么如何梳理交通,讓一次通過的紅綠燈讓更多的車子過去,提供更高效的通行效率和時間呢?關鍵就是在於,這次紅綠燈,我讓多少車過去了。

所以,提高DrawCall的效率非常的重要,就是保證盡量的讓每次的DrawCall能夠渲染更多的內容(讓更多的車子過去)。這樣,即便是紅綠燈通行次數少了(DrawCall的提交次數),但是

通行效率提高了,一次性過去的車子多了,那么也能有效的減少擁堵的情況。

然后如何去提升DrawCall的效率呢,主要的方法就是合批(Batch),,也就是上面解釋的名詞。


Unity中的合批

靜態合批 Static Batching

  • Unity中把物體標記為Static,然后開啟靜態合批
  • 限制
    • 需要保持static,不能改變transform
    • 使用相同材質的物體才能合批
    • 一個批次上限為~15k個頂點
       

動態合批 Dynamic Batching

Unity自帶動態合批,需要在Unity中開啟動態合批選項
會導致cpu消耗,如果不是gpu有瓶頸,最好關閉動態合批
前提
   使用頂點位置、法線、UV0、UV1和切線為一個着色器提供180個頂點
   使用頂點位置、法線和單一UV的着色器的300個頂點

 

動態合批的限制條件呢?

●材質球相同;

●Mesh頂點數量不能超過300以及頂點屬性不能超過900;

●縮放不能為負值(x、y、z向量的乘積不能為負)等。

 

 


 

靜態合批的利弊

靜態合批采用了以空間換時間的策略來提升渲染效率。

 

其優勢在於:網格通常在預處理階段(打包)時合並,運行時頂點、索引信息也不會發生變化,所以無需CPU消耗算力維護;若采用相同的材質,則以一次渲染命令,便可以同時渲染出多個本來相對獨立的物體,減少了DrawCall的次數。
在渲染前,可以先進行視錐體剔除,減少了頂點着色器對不可見頂點的處理次數,提高了GPU的效率。

其弊端在於:合批后的網格會常駐內存,在有些場景下可能並不適用。比如森林中的每一棵樹的網格都相同,如果對它采用靜態合批策略,合批后的網格基本等同於:單顆樹網格 x 樹的數量,這對內存的消耗可能就十分巨大了。

總而言之,靜態合批在解決場景中材質基本相同、網格不同、且自始至終都保持靜止的物體上時,很適用。

 


動態合批與靜態合批的區別

1、動態合批不會創建常駐內存的“合並后網格”,也就是說它不會在運行時造成內存的顯著增長,也不會影響打包時的包體大小;

2、動態合批在繪制前會先將頂點轉換到世界坐標系下,然后再填充進頂點、索引緩沖區;靜態合批后子網格不接受任何變換操作,僅手動合批后的Root節點可被操作,因此靜態合批的頂點、索引緩沖區中的信息不會被修改(Root的變換信息則會通過Constant Buffer傳入);

3、因為2的原因,動態合批的主要開銷在於遍歷頂點進行空間變換時的對CPU性能的開銷;靜態合批沒有這個操作,所以也沒有這個開銷;

4、動態合批使用根據渲染器類型分配的公共緩沖區,而靜態合批使用自己專用的緩沖區。

 


 

開啟方法

Player Setting > Other Settings

 


免責聲明!

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



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