了解DrawCall


一、什么是DrawCall  

    DrawCall的含義就是CPU調用圖像編程接口,以命令GPU進行渲染的操作。

    CPU和GPU通過使用一個命令緩沖區實現並行工作。命令緩沖區包含一個命令隊列,CPU向其中添加命令,GPU從中讀取命令,添加和讀取是相互獨立的,因此使得CPU和GPU可以獨立工作。命令緩沖區中的命令有很多種類,DrawCall就是其中一種。

二、為什么DrawCall多了會影響幀率

    DrawCall中真正造成性能問題的元凶是CPU。

    在每次調用DrawCall之前,CPU需要向GPU發送很多內容,包括數據、狀態和命令等。在這一階段,CPU需要完成很多工作,例如檢查渲染狀態等。而一旦CPU完成了這些准備工作,GPU就可以開始本次渲染。GPU的渲染能力很強,渲染速度往往快於CPU提交命令的速度。如果DrawCall的數量太多,CPU就會把大量時間花費在提交DrawCall上,造成CPU的過載。

三、DrawCall優化

    優化有一下幾個解決方案:

        1、使用Draw Call Batching,也就是批處理。Unity在運行時可以將一些物體進行合並,從而用一個DrawCall來渲染他們。具體下面會介紹。

        2、通過把紋理打包成圖集來盡量減少材質的使用。

        3、盡量少的使用反光,陰影之類的,因為那會使物體多次渲染。

    Draw Call Batching技術

    Unity內置了Draw Call Batching技術,它的主要目標就是在一次DrawCall中批量處理對個物體。只要物體的變換和材質相同,GPU就可以按完全相同的方式進行處理,即可以把它們放在一個Draw Call中。

    Draw Call Batching技術存在缺陷,當它需要把一個Batch中的所有物體組合到一起,相當於創建了一個與這些物體加起來一樣大的物體。這就需要分配相應大小的內存,也需要消耗CPU時間。特別是對於移動的物體,每一幀都得重新進行組合。但對於靜止不動的物體,只需要進行一次組合。

    Unity提供了Dynamic Batching和Static Batching兩種方式。

    Dynamic Batching

    Dynamic Batching是完全自動進行的,不需要也無法進行任何干預。

    動態批處理的約束:

        1、批處理動態物體需要在每個頂點上進行一定的開銷,所以動態批處理僅支持小於900頂點的網格物體。

        2、如果着色器使用頂點位置,法線和UV值三種屬性,那么只能批處理300頂點以下的物體;如果着色器需要使用頂點位置,法線,UV0,UV1和切向量,那么只能批處理180頂點以下的物體。

        3、不要使用縮放,分別擁有縮放大小(1,1,1)和(2,2,2)的兩個物體將不會進行批處理。

        4、統一縮放的物體不會和非統一縮放的物體進行批處理。

        5、使用縮放尺度(1,1,1)和(1,2,1)的兩個物體將不會進行批處理,但是使用縮放尺度(1,2,1)和(1,3,1)的兩個物體將可以進行批處理。

        6、使用不同材質的實例化物體將會導致批處理失敗。

        7、擁有lightmap的物體含有額外(隱藏)的材質屬性,比如:lightmap的偏移和縮放系數等。所以,擁有lightmap的物體將不會進行批處理(除非他們指向lightmap的同一部分)。

         8、多通道的shader會妨礙批處理操作。比如,幾乎unity中所有的着色器在前向渲染中都支持多個光源,並為它們有效地開辟多個通道。

         9、預設體的實例會自動地使用相同的網格模型和材質。  

    Static Batching

    Static Batching需要把靜止的物體標記為Static,然后無論大小,都會組成Batch。

    如何對動態加載的靜態物體進行靜態合批操作:
    GameObject go = (GameObject)Instantiate(...);
    go.isStatic = true;//將實例化的物體設置為靜態
    go.transform.parent = root.transform;
    gosList.Add(go);
    gos = gosList.ToArray(); 
    StaticBatchingUtility.Combine(gos, root);靜態合並

    高效利用Draw Call Batching

    1. 首先是盡量減少場景中使用的材質數量,即盡量共享材質,對於僅紋理不同的材質可以把紋理組合到一張更大的紋理中。

    2. 然后是把不會移動的物體標記為Static。此外還可以通過CombineChildren腳本(StandardAssets/Scripts/UnityScripts/

CombineChildren)手動把物體組合在一起,但這個腳本會影響可見性測試,因為組合在一起的物體始終會被看作一個物體,從而會增加GPU要處理的幾何體數量,因此要小心使用。

    3. 對於復雜的靜態場景,還可以考慮自行設計遮擋剔除算法,減少可見的物體數量同時也可以減少Draw Call。

 

    NVIDIA 在 GDC 曾提出,25K batchs/sec 會吃滿 1GHz 的 CPU,100的使用率。所以他們推出了一條公式,來預估游戲中大概可以 Run 多少個 Batch:
     
    舉個例子:如果你的目標是游戲跑30FPS、使用2GHz的CPU、20%的工作量撥給Draw Call來使用,那你每幀可以有多少Draw Call呢?
333 Batchs/Frame = 25K * 2 * (0.2/30)

 

 

參考資料:https://blog.csdn.net/zhongdong00/article/details/80590396

 


免責聲明!

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



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