CPU GPU設計工作原理

hemeinvyiqiluoben發表於2018-01-24

轉自:http://blog.csdn.net/claien/article/details/6965135

要說到設計的複雜程度,那還是CPU了!這個不用討論,很簡單的道理你看看顯示卡晶片的更新速度和CPU的更新速度就可見一斑了。還是簡單說說他們的設計原理吧。

CPU:

      但是,現在我要問一句:“什麼是CPU?”我相信大多數人並不知道什麼是CPU。當然,你可以回答CPU是中央處理器,或者來一句英文: Central Processing Unit。是的,沒錯。但,RISC和CISC是什麼?什麼是“9路超標量設計”、“20級流水線”?什麼是“解 碼”,為什麼Athlon和PIII的解碼過程需要的時鐘週期大大大於其他的RISC處理器?這些都不是一句“中央處理器”所能夠回答的。

一、 指令系統

要講CPU,就必須先講一下指令系統。指令系統指的是一個CPU所能夠處理的全部指令的集合,是一個CPU的根本屬性。比如我們現在所用的CPU都是 採用x86指令集的,他們都是同一型別的CPU,不管是PIII、Athlon或Joshua。我們也知道,世界上還有比PIII和Athlon快得多的 CPU,比如Alpha,但它們不是用x86指令集,不能使用數量龐大的基於x86指令集的程式,如Windows98。之所以說指令系統是一個CPU的 根本屬性,是因為指令系統決定了一個CPU能夠執行什麼樣的程式。所有采用高階語言編出的程式,都需要翻譯(編譯或解釋)成為機器語言後才能執行,這些機 器語言中所包含的就是一條條的指令。

1、 指令的格式

一條指令一般包括兩個部分:操作碼和地址碼。操作碼其實就是指令序列號,用來告訴CPU需要執行的是那一條指令。地址碼則複雜一些,主要包括源運算元地址、目的地址和下一條指令的地址。在某些指令中,地址碼可以部分或全部省略,比如一條空指令就只有操作碼而沒有地址碼。

舉個例子吧,某個指令系統的指令長度為32位,操作碼長度為8位,地址長度也為8位,且第一條指令是加,第二條指令是減。當它收到一個 “00000010000001000000000100000110”的指令時,先取出它的前8位操作碼,即00000010,分析得出這是一個減法操 作,有3個地址,分別是兩個源運算元地址和一個目的地址。於是,CPU就到記憶體地址00000100處取出被減數,到00000001處取出減數,送到 ALU中進行減法運算,然後把結果送到00000110處。

這只是一個相當簡單化的例子,實際情況要複雜的多。

2、 指令的分類與定址方式

一般說來,現在的指令系統有以下幾種型別的指令:

(1)算術邏輯運算指令

算術邏輯運算指令包括加減乘除等算術運算指令,以及與或非異或等邏輯運算指令。現在的指令系統還加入了一些十進位制運算指令以及字串運算指令等。

(2)浮點運算指令

用於對浮點數進行運算。浮點運算要大大複雜於整數運算,所以CPU中一般還會有專門負責浮點運算的浮點運算單元。現在的浮點指令中一般還加入了向量指令,用於直接對矩陣進行運算,對於現在的多媒體和3D處理很有用。

(3)位操作指令

學過C的人應該都知道C語言中有一組位操作語句,相對應的,指令系統中也有一組位操作指令,如左移一位右移一位等。對於計算機內部以二進位制不碼錶示的資料來說,這種操作是非常簡單快捷的。

(4)其他指令

上面三種都是運算型指令,除此之外還有許多非運算的其他指令。這些指令包括:資料傳送指令、堆疊操作指令、轉移類指令、輸入輸出指令和一些比較特殊的指令,如特權指令、多處理器控制指令和等待、停機、空操作等指令。

對於指令中的地址碼,也會有許多不同的定址(編址)方式,主要有直接定址,間接定址,暫存器定址,基址定址,變址定址等,某些複雜的指令系統會有幾十種甚至更多的定址方式。

3、 CISC與RISC

CISC,Complex Instruction Set Computer,複雜指令系統計算機。RISC, Reduced Instruction Set Computer,精簡指令系統計算機。雖然這兩個名詞是針對計算機的,但下文我們仍然只對指令集進行 研究。

(1)CISC的產生、發展和現狀

一開始,計算機的指令系統只有很少一些基本指令,而其他的複雜指令全靠軟體編譯時通過簡單指令的組合來實現。舉個最簡單的例子,一個a乘以b的操作就 可以轉換為a個b相加來做,這樣就用不著乘法指令了。當然,最早的指令系統就已經有乘法指令了,這是為什麼呢?因為用硬體實現乘法比加法組合來得快得多。

由於那時的計算機部件相當昂貴,而且速度很慢,為了提高速度,越來越多的複雜指令被加入了指令系統中。但是,很快又有一個問題:一個指令系統的指令數是受指令操作碼的位數所限制的,如果操作碼為8位,那麼指令數最多為256條(2的8次方)。

那麼怎麼辦呢?指令的寬度是很難增加的,聰明的設計師們又想出了一種方案:操作碼擴充套件。前面說過,操作碼的後面跟的是地址碼,而有些指令是用不著地址碼或只用少量的地址碼的。那麼,就可以把操作碼擴充套件到這些位置。

