謎一樣的GPU 手機,現在已經是人手一部甚至兩部了,餐廳酒吧、地鐵巴士、馬路街邊隨處可見的低頭族大家早就見慣不怪,在飯桌上如果你發現沒有人低頭看手機的話反而會懷疑自己是不是到了外星球。 吸引人們對手機目不轉睛的自然是它顯示的內容, 相對於個人電腦剛剛問世時候只能呈現有限的文字以及低分辨率的畫面而言,現在的智慧手機已經可以在巴掌大的螢幕上做到高達3840×2160 的分辨率,能呈現非常豐富的畫面元素。
台式機和智慧手機雖然存在較大的性能分野,但是兩者間一直在互相借鑒,例如操作系統界面都採用了硬體三維加速來強化用戶體驗:豐富元素的表現力以及實現界面的視覺擴展(例如窗口的旋轉切換),而實現這些三維硬體加速的正是許多手機、電腦文章報導中的GPU,比如說Qualcomm(高通)的Adreno、蘋果的PowerVR、ARM的Mali。
因為應用上的相似性,行動端的GPU和台式機GPU發展最近這幾年幾乎都是齊頭並進,理論上如果將行動端的GPU放大後也是可以拿到台式機上使用的。
(NVIDIA推出的NV10) GPU的全稱是Graphics Processing Unit,也即是圖形處理單元的意思。這個概念的最早確定是NVIDIA(英偉達)公司在1999年發布型號為GeForce (代號NV10)的三維芯片時首次提出,當時的定義是: 三角形變換能力達到每秒一千萬個三角形以上的三維芯片。 時至今日,當年NVIDIA提出的GPU定義相信已經很少人記得,GPU這個名詞因為微軟DirectX 7採用而普及,此後NVIDIA、微軟、ATI(後來的AMD)、Intel以及幾乎整個相關行業、媒體大量採用而成為大家非常熟悉的名詞,不管是台式機、伺服器、工作站還是遊戲機、行動設備,它已經是無處不在。 相較於GPU的定義,GPU 到底是怎麼一回事,它是如何實現三維渲染以及為何後來可以勝任非圖形計算,知道的人就更少了,本文嘗試在這方面做一些簡單的介紹。 GPU到底是如何實現三維渲染呢?要了解GPU是如何進行渲染操作其實並不難,宏觀角度來可以將其簡化為下面的樣子: 應用程序->幾何處理->光柵處理 在圖形處理中,應用程序執行的相關操作包括了碰撞偵測、全局加速算法、動畫處理、物理模擬等。
幾何處理就是對圖元進行處理,所謂圖元是指點、線、面這類幾何體,而光柵化則是將確定了位置、大小和光照的幾何體映射到螢幕空間柵格化後的處理,例如像素著色、貼圖、混合。 在沒有圖形芯片(顯卡)之前,幾何處理、光柵處理都是由CPU 或者FPU(浮點單元)、SIMD (單指令多數據)單元協助來完成,隨著芯片技術的進步,其中的幾何處理、光柵處理開始逐步放到專門的芯片上執行,之後這些專用芯片又被集成到一塊,逐漸形成了現在的GPU。行動處理器同樣經歷PC這一過程,比如說高通最早的處理器MSM7225/7625就沒有集成GPU ,甚至是2D處理都是交由CPU完成。
(智慧手機與PC一樣,經歷過無GPU時代) 應用程序把需要進行三維渲染或者計算的數據和指令遞交給GPU,由GPU來執行幾何處理以及光柵處理,這樣的處理方式被稱作流水線(pipeline)。 採用流水線的方式可以將工作拆分為若干個處理環節,也就是所謂的工位(stage)或者功能階段,這些工位本身也可以繼續拆分成若干部分,也可以實現(部分的)並行化。
幾何處理階段需要做些什麼啥呢?幾何處理階段執行的是頂點、多邊形級別的處理。這一步可以拆解為5 個工位或者說5 個步驟: •對模型及視圖進行變換(transform) •頂點著色 •投影 •裁剪 •屏幕映射 模型及視圖的變換 模型變換 由於每個模型都有自己的坐標,因此在成為屏幕上的畫面對象之前,模型需要變換為多個空間或者坐標系。
作為對象的模型空間(Model Space,或者叫模型自空間)的坐標被稱作模型坐標,在經過坐標變換後,模型就會處於世界坐標或者世界空間(World Space)裡,也就是確定了該模型在場景中的方向、位置。
我們允許在場景中存在多個模型的拷貝(被稱作引用),這些大小一樣的引用可以在同一個場景中有不同的位置、方向。 視圖(Viewport,或者視口)變換 現在的實時渲染場景中包含的對象(模型)可以有很多個,但是只有被攝像機(或者說觀察者,也即是設定的視角覆蓋)的區域才會被渲染。這個攝像機在世界空間裡有一個用來擺放的位置和面向的方向。
為了實現接下來的投影、裁剪處理,攝像機和模型都需要進行視圖變換這個操作,目的是將攝像機放置在坐標原點上,使其正對的方向為Z 軸(負向),Y 軸指向上(上圖是從攝像機正上方俯視,所以沒法給出Y 軸),X 軸指向右。 頂點著色 所謂著色就是指確定光照在物料上所呈現效果的操作,這類操作既可能運行於幾何階段的模型頂點上,也可能運行於光柵階段的各個像素上,也就是所謂的頂點著色和像素著色。
在頂點著色的時候,各個頂點需要存放若干個相關的物料數據,例如頂點位置、法線、色彩以及其他任何進行著色處理計算相關的數位信息。 頂點著色的計算結果(可以是色彩、向量、紋理坐標以及任何其他著色數據)會被發送到光柵化階段進行插值處理。 投影 在完成了著色處理後,渲染系統會把可視體轉換為一個位於(-1, -1, -1)到(1, 1, 1)的單元立方體(unit-cube)中,這個立方體被稱作正則觀察體(canonical view volume),使用到的投影方式一般有兩種:平行投影和透視投影。 前一種主要在CAD 等軟體中使用,後一種因為模擬了我們人類的視覺體驗,所以在遊戲或者虛擬現實中經常使用:
上圖分別是一部iPhone 6s Plus 以平行投影和透視投影的方式呈現在螢幕上的效果。 三角形裁剪 只有在可視體內的圖元會被傳送到在屏幕上繪製這些圖元的光柵階段,在進行裁剪動作的時候,如果圖元有頂點落在可視體之外,裁剪的時候就會將可視體之外的這部分剪切掉並且在可視體與圖元相交的位置生成新的頂點,而位於立方體外部的舊圖元就會被拋棄掉。
螢幕映射 經過上一步裁剪後的位於可視體內的圖元會被傳遞到螢幕映射階段,此時的坐標信息依然是三維的。圖元的X、Y 坐標被變換到螢幕坐標系,螢幕坐標再加上Z 軸坐標就被稱作窗口坐標。
我們假定場景要渲染到一個最小角落坐標為(x1, y1)和最大角落坐標為(x2, y2)的窗口中,也就是x1 < x2,y1 < y2。此時,螢幕映射執行的是一個縮放處理後的轉換操作。Z 軸坐標並不受此操作的影響。 現在,新的x 軸、 y 軸坐標就是螢幕坐標,有對應的螢幕像素位置,不再是之前投影處理後的那個立方體所採用的映像坐標系統。 光柵處理階段要幹些什麼呢? 在獲得了經過變換和投影處理的頂點及其相關聯的著色信息後,光柵化處理階段的目的就是計算並設置好被對象覆蓋區域的像素顏色。這個處理被稱作光柵化或者掃描轉換,也就是把二維坐標上包含深度(Z 軸)信息和各種相關著色信息的頂點到螢幕上像素的轉換。
這個處理階段一般可以拆分為4 個工位: 1、三角形設定 2、三角形遍歷 3、像素著色 4、輸出合併 三角形設定 這一步會進行三角形表面的微分以及其他關於三角形表面數據的計算,計算出來的數據會被用於掃描轉換以及幾何階段所產生的各種著色數據的插值處理。在GPU上這一步會採用固定硬件功能單元來實現。 三角形遍歷 這一步用作確定像素的中心是否被三角形覆蓋,如果該像素被三角形覆蓋的話,就會生成對應的片元(fragment)。 查找哪些樣本或者像素是否位於三角形內通常被稱作三角形遍歷或者掃描轉換。 每個三角形對應片元的屬性都是由該三角形的三個頂點數據插值而成,例如片元的深度值以及來自幾何階段的著色數據。 像素著色 所有的逐像素(per-pixel)著色計算都在這一步執行,使用的輸入數據是之前插值的著色數據。像素著色發送到下一個工位的計算的結果可能是一個色彩值也可能是多個色彩值。 和三角形設定以及三角形遍歷不同採用固定硬件功能單元不同的是,現在的像素著色都是由可編程的GPU內核執行。 在像素著色所依賴的眾多技術中最為重要的就是貼圖(texturing),所謂貼圖就是把一張或者多張圖片“貼”到對像上。 輸出合併 在這一步執行的操作主要是將之前步驟生成的色彩信息進行合併形成最終輸出的像素色彩。
用於存放像素色彩信息的緩存被稱作色彩緩存,一般情況下是以紅、綠、藍三個色元的方式存放,此外還有一個用於存放像素對應深度信息值的深度緩存(一般採用Z-Buffer)。
在GPU中實現這一步的功能單元有幾種叫法,例如ROP、Output Merger 或者Back-End。 在這個階段,Output Merger 會根據深度緩存(depth buffer 或者Z-buffer)存放的深度信息判斷是否更新色彩緩存中的色彩值。 例如當前像素計算出來的深度值(例如是0.1)比深度緩存中對應像素的值小(例如是0.2),則表示當前像素的三角形比色彩緩存存放的像素所對應的三角形更靠近“攝像頭”,於是GPU會對該圖元的色彩進行計算並把新計算出來的色彩值和深度值更新到色彩緩存和深度緩存中,否則的話就不會更新當前像素的緩存。 在整個場景完成渲染後,色彩緩存中存放的都是從攝像機視角位置看到的可視圖元色彩值。 這樣處理的好處是三角形可以使用任意次序來渲染,但是如果圖元或者說三角形是部分透明的話,則必須依照從遠到近的三角形層次進行渲染。這是Z-Buffer 的主要缺點之一。 像素除了色彩緩存和深度緩存外,還有其他利用通道或者緩存的技術來用於過濾和捕捉片元(fragmet)信息。 通常和色彩一起存放於色彩緩存的阿爾法通道(Alpha Channel)包含了每個像素的相對不透明值,開發人員可以在進行深度測試之前對到來的片元先執行名為阿爾法測試(Alpha Test)的操作。如果片元的alpha 值測試(一般是等於、大於等簡單的操作)為“假”,那麼這個像素的後續處理操作就會被省略掉。這個操作通常用於確保完全透明的片元不會對Z-buffer 構成影響。 此外,還可能會涉及到名為蠟板緩存(Stencil Buffer)的技術。Stencil Buffer 作為一個離屏緩存一般用於存放已渲染圖元的位置,它通常用於進行一些特殊效果的處理,例如將一個“實心”圓存放到蠟板緩存中,之後配合其他操作,就可以將被覆蓋圖元的色彩值控制為只有在位於這個實心圓中的時候才被呈現,相當於一個遮罩的作用。
以上這些緩存都被統稱為幀緩存,但是在一般情況下,幀緩存特指色彩緩存和深度緩存。由於畫面渲染是需要時間的,為了保證出到顯示器或者顯示螢幕的時候圖元都是已經完成渲染的,人們引入了雙緩存技術,渲染中的被稱為後台緩存(back buffer),完成渲染的稱作前台緩存(front buffer),在後台緩存完成渲染後,馬上變成前台緩存,而前台緩存就切換為後台緩存,以此類推。(以上未完待續) 以上文章來自http://www.evolife.cn/html/2016/87798_5.html GPU想必大家都耳熟能想,但有些人說GPU的效能過剩,這我是不能同意的,因為圖形處理包羅萬象。你每做任何一項動作它都需要映射。這麼一來效能是遠遠的不足。不然為何HTC 的M9+所使用的GPU並沒有很高級跑大形游戲就會有跑不動的現像。這是因為圖形處理無法應付它的需求。
本文章最後由( 陳誠誼 )於 2016-7-10 15:32 編輯
|