2013-07-25 34 views
5

蘋果公司表示,在他們的最佳實踐爲着色器avoid branching,並在着色器內的計算值特別分支。所以我用內置的clamp()函數替換了一些if語句。我的問題是,是clamp()min(),和max()可能是更有效的,或者是它們僅僅方便(即宏)功能,簡單地擴展到if塊?爲條件語句OpenGL ES的最佳做法,如果可能的話

我知道答案可能是執行相關的。無論如何,這些函數顯然更清晰並且表達了意圖,編譯器可能會用做些事情。

+2

我覺得你的最後一句話已經回答了它相當不錯。除了看起來更精簡以外,它們至少更有可能通過快速硬件指令來實現,而不是簡單的「if」。除了這個一般的建議(儘管應該已經足夠了),實際上它們很可能使用特殊的硬件指令或條件賦值,而不僅僅是包含「if」的函數。 –

回答

9

從歷史上看,GPU支持每片段指令(如MINMAX)的時間長於支持任意條件分支的時間。在桌面OpenGL這樣的一個例子是GL_ARB_fragment_program擴展(現在GLSL取代),其中明確指出它不支持分支,但它確實提供了MINMAX指令以及其他一些條件指令。

我很肯定所有的GPU都會爲這些操作提供專用硬件,因爲常見的min(),max()clamp()都在着色器中。規範並不保證這一點,因爲一個實現可以優化代碼,但它看起來合適,但在現實世界中,您應該使用GLSL的內置函數而不是自己滾動。

如果正在使用您的條件,以避免大量的額外片段處理的唯一例外是。在某個時候,分支的成本將低於運行分支中所有代碼的成本,但這裏的平衡將非常依賴於硬件,您必須進行基準測試,以查看它是否對您的應用程序有幫助目標硬件。這裏的那種東西我的意思是:

void main() { 
    vec3 N = ...; 
    vec3 L = ...; 
    float NDotL = dot(N, L); 
    if (NDotL > 0.0) 
    { 
     // Lots of very intensive code for an awesome shadowing algorithm that we 
     // want to avoid wasting time on if the fragment is facing away from the light 
    } 
} 

只是夾緊NDotL到0-1,然後一直在處理每一個片段的陰影碼只能由NDotL通過最終的陰影項被乘以了很多無用功,如果NDotL的本來是< = 0,理論上我們可以避免這個分支的開銷。這種事情並不總是表現勝利的原因是它非常依賴硬件如何實現着色器分支。

+0

優秀的評論。我應該已經意識到'MIN'和'MAX'早於一般的if塊,我相信你對硬件支持是正確的。非常感謝! –

+0

我認爲應該提及的是,一些GPU不尊重標準,甚至根本不實施分支。我偶然發現的只有三星的Galaxy Tab系列。他們只是無聲無息地死亡,沒有任何消息。 –