舉個簡單的例子,如果一個指令系統的操作碼為2位,那麼可以有00、01、10、11四條不同的指令。現在把11作為保留,把操作碼擴充套件到4位,那麼 就可以有00、01、10、1100、1101、1110、1111七條指令。其中1100、1101、1110、1111這四條指令的地址碼必須少兩 位。

然後,為了達到操作碼擴充套件的先決條件:減少地址碼,設計師們又動足了腦筋,發明了各種各樣的定址方式,如基址定址、相對定址等,用以最大限度的壓縮地址碼長度,為操作碼留出空間。

就這樣,慢慢地,CISC指令系統就形成了,大量的複雜指令、可變的指令長度、多種的定址方式是CISC的特點,也是CISC的缺點:因為這些都大大 增加了解碼的難度,而在現在的高速硬體發展下,複雜指令所帶來的速度提升早已不及在解碼上浪費點的時間。除了個人PC市場還在用x86指令集外,伺服器以 及更大的系統都早已不用CISC了。x86仍然存在的唯一理由就是為了相容大量的x86平臺上的軟體。

(2)RISC的產生、發展和現狀

1975年,IBM的設計師John Cocke研究了當時的IBM370CISC系統,發現其中佔總指令數僅20%的簡單指令卻在程式呼叫中佔了80%,而佔指令數80%的複雜指令卻只有20%的機會用到。由此,他提出了RISC的概念。

事實證明,RISC是成功的。80年代末,各公司的RISC CPU如雨後春筍般大量出現,佔據了大量的市場。到了90年代,x86的CPU如pentium和k5也開始使用先進的RISC核心。

RISC的最大特點是指令長度固定,指令格式種類少,定址方式種類少,大多數是簡單指令且都能在一個時鐘週期內完成,易於設計超標量與流水線,暫存器 數量多,大量操作在暫存器之間進行。由於下文所講的CPU核心大部分是講RISC核心,所以這裡就不多介紹了,對於RISC核心的設計下面會詳細談到。

RISC目前正如日中天,Intel的Itanium也將最終拋棄x86而轉向RISC結構。

二、CPU核心結構

好吧,下面來看看CPU。CPU核心主要分為兩部分:運算器和控制器。

(一) 運算器

1、 算術邏輯運算單元ALU(Arithmetic and Logic Unit)

ALU主要完成對二進位制資料的定點算術運算(加減乘除)、邏輯運算(與或非異或)以及移位操作。在某些CPU中還有專門用於處理移位操作的移位器。

通常ALU由兩個輸入端和一個輸出端。整數單元有時也稱為IEU(Integer Execution Unit)。我們通常所說的“CPU是XX位的”就是指ALU所能處理的資料的位數。

2、 浮點運算單元FPU(Floating Point Unit)

FPU主要負責浮點運算和高精度整數運算。有些FPU還具有向量運算的功能,另外一些則有專門的向量處理單元。

3、通用暫存器組

通用暫存器組是一組最快的儲存器,用來儲存參加運算的運算元和中間結果。

在通用暫存器的設計上,RISC與CISC有著很大的不同。CISC的暫存器通常很少,主要是受了當時硬體成本所限。比如x86指令集只有8個通用寄存 器。所以,CISC的CPU執行是大多數時間是在訪問儲存器中的資料,而不是暫存器中的。這就拖慢了整個系統的速度。而RISC系統往往具有非常多的通用 暫存器,並採用了重疊暫存器視窗和暫存器堆等技術使暫存器資源得到充分的利用。

對於x86指令集只支援8個通用暫存器的缺點,Intel和AMD的最新CPU都採用了一種叫做“暫存器重新命名”的技術,這種技術使x86CPU的寄 存器可以突破8個的限制,達到32個甚至更多。不過,相對於RISC來說,這種技術的暫存器操作要多出一個時鐘週期,用來對暫存器進行重新命名。

4、 專用暫存器

專用暫存器通常是一些狀態暫存器,不能通過程式改變,由CPU自己控制,表明某種狀態。

(二) 控制器

運算器只能完成運算,而控制器用於控制著整個CPU的工作。

1、 指令控制器

指令控制器是控制器中相當重要的部分,它要完成取指令、分析指令等操作,然後交給執行單元(ALU或FPU)來執行,同時還要形成下一條指令的地址。

2、 時序控制器

時序控制器的作用是為每條指令按時間順序提供控制訊號。時序控制器包括時鐘發生器和倍頻定義單元,其中時鐘發生器由石英晶體振盪器發出非常穩定的脈衝訊號,就是CPU的主頻;而倍頻定義單元則定義了CPU主頻是儲存器頻率(匯流排頻率)的幾倍。

3、 匯流排控制器

匯流排控制器主要用於控制CPU的內外部匯流排,包括地址匯流排、資料匯流排、控制匯流排等等。

4、中斷控制器

中斷控制器用於控制各種各樣的中斷請求,並根據優先順序的高低對中斷請求進行排隊,逐個交給CPU處理。

(三) CPU核心的設計

CPU的效能是由什麼決定的呢?單純的一個ALU速度在一個CPU中並不起決定性作用,因為ALU的速度都差不多。而一個CPU的效能表現的決定性因素就在於CPU核心的設計。

1、超標量(Superscalar)

既然無法大幅提高ALU的速度,有什麼替代的方法呢?並行處理的方法又一次產生了強大的作用。所謂的超標量CPU,就是隻整合了多個ALU、多個FPU、多個譯碼器和多條流水線的CPU,以並行處理的方式來提高效能。

