如何在shader中避免使用if else

? ? ? ?今天和同事討論GPU如何實現(xiàn)求導(求偏導),過程中又學習了一下GPU的工作模式。然后發(fā)現(xiàn)了我以前的一個誤解:我以前以為shader中動態(tài)分支會造成性能損失50%,其實這只是一個估計值。實際情況下,GPU性能最壞情況是無分支的1/8 (N卡GTX480以上為1/16),而最好情況也只是無分支的7/8 (N卡GTX480以上為15/16),各種情況取平均值大概是 1/2 。
? ? ? ?首先補充一下GPU中分支語句的種類。GPU中一共有三種分支語句,第一種是 #if #else,由宏來實現(xiàn),被稱作靜態(tài)分支,在編譯期決定,沒有性能損失;第二種是if else語句,但是if條件中僅有uniform變量和常量組成,在運行期相當于?#if #else,也沒有運行期損失(但是驅(qū)動判斷static uniform branch有輕微消耗);第三種就是真正的if else語句,也就是動態(tài)分支。
? ? ? ?先舉一個簡單的例子,來說明去除動態(tài)分支的方法吧。

可以被優(yōu)化成:

如果使用HLSL,則應(yīng)用?
step
?函數(shù)取代GLSL中的?sign
?函數(shù)
? ? ? ?
對于代碼:

則可以優(yōu)化成:

? ? ? ?通過這兩個例子,大概可以看出來目的了。這種優(yōu)化的實質(zhì),就是分支合并,手工計算了所以分支的情況,再只取有用的部分。這種優(yōu)化只會在分支部分損耗加倍,不會造成老舊GPU那樣整個shader性能折半的情況。
? ? ? ?接下來列舉一些常用的優(yōu)化分支函數(shù)。
常用關(guān)系運算符優(yōu)化

常用邏輯運算符優(yōu)化

給浮點數(shù)求余數(shù),HLSL應(yīng)使用?
fmod
?函數(shù);GLSL應(yīng)使用?modf
?函數(shù),且只有openGL 3.x/openGL ES 3.x 中才能使用