Render - 淺談 CPU 與 GPU 如何分工?
05-18
Render - 淺談 CPU 與 GPU 如何分工?
來自專欄 Unity
針對渲染導致的性能問題,這個世界上是沒有一套萬能的解決方案的。渲染的性能問題涉及到許多因素,不僅僅是遊戲本身,它也很大程度上取決於運行遊戲的硬體和操作系統。最重要的是我們要通過不斷的研究和實驗來解決這些性能問題。
知道了渲染工作的流程以及階段可以幫我們更好的研究和解決渲染方面的性能問題。這篇文章主要是介紹在渲染工作的一幀中,我們的CPU與GPU都做了些什麼?
我們這裡提到的 Object 指我們遊戲中會被渲染的對象,任何掛有渲染組件 (Renderer Component) 的 GameObject 都將被引擎作為 Object 進行渲染。
基本上,渲染工作可以分解為以下步驟:
- 中央處理器(CPU)進行準備工作,比如哪些對象要被繪製,需要如何被繪製。
- CPU向圖形處理器(GPU)發送指示。
- GPU根據CPU的指示進行圖形的繪製。
接下來我們會針對這些步驟進行更詳細的研究,這裡主要是說明一下在渲染工作中CPU與GPU所扮演的角色。
渲染工作我們也常稱之為渲染管線。
在每一幀的渲染流程中, CPU 主要做了這些事:
- 確認場景中哪些對象需要被渲染,一個object只要在符合特定的規則才會被渲染。例如,當處於相機的視錐體內的對象可以被渲染,而超出(不在視錐體內)的部分則被剔除(Culled),不進行渲染。
- CPU會收集這些將要被渲染的每一個對象的數據,並且整合成指令,即我們常說的Draw Calls。一個Draw Call包含一個單獨的材質(mesh)數據和它將如何進行渲染的信息。比如,需要對材質使用哪些貼圖等。在某些情況下,使用相同的設置的object數據會被合併進一個Draw Call。將不同的object數據合併到一個Draw Call的行為我們稱之為 合批(Batching)。
- CPU會為每一個Draw Call創建一個數據包叫做 batch,然而,batch中包含的數據不僅僅是draw call,還有一些數據由於與我們探討的渲染性能問題無關,因此就不在這裡展開。一旦完成了batch工作,CPU接著會進行如下工作:
- 發送一條指令給到GPU變更渲染狀態(Render State)。這個指令我們稱為 SetPass Call。SetPass Call的作用是告訴GPU在渲染下一個材質的時候該使用哪一種設置。SetPass Call僅當從前一個材質到下一個材質確實需要變更渲染狀態的情況下CPU才會發出。
- CPU發送一條Draw Call指令給到GPU。Draw Call指示GPU按照最後一次SetPass Call定義的設置來對具體的材質進行渲染。
- 某種情況下,你的batch可能包含不止一個渲染通道(pass),這取決於你的 shader 代碼中pass的代碼塊,一個pass代碼塊就需要GPU變更一次渲染狀態。所以,一個batch中每多包含一個pass,CPU就要新發送一次SetPass Call到GPU,然後再把Draw Call發送一次到GPU。
與此同時, GPU 會進行如下工作:
- GPU按照CPU的要求完成渲染任務。
- 如果當前任務是一個SetPass Call,那麼GPU會變更當前的渲染狀態(Render State)。
- 如果當前任務是一個Draw Call, GPU就渲染指定的材質。這部分工作是分階段進行,由shader 代碼中不同的部分決定。這部分比較複雜,在這裡不進行詳述,感興趣的朋友可以去看一下《Unity Shader 入門精要》這本書,對於入門shader的同學比較有用,推薦一下。我們這裡只需要知道shader中有一部分代碼叫做頂點著色器(vertex shader),告訴GPU如何處理材質的頂點數據,還有一部分代碼叫做片元著色器(fragment shader),告訴GPU如何進行逐像素工作(individual pixels)。
- 以上GPU這部分工作會一遍遍重複執行直到完成CPU這一次渲染工作的全部指令。
什麼是視錐體?
可以看一下這篇文章:
Understanding the View Frustum文章轉自:
Unity - Optimizing graphics rendering in Unity games
推薦閱讀:
※Redshift The Brute-Force GI Engine
※Gamma
※U3D優化批處理-GPU Instancing了解一下
※Redshift Optimizations優化