超標量技術應該是很容易理解的,不過有一點需要注意,就是不要去管“超標量”之前的那個數字,比如“9路超標量”,不同的廠商對於這個數字有著不同的定義,更多的這只是一種商業上的宣傳手段。

2、流水線(Pipeline)

流水線是現代RISC核心的一個重要設計,它極大地提高了效能。

對於一條具體的指令執行過程,通常可以分為五個部分:取指令,指令譯碼,取運算元,運算(ALU),寫結果。其中前三步一般由指令控制器完成,後兩步 則由運算器完成。按照傳統的方式,所有指令順序執行,那麼先是指令控制器工作,完成第一條指令的前三步,然後運算器工作,完成後兩步,在指令控制器工作, 完成第二條指令的前三步,在是運算器,完成第二條指令的後兩部……很明顯,當指令控制器工作是運算器基本上在休息,而當運算器在工作時指令控制器卻在休 息,造成了相當大的資源浪費。解決方法很容易想到,當指令控制器完成了第一條指令的前三步後,直接開始第二條指令的操作,運算單元也是。這樣就形成了流水 線系統,這是一條2級流水線。

如果是一個超標量系統,假設有三個指令控制單元和兩個運算單元,那麼就可以在完成了第一條指令的取址工作後直接開始第二條指令的取址,這時第一條指令 在進行譯碼,然後第三條指令取址,第二條指令譯碼,第一條指令取運算元……這樣就是一個5級流水線。很顯然,5級流水線的平均理論速度是不用流水線的4 倍。

流水線系統最大限度地利用了CPU資源,使每個部件在每個時鐘週期都工作,大大提高了效率。但是,流水線有兩個非常大的問題:相關和轉移。

在一個流水線系統中,如果第二條指令需要用到第一條指令的結果,這種情況叫做相關。以上面哪個5級流水線為例,當第二條指令需要取運算元時,第一條指 令的運算還沒有完成,如果這時第二條指令就去取運算元,就會得到錯誤的結果。所以,這時整條流水線不得不停頓下來,等待第一條指令的完成。這是很討厭的問 題,特別是對於比較長的流水線,比如20級,這種停頓通常要損失十幾個時鐘週期。目前解決這個問題的方法是亂序執行。亂序執行的原理是在兩條相關指令中插 入不相關的指令,使整條流水線順暢。比如上面的例子中,開始執行第一條指令後直接開始執行第三條指令(假設第三條指令不相關),然後才開始執行第二條指 令,這樣當第二條指令需要取運算元時第一條指令剛好完成,而且第三條指令也快要完成了,整條流水線不會停頓。當然,流水線的阻塞現象還是不能完全避免的, 尤其是當相關指令非常多的時候。

另一個大問題是條件轉移。在上面的例子中,如果第一條指令是一個條件轉移指令,那麼系統就會不清楚下面應該執行那一條指令?這時就必須等第一條指令的 判斷結果出來才能執行第二條指令。條件轉移所造成的流水線停頓甚至比相關還要嚴重的多。所以,現在採用分支預測技術來處理轉移問題。雖然我們的程式中充滿 著分支,而且哪一條分支都是有可能的,但大多數情況下總是選擇某一分支。比如一個迴圈的末尾是一個分支,除了最後一次我們需要跳出迴圈外,其他的時候我們 總是選擇繼續迴圈這條分支。根據這些原理,分支預測技術可以在沒有得到結果之前預測下一條指令是什麼,並執行它。現在的分支預測技術能夠達到90%以上的 正確率,但是,一旦預測錯誤,CPU仍然不得不清理整條流水線並回到分支點。這將損失大量的時鐘週期。所以,進一步提高分支預測的準確率也是正在研究的一 個課題。

越是長的流水線,相關和轉移兩大問題也越嚴重,所以,流水線並不是越長越好,超標量也不是越多越好,找到一個速度與效率的平衡點才是最重要的。

三、CPU的外核

1、解碼器(Decode Unit)

這是x86CPU才有的東西,它的作用是把長度不定的x86指令轉換為長度固定的類似於RISC的指令,並交給RISC核心。解碼分為硬體解碼和微解 碼,對於簡單的x86指令只要硬體解碼即可,速度較快,而遇到複雜的x86指令則需要進行微解碼,並把它分成若干條簡單指令,速度較慢且很複雜。好在這些 複雜指令很少會用到。

Athlon也好,PIII也好,老式的CISC的x86指令集嚴重製約了他們的效能表現。

2、一級快取和二級快取(Cache)

以及快取和二級快取是為了緩解較快的CPU與較慢的儲存器之間的矛盾而產生的,以及快取通常整合在CPU核心,而二級快取則是以OnDie或OnBoard的方式以較快於儲存器的速度執行。對於一些大資料交換量的工作,CPU的Cache顯得尤為重要。

GPU:

     Graphic Processing Unit簡稱GPU距離那場革命已經5年了還記得最早由偉大的nVIDIA在1999年8月31日提出

一,GPU

