1. 程式人生 > 其它 >第3章-圖形處理單元-3.3-可程式設計著色器階段

第3章-圖形處理單元-3.3-可程式設計著色器階段

《實時渲染》第四版中翻,第3.3節。

3.3 可程式設計著色器階段

現代著色器程式使用統一的著色器設計。這意味著頂點、畫素、幾何和曲面細分相關的著色器共享一個通用的程式設計模型。在內部,它們具有相同的指令集架構(ISA)。實現此模型的處理器在DirectX中稱為通用著色器核心,具有此類核心的 GPU被稱為具有統一著色器架構。這種架構背後的想法是著色器處理器可用於各種角色,GPU可以根據需要分配這些角色。例如,與由兩個三角形組成的大正方形相比,具有小三角形的一組網格需要更多的頂點著色器處理。具有單獨的頂點和畫素著色器核心池的GPU意味著保持所有核心忙碌的理想工作分配是嚴格預先確定的。使用統一的著色器核心,GPU可以決定如何平衡此負載。

描述整個著色器程式設計模型遠遠超出了本書的範圍,並且有許多文件、書籍和網站已經這樣做了。著色器使用類似C的著色語言進行程式設計,例如DirectX的高階著色語言(HLSL)和OpenGL著色語言 (GLSL)。DirectX的HLSL可以編譯為虛擬機器位元組碼,也稱為中間語言(IL或DXIL),以提供硬體獨立性。"中間"表示還可以允許離線編譯和儲存著色器程式。該中間語言由驅動程式轉換為特定GPU的ISA。控制檯程式設計通常會避免中間語言步驟,因為系統只有一個ISA。

基本資料型別是32位單精度浮點標量和向量,儘管向量只是著色器程式碼的一部分,並且如上所述不受硬體支援。在現代 GPU上,本機也支援32位整數和64位浮點數。浮點向量通常包含位置(xyzw)、法線、矩陣行、顏色(rgba)或紋理座標 (uvwq)等資料。整數最常用於表示計數器、索引或位掩碼。還支援聚合資料型別,例如結構體、陣列和矩陣。

繪製命令呼叫圖形API來繪製一組圖元,從而使得圖形管線執行並執行其著色器。每個可程式設計著色器階段都有兩種型別的輸入:統一(uniform)輸入,其值在整個繪製呼叫期間保持不變(但可以在繪製呼叫之間更改),以及變化(varying)的輸入,來自三角形頂點或光柵化的資料。例如,畫素著色器可以將光源的顏色作為統一(uniform)值提供,並且三角形表面的位置每個畫素都會發生變化,因此也會發生變化。紋理是一種特殊的統一(uniform)輸入,曾經是應用於表面的彩色影象,但現在可以將其視為任何大型資料陣列。

底層虛擬機器為不同型別的輸入和輸出提供特殊暫存器。用於uniform的可用常量暫存器的數量遠大於可用於varying輸入或輸出的那些暫存器。發生這種情況是因為需要為每個頂點或畫素單獨儲存不同的輸入和輸出,因此需要多少個自然是有限制的。uniform輸入儲存一次,並在繪製呼叫中的所有頂點或畫素中重複使用。虛擬機器還具有通用臨時暫存器,用於暫存空間。所有型別的暫存器都可以使用臨時暫存器中的整數值進行陣列索引。著色器虛擬機器的輸入和輸出如圖3.3所示。

圖3.3. 統一虛擬機器架構和暫存器佈局,Shader Model 4.0下。最大可用數量顯示在每個資源旁邊。由斜槓分隔的三個數字表示頂點、幾何和畫素著色器的限制(從左到右)。

圖形計算中常見的操作可以在現代GPU上高效執行。著色語言通過諸如\(*\)\(+\)之類的運算子支援了這些操作中最常見的操作(例如加法和乘法)。還有其他的內部函式介面,例如\(atan()\)\(sqrt()\)\(log()\)和許多其他為GPU優化的函式。還存在用於更復雜操作的函式,例如向量歸一化和反射、叉積以及矩陣轉置和行列式計算。

“流控制”這個術語是指使用分支指令來改變程式碼執行的流程。與流控制相關的指令用於實現高階語言結構,例如“if”和“case”語句,以及各種型別的迴圈。著色器支援兩種型別的流控制。靜態流控制分支基於統一輸入的值。這意味著程式碼流在繪製呼叫中是恆定的。靜態流控制的主要好處是允許在各種不同情況下使用相同的著色器(例如,不同數量的燈光)。沒有執行緒發散,因為所有呼叫都採用相同的程式碼路徑。動態流控制基於不同輸入的值,這意味著每個片元可以不同地執行程式碼。這比靜態流控制強大得多,但會降低效能,特別是如果程式碼流在著色器呼叫之間發生不規律變化。