在渲染工作的一幀中,CPU與GPU都做了些什么?
針對渲染導致的性能問題,這個世界上是沒有一套萬能的解決方案的。渲染的性能問題涉及到許多因素,不僅僅是游戲本身,它也很大程度上取決于運行游戲的硬件和操作系統(tǒng)。重要的是我們要通過不斷的研究和實驗來解決這些性能問題。
知道了渲染工作的流程以及階段可以幫我們更好的研究和解決渲染方面的性能問題。這篇文章主要是介紹在渲染工作的一幀中,我們的CPU與GPU都做了些什么?
我們這里提到的 Object 指我們游戲中會被渲染的對象,任何掛有渲染組件 (Renderer Component) 的 GameObject 都將被引擎作為 Object 進行渲染。
基本上,渲染工作可以分解為以下步驟:
① 中央處理器(CPU)進行準備工作,比如哪些對象要被繪制,需要如何被繪制。
② CPU向圖形處理器(GPU)發(fā)送指示。
③ GPU根據(jù)CPU的指示進行圖形的繪制。
接下來我們會針對這些步驟進行更詳細的研究,這里主要是說明一下在渲染工作中CPU與GPU所扮演的角色。
渲染工作我們也常稱之為渲染管線。

在每一幀的渲染流程中, CPU 主要做了這些事:
① 確認場景中哪些對象需要被渲染,一個object只要在符合特定的規(guī)則才會被渲染。例如,當處于相機的視錐體內(nèi)的對象可以被渲染,而超出(不在視錐體內(nèi))的部分則被剔除(Culled),不進行渲染。
② CPU會收集這些將要被渲染的每一個對象的數(shù)據(jù),并且整合成指令,即我們常說的Draw Calls。一個Draw Call包含一個單獨的網(wǎng)格(mesh)數(shù)據(jù)和它將如何進行渲染的信息。比如,需要對材質(zhì)使用哪些貼圖等。在某些情況下,使用相同的設置的object數(shù)據(jù)會被合并進一個Draw Call。將不同的object數(shù)據(jù)合并到一個Draw Call的行為我們稱之為 合批(Batching)。
③ CPU會為每一個Draw Call創(chuàng)建一個數(shù)據(jù)包叫做 batch,然而,batch中包含的數(shù)據(jù)不僅僅是draw call,還有一些數(shù)據(jù)由于與我們探討的渲染性能問題無關,因此就不在這里展開。
一旦完成了batch工作,CPU接著會進行如下工作:
④ 發(fā)送一條指令給到GPU變更渲染狀態(tài)(Render State)。這個指令我們稱為 SetPass Call。SetPass Call的作用是告訴GPU在渲染下一個材質(zhì)的時候該使用哪一種設置。SetPass Call僅當從前一個材質(zhì)到下一個材質(zhì)確實需要變更渲染狀態(tài)的情況下CPU才會發(fā)出。
⑤ CPU發(fā)送一條Draw Call指令給到GPU。Draw Call指示GPU按照SetPass Call定義的設置來對具體的材質(zhì)進行渲染。
⑥ 某種情況下,你的batch可能包含不止一個渲染通道(pass),這取決于你的 shader 代碼中pass的代碼塊,一個pass代碼塊就需要GPU變更一次渲染狀態(tài)。所以,一個batch中每多包含一個pass,CPU就要新發(fā)送一次SetPass Call到GPU,然后再把Draw Call發(fā)送一次到GPU。
與此同時, GPU 會進行如下工作:
① GPU按照CPU的要求完成渲染任務。
② 如果當前任務是一個SetPass Call,那么GPU會變更當前的渲染狀態(tài)(Render State)。
③ 如果當前任務是一個Draw Call, GPU就渲染指定的材質(zhì)。這部分工作是分階段進行,由shader 代碼中不同的部分決定。這部分比較復雜,在這里不進行詳述,感興趣的朋友可以去看一下《Unity Shader 入門精要》這本書,對于入門shader的同學比較有用,推薦一下。我們這里只需要知道shader中有一部分代碼叫做頂點著色器(vertex shader),告訴GPU如何處理材質(zhì)的頂點數(shù)據(jù),還有一部分代碼叫做片元著色器(fragment shader),告訴GPU如何進行逐像素工作(individual pixels)。
④ 以上GPU這部分工作會一遍遍重復執(zhí)行直到完成CPU這一次渲染工作的全部指令。
那么現(xiàn)在大家懂了CPU 與 GPU 如何分工了嗎?
知道了渲染工作的流程以及階段可以幫我們更好的研究和解決渲染方面的性能問題。這篇文章主要是介紹在渲染工作的一幀中,我們的CPU與GPU都做了些什么?
我們這里提到的 Object 指我們游戲中會被渲染的對象,任何掛有渲染組件 (Renderer Component) 的 GameObject 都將被引擎作為 Object 進行渲染。
基本上,渲染工作可以分解為以下步驟:
① 中央處理器(CPU)進行準備工作,比如哪些對象要被繪制,需要如何被繪制。
② CPU向圖形處理器(GPU)發(fā)送指示。
③ GPU根據(jù)CPU的指示進行圖形的繪制。
接下來我們會針對這些步驟進行更詳細的研究,這里主要是說明一下在渲染工作中CPU與GPU所扮演的角色。
渲染工作我們也常稱之為渲染管線。

