Draw Call就是CPU調用圖形編程接口,比如DirectX或OpenGL,來命令GPU進行渲染的操作。
例如,DirectX中的DrawIndexedPrimitive命令,OpenGL中的glDrawElement命令。
1.CPU和GPU并行工作的原理
為了CPU和GPU可以并行工作,就需要一個命令緩沖區(Command Buffer)
命令緩沖區包含了一個命令隊列,由CPU向其中添加命令,而由GPU從中讀取命令。添加和讀取的過程是相互獨立的,因此命令緩沖區可以使CPU和GPU相互獨立工作。當CPU需要渲染一些對象時,它可以向命令緩沖區添加命令,而GPU完成了上一次的渲染任務后,它就可以從命令隊列里取出一個命令并執行它。
命令緩沖區中的命令有很多種類,而Draw Call是其中的一種,其它命令還有改變渲染狀態等命令(改變使用的Shader,使用不同的紋理等)。
2.為什么 Draw Call多了會影響幀率?
在每次調用Draw Call之前,CPU需要向GPU發送很多內容,包括數據,狀態,命令等。在這一階段,CPU需要完成很多工作,例如檢查渲染狀態等。而一旦CPU完成了這些準備工作,GPU就可以開始本次的渲染。GPU的渲染能力是很強的,渲染300個和3000個三角網格通常沒有什么區別,因此渲染速度往往快于CPU提交命令的速度。如果Draw Call的數量太多,CPU就會把大量時間花費在提交Draw Call命令上,造成CPU的過載。
*因此造成Draw Call性能問題的元兇是CPU。
3.如何減少DrawCall?
提交大量很小的Draw Call會造成CPU的性能瓶頸,即CPU把時間都花費在準備Draw Call的工作上了。那么,一個很顯然的優化想法就是把很多小的Draw Call合并成一個大的Draw Call,這就是批處理的思想。
需要注意的是,由于我們需要在CPU的內存中合并網格,而合并的過程是需要消耗時間的。因此,批處理更適合靜態的物體,例如不會移動的大地,石頭等,對于這些靜態物體我們只需合并一次即可。當然,我們也可以對動態物體進行批處理。但是,由于這些物體是不斷運動的,因此每一幀都需要重新進行合并然后再發送給GPU,這對空間和時間都會造成一定的影響。