GPU全稱是Graphic Processing Unit—圖形處理器,其最大的作用就是進行各種繪製計算機圖形所需的運算。包括頂點設定,光影,像 素操作等。GPU實際上是一組圖形函式的集合,而這些函式由硬體實現,主要用於處理3D遊戲中物體移動時的座標轉換及光源處理。以前,這些工作都是由 CPU配合特定的軟體來做的。GPU從某種意義上來講就是為了取代CPU在圖形處理過程中充當主角而出現的,一塊標準的GPU主要包括 2D Engine,3D Engine ,Video Processing Engine,FSAA Engine,視訊記憶體管理單元等等,其中,3D運 算中起決定作用的是3D Engine,這是現代3D顯示卡的靈魂,也是區別GPU等級的重要標誌。3D Engine在各公司的產品中都是宣傳攻勢的重點 照顧物件,名字叫的一個比一個響,像nVidia的nFinitFX系列,CineFX系列,ATI的SmoothVision系列,一個 3D Engine通常包含著T&L單元,Vertex Processing Engine,Setup Engine, Piexl Shader等

二,API

說到API,也許很多人不容易理解。在計算機行業中,所有軟體的程式介面,包括3D圖形程式介面在內,統稱為API (Application Program Interface)—應用程式介面。過去,如果您想讓它們發揮最大功效,必須做的一件事,就是記錄相關硬體 裝置的地址。現在,API已成為軟、硬體之間一種連線的橋樑,這道工序就可以省略了。顯示卡晶片廠商根據標準來設計自己的硬體產品,以達到在API呼叫硬體 資源時最優化,獲得更好的效能。有了這個橋樑,便可實現不同廠家的硬體、軟體最大範圍相容。目前PC遊戲與顯示卡之間的橋樑主要有兩個—DirecX和 OpenGL。可能會有人認為DriectX是一個專門的圖形API,其實,DirectX並不侷限於顯示領域。目前的DirectX中包含有 Direct Graphics(Direct 3D+Direct Draw)、Direct Input、Direct Play、 Direct Sound、Direct Show、Direct Setup、Direct Media Objects等多個元件,它提供了一整套的 多媒體介面方案。其中,Direct Graphics主要負責3D圖形部分

初代的DriectX並不成功,技術上也不成熟,這種情況一直持續DriectX5.0,DirectX 5版本在D3D上有很大改善,對D3D的內容做 了徹底修改,除此之外,許多應用程式介面的細節部分也得到了改進。加入了霧化效果、Alpha混合等3D特效,使3D遊戲中的空間感和真實感得以增強。因 此,DirectX發展到DirectX 5才真正走向了成熟。而真正顯現出DirectX的王者霸氣並且的版本是革命的DirectX7.0

DirectX 7.0加入了硬體幾何轉換與光源處理,及T&L技術。雖然OpenGL中已有相關技術,但此前從未在娛樂級顯示卡中出現。 T&L技術將多邊形設定,光影轉換等大計量消耗CPU運算能力的工作轉移給了GPU內的T&L單元進行,從而在一定程度上將CPU從繁重 的勞力中解放了出來

隨後的DirectX 8.0中,T&L被Shader所取代,各種Shader單元的應用帶來了圖形特效的質的飛躍,DirectX 8.0使 GPU真正成為了可程式設計的處理器。而DirectX 9.0則將各種Shader效果帶入了FLOAT運算的時代在GPU出現的以前,顯示卡和CPU的關係 有點像“主僕”,簡單的說這時的顯示卡就是畫筆,根據各種由CPU發出的指令和資料進行著色,材質的填充,渲染,輸出等等。所以較早的娛樂用3D顯示卡又稱 “3D加速卡”,由於大部分座標處理的工作及光影特效需要由CPU親自來執行,佔用了CPU太多的運算時間,從而造成整體畫面不能非常流暢地表現出來。隨 著時間的推移,CPU進行各種光影運算的速度變的越來越無法滿足遊戲開發商的要求,更多多邊形以及特效的應用壓榨光了幾乎所有的CPU效能,矛盾產生 了……如果說不堪忍受的遊戲速度催生了GPU的話,那麼為GPU準備“產床”的則是我們這個世界上唯一的軟體帝國:微軟—當矛盾接近臨界點時, DriectX7.0來了。接著,1999年8月31日,NV10(就是GeForce)誕生了伴隨著DriectX版本的變化,GPU的發展也經歷了3 個階段:

1、剪除,變形,光照—T&L以及第一代GPU

第一代GPU的最重要的特點就是在硬體級別上實現了T&L運算,其代表有:NV10/15(Geforce256/2GTS/MX),R100 (Radeon256/LE),Savage2000等,由於這一代GPU的基本工作原理相同,所以這裡我們以Geforce2GTS為例,來看看第一代 的GPU是如何工作的首先,CPU將資料傳遞給GPU進行處理,資料先進入T&L單元中的Transform Engine,在這裡,資料將以頂 點的形式接受視野範圍的判斷,當處理單元判斷某部分頂點處於觀察者的視線範圍以外時,Transform Engine將把這部分頂點“剪除”以使其不會 干擾後續的流水線操作, 具個簡單的例子:當你在某FPS遊戲中突然開啟狙擊槍的狙擊鏡,視野變成了一個圓形的空洞,而其他部分則為黑色,這時 Transform Engine將去除這個圓形視野範圍以外的所有頂點,不過,這裡進行的只是視野範圍的判斷,Transform Engine去除在 你的視線範圍內但是被其它東西擋住了的物體,另外,每一個三角形可能被旋轉,放大/縮小,上升,下降,左偏,右移等。 這就是多邊形轉換轉換。 Transform Engine根據你的視角,改變了由程式提供的組成3D物體的頂點的座標。經過Lighting Engine處理後的圖象經過判斷 處理後的資料將流入T&L單元中的Lighting Engine,根據光源的型別,距離,角度,數目,應用方式等不同引數,每一個多邊形都會有 不同的光影表現和光影關係,因而需要不同的光線函式予以表徵,在Lighting Engine中,處理單元將根據軟體提出的光源分佈情況為每個頂點計算 出它所具有的光線向量,以便後續進行的光線紋理貼圖,著色等操作