在每一幀的渲染流程中, CPU 主要做了這些事:
① 確認場景中哪些對象需要被渲染,一個object只要在符合特定的規(guī)則才會被渲染。例如,當處于相機的視錐體內(nèi)的對象可以被渲染,而超出(不在視錐體內(nèi))的部分則被剔除(Culled),不進行渲染。
② CPU會收集這些將要被渲染的每一個對象的數(shù)據(jù),并且整合成指令,即我們常說的Draw Calls。一個Draw Call包含一個單獨的網(wǎng)格(mesh)數(shù)據(jù)和它將如何進行渲染的信息。比如,需要對材質(zhì)使用哪些貼圖等。在某些情況下,使用相同的設置的object數(shù)據(jù)會被合并進一個Draw Call。將不同的object數(shù)據(jù)合并到一個Draw Call的行為我們稱之為 合批(Batching)。
③ CPU會為每一個Draw Call創(chuàng)建一個數(shù)據(jù)包叫做 batch,然而,batch中包含的數(shù)據(jù)不僅僅是draw call,還有一些數(shù)據(jù)由于與我們探討的渲染性能問題無關,因此就不在這里展開。
一旦完成了batch工作,CPU接著會進行如下工作:
④ 發(fā)送一條指令給到GPU變更渲染狀態(tài)(Render State)。這個指令我們稱為 SetPass Call。SetPass Call的作用是告訴GPU在渲染下一個材質(zhì)的時候該使用哪一種設置。SetPass Call僅當從前一個材質(zhì)到下一個材質(zhì)確實需要變更渲染狀態(tài)的情況下CPU才會發(fā)出。
⑤ CPU發(fā)送一條Draw Call指令給到GPU。Draw Call指示GPU按照SetPass Call定義的設置來對具體的材質(zhì)進行渲染。
⑥ 某種情況下,你的batch可能包含不止一個渲染通道(pass),這取決于你的 shader 代碼中pass的代碼塊,一個pass代碼塊就需要GPU變更一次渲染狀態(tài)。所以,一個batch中每多包含一個pass,CPU就要新發(fā)送一次SetPass Call到GPU,然后再把Draw Call發(fā)送一次到GPU。
與此同時, GPU 會進行如下工作:
① GPU按照CPU的要求完成渲染任務。
② 如果當前任務是一個SetPass Call,那么GPU會變更當前的渲染狀態(tài)(Render State)。
③ 如果當前任務是一個Draw Call, GPU就渲染指定的材質(zhì)。這部分工作是分階段進行,由shader 代碼中不同的部分決定。這部分比較復雜,在這里不進行詳述,感興趣的朋友可以去看一下《Unity Shader 入門精要》這本書,對于入門shader的同學比較有用,推薦一下。我們這里只需要知道shader中有一部分代碼叫做頂點著色器(vertex shader),告訴GPU如何處理材質(zhì)的頂點數(shù)據(jù),還有一部分代碼叫做片元著色器(fragment shader),告訴GPU如何進行逐像素工作(individual pixels)。
④ 以上GPU這部分工作會一遍遍重復執(zhí)行直到完成CPU這一次渲染工作的全部指令。
那么現(xiàn)在大家懂了CPU 與 GPU 如何分工了嗎?