只要接觸過圖像編程就必定據說過OpenGL
和DirectX
,也知道這二者之間存在着競爭關係。這二者實際上就是圖像應用編程接口,這些接口用於渲染二維或三維圖形。能夠說,這些接口架起來了上層應用程序和底層GPU的溝通橋樑。一個應用向這些接口發送渲染命令,而這些接口會依次向顯卡驅動發送渲染命令,這些顯卡驅動是真正知道如何與GPU通訊的,正式它們把OpenGL或者是DirectX的函數調用翻譯成了GPU可以識別的指令。另外,一塊顯卡除了有圖像處理單元GPU以外,還擁有本身的內存
,這個內存一般被稱爲顯存。GPU能夠在顯存中存儲任何數據,可是對於渲染而言有一些數據類型是必須的,因此通常顯存中都包含圖像緩存,深度緩存,紋理緩存,頂點緩存。
由於顯卡驅動的存在,幾乎全部的GPU均可以和OpenGL打交道,也能夠和DirectX一塊兒合做。從顯卡的角度出發,實際上它只須要和顯卡驅動打交道就能夠了。而顯卡驅動就好像一箇中介,負責和兩方溝通。所以,一個顯卡製造商爲了讓他們的顯卡能夠同時和OpenGL和DirectX合做,就必須提供支持這兩個接口的顯卡驅動。編程
在可編程渲染管線出現以前,爲了編寫着色器代碼,開發者們學習彙編語言。爲了給開發者們方便,就出現了更高級的着色器語言(Shading Language)
,常見的着色器語言有DiretX的HLSL(High Level Shading Language)
,OpenGLGLSL(OpenGL Shading Language)
以及NVIDIA的CG(C for Graphic)
。HLSL,GLSL,CG都是「高級」語言,可是這個高級其實是相對彙編語言來講的。這些語言會被編譯成爲與機器無關的彙編語言,也被成爲中間語言(Intermediate Language)
。這些中間語言會被顯卡驅動來翻譯成爲真正的機器語言,即GPU能夠理解的語言。緩存
Draw Call自己的含義很簡單,就是調用圖像編程接口,如OpenGL中glDrawElements
命令或者DirectX中的DrawIndexedPrimitive
命令,來命令GPU進行渲染的操做。一個很常見的誤區是,Draw Call中形成性能問題的元兇是GPU,認爲GPU上的狀態切換是耗時的,其實不是的,真正「拖後腿」實際上是CPU。網絡
若是沒有流水線化,那麼CPU須要等到GPU完成上一個渲染任務才能再次發送渲染指令,這種方法顯然會形成效率地下。解決的辦法也很簡單,就是使用一個命令緩衝區(Command Buffer)。命令緩衝區包含了一個隊列,由CPU添加命令,而由GPU從中讀取命令,值得注意的是,添加和讀取的過程是相互獨立的。命令緩衝區的存在是的CPU和GPU能夠相互獨立。當CPU須要渲染一些對象時,它能夠向緩衝區中添加命令,而當GPU完成了上一次渲染任務後,它從命令隊列中再取出一個命令而且執行它。
命令緩衝區中的命令有不少種類,而Draw Call是其中一種,其它命令還有改變渲染狀態等等。函數
咱們先來作一個實驗:請建立10000個小文件,每一個文件的大小爲1KB,而後把他們呢從一個文件夾複製到另外一個文件夾中。你會發現,儘管這些文件的空間總和不超過10MB,但仍是要話費很長的時間。而後你再建立一個10MB的文件,把這個文件從一個文件夾複製到另外一個文件夾中,此次複製操做所消耗的時間卻少不少!會發生這樣的現象的緣由在於,每個複製動做須要有不少額外的操做,好比分配內存,建立各類個樣的元數據,這些操做將形成不少額外的性能開銷。
渲染的過程雖然和複製一大堆文件不同,可是從感性的認知來講這兩點是有相同點的。在每一次調用Draw Call前,CPU要向GPU發送不少內容,包括數據,狀態和命令等。GPU的渲染能力是很強的,渲染200個仍是2000個三角形網絡一般沒有什麼區別,所以渲染速度每每會快於CPU提交命令的速度。若是Draw Call的數量太多,CPU就會把時間大量浪費在提交Draw Call上,形成CPU的過載。性能
一個顯然的優化想法就是把不少小的Draw Call合併成爲一個大的Draw CAll這就是批處理的思想。值得注意的是,因爲咱們須要在CPU的內存中合併網格,而合併的過程是須要消耗時間的。所以,批處理技術更加適合那些處於靜態的物體,例如不會移動的大地,石頭等,對於這些物體咱們只須要合併。學習