經過Lighting Engine處理的畫面

其實,經由T&L單元處理過的資料還只是抽象的資料,並不是具體的圖形,上面兩副圖僅僅是方便讀者進行想象的示意圖。

接下來資料將流入Setup Engine,在這裡,運算單元將進行三角形的設定工作,這是整個繪圖過程中最重要的一個步驟,Setup Engine甚 至直接影響著一塊GPU的執行效能。三角形的設定過程是由一個一個的多邊形組成的,或者是用更好的三角形代替原來的三角形。在三維影像中可能會有些三角形 被它前面的三角形擋住,但是在這個階段3D晶片還不知道哪些三角形會被擋住。所以三角形建立單元接收到的是一個個由三個頂點組成的完整三角形。三角形的每 個角(或頂點)都有對應的X軸、Y軸和Z軸座標值,這些座標值確定了它們在3D景物中的位置。同時,三角形的設定也確定了畫素填充的範圍

經過Setup Engine處理的畫面

最終著色完畢的畫面

在三角形設定完畢後,T&L單元的全部運算就完成了。接下來資料將進入NV15獨有的NSR畫素處理單元進行一定的畫素處理,接著流入畫素流水線 進行後續的紋理畫素填充等操作,這部分操作在DriectX7.0中的變化並不明顯,基本的渲染填充過程與過去的顯示卡幾無二異

T&L雖然再一定程度上緩解了CPU運算能力的不濟所帶來的瓶頸,使得系統在圖形方面的資源得到了再分配和增強,但同時,T&L也將新的矛盾轉到了GPU上

T&L是一組相對固定的簡單的圖形函式,所實現的特效受到了函式本身語句的限制,雖然這種固定的指令集設計可以帶來比較高的執行效率,但這種設定 使得DX7下所能實現的特效受到了指令集的約束,許多逼真的特效無法實現,程式設計師的思想也被限定在一個相對狹窄的範圍內。

2、我要看到你飄逸的秀髮和迷人的微笑—可程式設計Shader以及第二代GPU

DriectX8.0在傳統T&L的基礎上加入了兩個新的概念—可程式設計的Vertex Shader和Piexl Shader,同樣的,第二代 GPU的標誌就是硬體級別的可程式設計Shader運算,代表產品為NV2X(Geforce3/4Ti),R2XX(Radeon8500)等

可程式設計Shader的複雜程度遠非T&L可比,為了方便大家理解第二代GPU的特點,我們先來認識一下什麼是可程式設計Shader,以及可程式設計Shader運算單元

可程式設計Vertex Shader及頂點處理器:

可程式設計Vertex Shader讓程式設計師能夠對特定物體,甚至整個畫面的每一個頂點,指定特別的運算程式,卻不需要CPU介入。每一個頂點都攜帶相當多 的資訊,比如座標,重量,法線,顏色,紋理座標,霧和點大小資料。頂點處理器能夠以簡短的程式來改變上述這些資訊。 這些小程式直接由頂點著色引擎本身執 行,不必勞駕CPU。 典型的T&L引擎將程式設計師限制在3D運算的光影轉換之前, 在有了頂點處理器的支援之後,遊戲設計師對遊戲場景裡的3D物 體能夠為所欲為的操縱變化,而且不需要用到中央處理器。

這導致了一場革新,程式可以改變頂點的座標,這樣基本上改變物體的形狀,以達到更接近真實的移動、移動殘影、混色、內插(在兩種外型間轉換),以及變形, 比如改變角色臉部的骨骼和皮膚一個產生一個適時的微笑。也可改變頂點上的顏色資料和紋理座標,物體表面的顏色達到設計師所想要的色彩效果、投影、凹凸貼圖 設定(如Blinn Bump mapping)或者其它投射的紋理。光源也可以為程式設計師隨心所欲的調整,不再像過去那樣需要對光源的效果進行笨拙的光線 紋理貼圖,而這些在以前是不可想象的。這一切都歸功於可程式設計Vertex Shader和頂點處理器的出現

Blinn Bump mapping

可程式設計Piexl Shader以及畫素處理器

在NV15中,nVidia曾經嘗試加入一個叫NSR的畫素處理單元,它可以在資料進入畫素流水線之前對每個畫素進行一系列運算操作,雖然同為每畫素操 作,但NSR與Piexl Shader可不能同日而語, NSR對於畫素的運算只有7種,同T&L一樣,它依然是固定模式的,程式設計師依然要依照 規定好的條條框框寫出程式,而Piexl Shader則不同,我們可以用許多不同方式去程式設計,以實現不同的特效,下面就是一般的畫素處理器所具備的特 性:

· 陰影貼圖

· 快速紋理載入

· 影像乘法,對稱核心

· 支援4096x4096或512x512x512 紋理

· 立方體貼圖每邊可4096x4096x32-位

· 支援YUYV的紋理(自動轉換成RGB三原色)

