• 沒有找到結果。

第三章 Shader 架構探討

3.1 Shader pipeline

Shader 是一種在計算機圖學領域中,用來執行成像任務所使用的指令,Shader 主要是應用於利用 GPU 實現三維成像的可編譯流水管線(Programmable Pipeline),

而主要流程可參考圖 3.1,可分為兩個大步驟,一個是 Vertex Shader,在這個階段,

將我們在主程式所傳入的頂點、法向量等場景物體資訊,置放在空間中,並且利 用投影矩陣以及視角矩陣將物體投影在螢幕上,即將三維座標投影成二維座標的 過程,同時這個階段也會負責深度緩衝(Z-Buffer)的計算,光柵化後進入第二 階段 Fragment Shader,這個階段,主要處理來自光柵化後的數據,針對每顆需要 處理的像素利用 GPU 的多核心處理單元(即 Shader Unit),同時進行顏色成像計 算,而在此步驟即是一種平行加速的 GPGPU 語言最初原型,最後透過 GPU 的平 行運算將結果,回傳畫面到我們的螢幕上。

圖 3.1:Shader 運作概念圖

9

3.2 為什麼要使用 Fragment Shader?

由前文提到,我們知道光線追蹤因為是根據每條光線各自獨立做追蹤的動作,

所以是非常適合做平行化處理的演算法。而 Shader 中的 Fragment Shader,是接收 來自 Vertex Shader 不同的像素,各自獨立做顏色計算,這其實就是最初的 GPGPU 語言,但除了兩者剛好一個是適合平行化的程式,另一個是可以平行化的工具的 原因之外。Fragment Shader 除了可以接收來自上一階段所得的輸入資訊之外,它 本身還有額外的三個記憶體位置:材質記憶體、常數記憶體和暫存記憶體。前者 可以想像成之於 OpenCL[SAN 10]的 Global Memory,這是屬於所有 Kernels,即 Fragment Shader 共有讀取的部分,而後兩者比較類似 Local Memory 或者 cache 是比較屬於各 Kernel 或者 Workgroup 所共有。各自比照發現,其實 Fragment Shader 可以當成一個限制比較多的 OpenCL Kernel,所以光線追蹤在上面實行,理論上 是可以達到的。但兩者還是有一些差異,比如使用 Shader 時候的時脈,並不會等 於使用 OpenCL 時候的時脈。

圖 3.2:Fragment Shader 與 OpenCL kernel 比較示意圖

左圖為 Fragment Shader 的記憶體架構,右圖為 OpenCL 的記憶體架構,兩者其實非常類似,我們 都可以找到彼此對應的記憶體空間。

10

3.3 Shader 相關硬體名詞解釋

 Shader Unit:

指的是 GPU 的核心數,即 GPU 在執行 Fragment Shader 成像時,同一時間可 以啟動幾個 Kernel 執行,通常 Shader Unit 會跟 OpenCL 或者 CUDA 的核心 數一樣多。

 Shader Clock Speed:

GPU 執行 Shader 的時脈,這裡通常不會跟執行 OpenCL 或者 CUDA 的時候 一樣時脈,通常 Shader 的時脈會略低於使用 OpenCL 或者 CUDA 的時候。

 Fill rate:

指的是 GPU 平均每秒所能填的最大像素量,以 GP/S 為其單位。我們亦可從 這裡算出平均填一顆像素所可以執行的最大浮點數量,當作為光柵化的基本 處理能力,詳細請參照第 5.2.5 節的討論。

 Processing Power:

即 GPU 處理的能力,通常以 GFLOPS 為單位。我們將利用這個數值來推導 出我們演算法平均處理一片三角形,所需要的指令數,用來說明我們的演算 法合理性。

3.4 GLSL 版本差異

OpenGL 和 GLSL 大約以 OpenGL 3.2 以及 GLSL1.4 為分水嶺[8],在這以前,

對於 OpenGL 提供了豐富的指令提供使用者傳遞參數,舉凡所需的矩陣、基本測 試模型和場景寫入記憶體的方法等等,而在 GLSL 裡面也是如此,對於由 OpenGL 所傳入的資訊只需要利用指令就可以直接運用,使用者無須再另外設定參數,然 而這樣的方式,雖然方便,可是對於一些額外的設定,還是需要使用者自行額外 去設定,其實做了一些沒必要的重覆動作,比如設定光源有光源的參數設定方法,

11

然而其實設定一個常數值,利用 Uniform 就可以傳入相關資訊了。所以在之後的 版本,將大量的指令都刪除。從這版本之後,矩陣需要自行計算,再設定為矩陣 常數值傳入 Shader;場景的讀入也非先前使用 glBegin 和 glEnd 指令,取而代之 的是利用 Vertex Array Object,分別將所需的頂點、法向量和顏色等資訊存成一條 陣列,傳入 Shader。

不過新版本也並非只有簡化指令,我們之所以選用新版的寫法,是因為對於 材質記憶體的使用方式也更加多元,過去來說,我們無法精確地抓到材質記憶體 內的浮點數內容,大多只能利用各家 GPU 各自提供的特殊指令或者模式來達到 這個工作。而新版本卻提供這個功能,可以讓我們不需要透過任何特殊硬體,去 達到抓取正確浮點數值的工作。這項功能可以使我們在 Fragment Shader 階段,可 以精確地抓取我們存於 Texture Memory 內的面、頂點等資訊。

12

相關文件