在玩遊戲時遇到的掉幀、操作延遲,大概率和一個叫Draw Call的指標有關。
它是遊戲渲染的核心環節,也是性能優化繞不開的坎,哪怕是Unity、UE 引擎的資深開發者,也得在它身上下功夫。
什麼是Draw Call?
Draw Call僅僅是一條指令。
是CPU向GPU發送的繪圖指令,包含頂點、材質、紋理、着色器參數等,GPU接收後執行繪製。例如在Unity引擎中,每個使用獨立材質的物體都會觸發一次Draw Call,GPU接收到指令後執行頂點變換、光照計算、像素填充等操作,最終輸出到顯示設備。
![]()
就好比CPU是廚師長,下單(發Draw Call)告知GPU(廚師)做什麼菜(繪圖數據)、怎麼炒(渲染狀態),指令越多通信越耗時,越容易導致畫面卡頓。
其核心流程包含三個階段:
1、數據準備:CPU將這些數據從內存(RAM)傳輸至GPU顯存(VRAM)
2、狀態配置:設置渲染管線狀態(如着色器、混合模式、深度測試)和全局參數(如光照、投影矩陣)
3、指令提交:調用glDrawElements或DrawIndexedPrimitive等API觸發GPU渲染
關鍵特性:
命令緩衝區機制:CPU與GPU通過Command Buffer實現異步通信,CPU寫入指令,GPU按隊列順序執行
渲染狀態切換成本:每次材質、紋理或着色器變更需重新配置全局狀態,產生額外開銷
你在遊戲裏看到的每棵樹、每個角色、每道特效,背後都需要CPU發一次(或多次)命令,告訴 GPU “該畫這個東西了”。比如屏幕上有100棵樹,默認情況下可能就有100個Draw Call,GPU收到命令後纔會執行渲染操作。
![]()
這裏要明確一個關鍵點:Draw Call就是一個命令,它的發起方是CPU,接收方是GPU。這個命令僅僅會指向一個需要被渲染的圖元(primitives)列表,而不會再包含任何材質信息。
而Draw Call中造成性能問題的元兇其實不是的GPU,真正“拖後腿”其實的是CPU
Draw Call多了會影響幀率?
舉個栗子:先創建10000個小文件,每個文件的大小爲1KB,然後把它們從一個文件夾複製到另一個文件夾。你會發現,儘管這些文件的空間總和不超過10MB ,但要花費很長時間。
然後再創建一個單獨的文件,它的大小是10MB,然後也把它從一個文件夾複製到另一個文件夾。而這次複製的時間卻少很多。
這是爲什麼呢?明明它們所包含的內容大小是一樣的。原因在於,每一個複製動作需要很多額外的操作,例如分配內存、創建各種元數據等。
如你所見,這些操作將造成很多額外的性能開銷,如果我們複製了很多小文件,那麼這個開銷將會很大。
渲染的過程雖然和上面的例子有很大不同,但也是類似的道理。在每次調用Draw Call之前, CPU需要向GPU發送很多內容,包括數據、狀態和命令等。
![]()
在這一階段, CPU需要完成很多工作,一旦CPU完成了這些準備工作, GPU就可以開始本次的渲染。
影像CPU還是GPU?
如果Draw Call的數量太多,CPU就會把大量時間花費在提交Draw Call上,造成CPU的過載,CPU會首先成爲瓶頸。
![]()
其次是GPU,GPU的吞吐量其實遠遠大於CPU,但DrawCall過多也會在一定程度上影響GPU,這是由於數據沒有組織好,導致GPU頻繁切換硬件狀態,頻繁請求顯存數據,頻繁出現Cache Miss情況造成的。
所以對於開發者來說,Draw Call作爲遊戲性能的關鍵指標,優化的核心從來不是讓GPU少畫,而是讓CPU少發命令。
![]()
比如批處理的方法,很顯然就是在CPU中把很多小的DrawCall合併成一個大的Draw Call,再發送給GPU。
而批處理也分靜態和動態,由於需要在CPU的內存中合併,而合併的過程是需要消耗時間的。因此,批處理技術更加適合於那些靜態的物體,例如不會移動的大地、石頭等,對於這些靜態物體只需要合併一次即可。
當然,也可以對動態物體進行批處理。但是,由於這些物體是不斷運動的,因此每一幀都需要重新進行合併然後再發送給GPU,這對空間和時間都會造成一定的影響。
🙏感謝閱讀、點贊和充電
更多遊戲資訊請關註:電玩幫遊戲資訊專區
電玩幫圖文攻略 www.vgover.com