· 支援全景貼圖

可以指向任何一個影像,如背景緩衝區(back buffer),而可直接當作紋理使用

· 邊緣色彩及邊緣紋理

· 硬體同步化讀/寫

對同一張紋理的讀及寫允許全流水線操作。

可以對背景緩衝區著色,然後馬上能當作紋理使用

· Pass through colors

· 支援DX6規格的環境凹凸/亮度貼圖(就是環境凹凸貼圖)

· 簡單的紋理,S,T 在alpha/紅(AB)及藍/綠 (BG)

· 等向的雙方向性反射分佈功能光源

· 內積產生色彩貼圖或Z座標

· 真實反射凹凸貼圖

這看起來似乎有點抽象,簡單的說,可程式設計Piexl Shader實現了一個非常重要的特效—真實的毛髮

古老街道上昏暗燈光中的狼人

在3D渲染中,渲染真實的毛髮一直是一件非常困難的事情,大量的多邊形給多邊形生成帶來了嚴峻的考驗,而每一根毛髮之間複雜多變的即時光影關係更不是幾個簡單固定的指令所能實現的。Piexl Shader的可程式設計性和運算能力很好的解決了這個問題

好啦,現在讓我們來看看第二代GPU是如何完整處理一個畫面的吧

首先,來自CPU的各種物理引數進入GPU,Vertex Shader將對頂點資料進行基本的判斷,如果沒有需要處理的Vertex效果,則頂點資料直 接進入Transform&Lighting Unit進行傳統的T&L操作以節約時間提高效率,如果需要處理各種Vertex效果,則 Vertex Shader將先對各種Vertex Programs的指令進行運算,一般的Vertex Programs中往往包含了過去轉換,剪 切,光照運算等所需要實現的效果,故經由Vertex Shader處理的效果一般不需要再進行Transform&Lighting操作;另 外,當遇到涉及到曲面鑲嵌(把曲面,比如弓形轉換成為多邊形或者三角形)的場合時,CPU可以直接將資料交給Vertex Shader進行處理

另外,在DX8.0的Transform過程中,Vertex Shader可以完成Z值的剔除,也就是Back Face Culling—陰面隱去,這就意味著除了視野以外的頂點外,視野內被前面頂點遮住的頂點也會被一併剪除,這大大減輕了需要進行操作的頂點數目

接下來,經由Vertex Shader處理完成的各種資料將流入Setup Engine,在這裡一如既往的進行三角形的設定工作,到這裡為止,Vertex Shader的工作就完成了

過去,設定好的三角形本來應該帶著各自所有的引數進入畫素流水線內進行紋理填充和渲染,但現在則不同,在填充之前我們還需要進行Piexl Shader的操作

其實Piexl Shader並非獨立存在的,它位於紋理填充單元之後,資料流入畫素流水線後先進入紋理填充單元進行紋理填充,然後便是 Piexl Shader單元,經由Piexl Shader單元進行各種處理運算之後再進入畫素填充單元進行具體的著色,再經由霧化等操作後,一個完整 的畫面就算完成了

值得注意的是,第二代GPU中普遍引入了獨立的顯示資料管理機制,他們位於Vertex Shader,Setup Engine以及畫素流水線之間,負 責資料的更有效率的傳輸、組合,各種無效值的剔除,資料的壓縮以及暫存器的管理等工作,這個單元的出現對整個GPU的工作效率的保證其到了至管重要的作 用。

HyperZ系列:HyperZ技術本身就是一種類似nVIDIA的“Z-封閉甄別”的技術,但是比nVIDIA還更進一步。它的主要功能簡單說來就是分 析在Z軸上的場景,被遮擋的就會被忽略掉,只渲染我們能看到的部分場景;然後對渲染過的Z軸場景進行壓縮處理,資料的壓縮可減少他所佔用的空間,從而在存 取Z-Buffer資料的時候可以保留更多的視訊記憶體頻寬。而且這是一種畫面質量沒有損害的壓縮演算法,並不影響畫面質量。最後一步就是把經過渲染的場景中的Z -Buffer資訊立刻清除掉,這樣就更加大了視訊記憶體頻寬的利用率。

LMA(光速視訊記憶體架構)系列:光速視訊記憶體架構採用的第一個技術是“視訊記憶體交錯控制”技術, LMA中的視訊記憶體控制器劃分成了4個獨立的視訊記憶體控制單元,每個單元最 大可以進行32bit圖形相關資料的存取工作,並且這4個單元之間以及它們和圖形處理單元之間都保持密切的通訊聯絡,並隨時協調平衡各個子單元之間的資料 流量,因此整體來看LMA的視訊記憶體控制單元還是可以進行128bit資料的儲存,但是保證了視訊記憶體頻寬的充分利用。光速視訊記憶體架構採用的第二個技術是“無損Z壓 縮演算法”。傳統的圖形晶片對於每個待渲染的圖形象素都要進行Z軸資料的讀寫工作,因此儲存這些資料的Z快取一向是消耗視訊記憶體頻寬的大戶。LMA中整合了硬體 “無損Z壓縮”單元,採用“無損Z壓縮演算法”對Z-快取資料進行4:1的完全無失真壓縮。 光速視訊記憶體架構採用的第三個技術是“Z-封閉甄別”。排除了圖象中 被遮蓋住而不可見的部分,這樣GPU就不做隱面模型構建(節省處理器的多邊形運算資源),並且渲染管線也不對隱面進行渲染(無需從幀快取中讀寫隱面資料數 據,節省渲染管線的象素和紋理生成資源並完全消滅了隱面資料對視訊記憶體頻寬的佔用)。最後,LMA還包括了4組高速Cache,對資料傳輸進行緩衝。

3、夢中的鏡花水月—可程式設計Shader2.0以及第三代GPU

當你第一次看到3Dmark03中的MotherNature時,你有沒有感覺到震撼?

更加寬泛的色彩範圍能夠使得圖形的逼真度上升,這就是Shader2.0的由來,Shader2.0的核心實際上就是以擴大指令數目以及FLOAT資料形 式的應用來提高色彩表達的精確度,而第三代GPU的Shader單元也由此而具備了高精度FLOAT色彩資料的運算能力。從一般角度來講,第三代GPU同 第二代GPU相比在基本的操作控制形式等方面並沒有本質的區別,但是由於Shader2.0更大的指令長度和指令個數,以及通用程式+子程式呼叫的程式形 式等使得第三代GPU在處理高精度的龐大指令時效率上有了明顯的提升,同時也使得第三代GPU的可程式設計性躍上了一個新的臺階

讓我們來看看第三代GPU到底有哪些改進吧

Vexter Shader部分

第三代GPU的頂點處理器部分除了一般的操作功能外還具備流程控制能力,包括迴圈,跳躍以及子程式呼叫等,這些控制指令以及更多向量(或標量)暫存器的應 用使得頂點處理器能夠以更高的效率執行Vertex Programs,提高了Vertex的處理速度。同時,加大的指令長度和指令數量使得頂點處理器的 功能得到了進一步的強化。另外,在第三代GPU中,傳統的T&L資料將完全交由頂點處理器來執行,Transform& Lighting Unit將徹底被頂點處理器“吞併”,這也是第三代GPU的一個重要特點

Piexl Shader部分

第二代GPU的Piexl Shader只能實現INT資料的運算,這勢必會帶來最終運算結果的不精確,而資料的不精確導致了顏色表現的不準確,干擾了最 終畫面的質量以及效果的表現,第三代GPU的重點改進就是運算單元和暫存器所支援的運算格式,現在Piexl Shader可以進行更高精度的FLOAT 運算和輸出,從而使得圖形的色彩顯示更加精確

暴光正確的圖象

資料精度不當而無法實現的特種暴光

另外,第三代GPU的畫素處理器每週期所能處理的材質以及指令也分別增加了數倍,這些新特性使得第三代GPU可以處理各種複雜程度的效果,營造一個更為真實的3D畫面,比如更加真實的水面效果

INT Piexl Shader所表現的水面效果

FLOAT Piexl Shader所表現的水面效果

傳統的INT無法表現寬泛的波浪效果,程式設計師害怕資料精度範圍狹窄引起的上溢或者下溢的發生而不得不在一個很小的物理引數範圍內控制漣漪水面所需的波長、 波浪的大小、移動速度以及反射和折射效果等,現在,由於資料精度的提升,畫素處理器完全可以處理一個非常寬泛的資料精度範圍,避免資料的溢位,這就使得更 加真實的水面效果得以被表現。第三代GPU的代表是NV3X系列,R3XX系列等,其中R3XX系列的基本處理方式和順序與第二代GPU在本質上基本相 同,僅僅是Vertex Shader和Piexl Shader的具體操作細節和運算精度上有些許不同,而NV3X雖然在基本原理上也與之大略相同,但 從流水線的角度來看則與完全不同,應該算是個“異類”。產生過程,只分析一下NV3X

以NV35為例:

首先,他具有8個紋理帖圖單元,但8個紋理貼圖單元並不在固定分佈於每一條Piexl流水線,而是集簇在一起,根據情況來搭配,可以是4*2、8*1。

其次,他具有12條Shader流水線,但沒有全盤採用浮點渲染流水線,而只是把12條Shader流水線中的8條做成具備浮點處理能力;不過全部12條Shader流水線都具備Fixed-Point Shader的執行能力。

另外,NV3X將流水線後部的各種渲染單元,如霧化,Alpha混合等大幅削減,使得流水線在一定程度上公用這些單元

NV30的構架組成形式基本上與之相當,只是數目上略有不同

由於這個構架並不是傳統意義上的4*2或者8*1的固定構架,我們不能象過去那樣說NV35“每個流水線具有2個紋理帖圖單元”或者“每條管線具有3個Shader流水線”……我們只能說“NV35單位週期可以完成8次左右的紋理貼圖或者12次Shader操作”

另外,由於NV3X對於Fixed-Point Shader的支援精度是FP16和FP32,同時NV3X的Shader流水線的單位Fixed- Point Shader處理精度是16位,所以當遇到32位Fixed-Point Shader資料時,能進行Fixed-Point Shader 資料處理的8條Shader流水線也會根據情況進行搭配來運算32位的Fixed-Point Shader資料

Pixel Programs往往是由多條指令構成的,不同的指令需要不同的執行時間來完成,每個畫素必須在應用在它“身上”的Pixel Shader 操作完成後才能由畫素流水線寫入到幀快取裡。故此,對於應用了Piexl Shader的畫素實際上是需要多個以上的週期才能寫入到幀快取裡,如果採用8 條完整的渲染流水線的話, 流水線後面的霧化、色彩混合等單元很多時候都會處在等待階段,這部分單元需要佔用的電晶體數量不在少數,如果這樣浪費就怪可惜 的,砍掉後其中的霧化等單元后,對整體的效能雖然有一些影響,但是卻可以把節省下來的電晶體用於加強Pixel Shader的功能和效能上來,同時可以 保證比較高的多重紋理效率,利大於弊。

簡單的,這個有點詭異的體系節省電晶體的同時能確保相對較好的Pixel Shader效能,同時還有極高的多重貼圖效能

nVidia本指望4條Pixel管線+ 12條Shader流水線的設計能夠在現在以及未來較長的一段時間的遊戲裡提供超過4條甚至8條 Pixel Pipeline顯示卡的效能。不過,實際情況卻與nVidia的初衷有些背道而馳,Shader的完美應用帶來的一個結果就是越來越好的非多 紋理光效果,傳統的多紋理貼圖才能表現的很好的光效果現在只需要進行一次貼圖或者直接使用Shader就可以達到,這使得NV3X的設計成為了空架子,實 用意義大大降低,而在單紋理處理過程中由於NV3X的後續效果單元被削減,它的渲染效能註定沒有傳統的完整流水線高,另外,由於DX9中的最終FP精度被 定義為FP24,這導致了NV3X的相對低下的FP效能。最終,本來“先進”的NV3X構架落的個整體效能低下的下場

從本質上來講,圖形資料在NV3X中的實際處理過程依然是沿著頂點處理器—Setup Engine—畫素流水線的順序進行的,這與R3XX以及所有的第二代GPU是相同的

天堂的入口—可程式設計Shader3.0,DriectX Next以及未來的GPU

在微軟剛剛公佈的Driect9.0C中,Vertex Shader和Piexl Shader已經具有了幾乎相同的能力,而在nVidia新發布的第 四代GPU—NV40中,我們發現Vertex Shader包含了4個紋理取樣器,可以使用texld指令進行查表操作, NV40可以在一個 shader pass裡完成4個紋理的讀取,這個對於通用替換貼圖而言相當的重要,有了vertex texturing功能後, vertex shader就能讀取紋理資訊直接對映到頂點上,以實現displacement mapping(位移對映)等等效果,用不同的紋理和較 少的頂點傳輸時間就能實現外形複雜、平滑的模型,這表明GPU中Vertex Shader的功能正在逐漸接近Piexl Shader。隨著GPU的發 展,未來GPU中的Vertex Shader和Piexl Shader最終將被合併成一個統一的處理單元—Intergrated Shader,兩 種處理單元將使用完全相同的語法以及指令集,Shader的統一將帶來完全不同與現在的資料執行處理方式,GPU的內部結構將發生本質的變化, Intergrated Shader帶來了更低電晶體數目的解決方案,以更少的電晶體數目來完成現在需要數億電晶體才能完成的功能,同時統一 Shader將引出類似全通用I/O介面的設計以利資源的更合理的傳輸和分配,同時,為了解決越來越龐大的資料量,虛擬視訊記憶體、無限資源訪問以及幀緩衝操作 等技術的引入也勢在必行。另外,我們在DirectX Next中還發現了整數指令集,處理器等特殊的定義,這些新穎的設計為我們勾勒出了未來GPU的輪 廓

整數指令集

在程式設計中不必在擔心指令限制是一個很大的進步,不過想使得GPU更為通用還需要更多的工作。一個需要提高的主要區域就是整數處理能力。目前基於在著色器中 處理的所有資料都是浮點,這對於大多數顯示卡操作而言是沒有問題的,不過不適合動態分支預測、非內插式視訊記憶體搜尋(如頂點緩衝的索引)等操作。在目前的GPU 中,唯一的記憶體定址就是紋理查詢,使用的也是浮點值。這樣的情況對於紋理定位而言沒有什麼問題,不過對於通用記憶體定址而言就不合適了,這裡的連續記憶體塊可 以完全彼此沒有關聯,採用內插式查詢沒有任何意義。微軟對於這樣的情況,在4.0版的Shader模型中引入了全新的、完整的整數指令集。拓撲處理器實際 上,目前的顯示卡可以在某些情況下新生成三角形,比如在用到直線以及點的時候。大多數的娛樂級顯示卡只具備對三角形進行光柵化處理的能力,這也就意味著所有的 點、線就必須轉化為三角形。點和線在最後都將以2個三角形結束,這樣就需要用到2-6個頂點(根據索引方式的不同而變化)。從本質上來說,這樣的做法是有 益處的,通過可程式設計的管線,顯示先前應該遮蔽的場景也就無需通過CPU,而可以通過微軟的“拓撲處理器”直接完成。從邏輯上來說,這個拓撲處理器和鑲嵌單 元是相互獨立的,這個處理器在兩種操作集中均可以使用。由目前的趨勢來看,未來的GPU將向著高運算能力,高精度,高通用性的方向發展,GPU在工作方式 上將越來越接近CPU,由於高通用性等CPU特性的引入,GPU可能在一定程度上替代一部分CPU在非繪圖領域的工作,也許在未來我們會看到由全GPU組 成的圖形工作站。儘管未來GPU需要面對由於這些改進而帶來得的諸多問題,尤其是通用性導致的效率低下,比如Intergrated Shader的效率 低下,但隨著時間的推移,各種問題都將會得到妥善的解決。




相關文章