2

我在片段着色器下面的代碼:爲什麼下面會拖累片段着色器(Open GL的ES 2.0)的性能

precision lowp float; 

varying vec2 v_texCoord; 
uniform sampler2D s_texture; 

uniform bool color_tint; 
uniform float color_tint_amount; 
uniform vec4 color_tint_color; 

void main(){ 
    float gradDistance; 
    vec4 texColor, gradColor; 
    texColor = texture2D(s_texture, v_texCoord); 
    if (color_tint){ 
     gradColor = color_tint_color; 
     gradColor.a = texColor.a; 
     texColor = gradColor * color_tint_amount + texColor * (1.0 - color_tint_amount); 
    } 
    gl_FragColor = texColor; 
} 

的代碼工作正常,但有趣的是,即使所有color_tint我傳入的是錯誤的,上面的代碼仍然會導致性能嚴重拖累。當與之比較時:

void main(){ 
    float gradDistance; 
    vec4 texColor, gradColor; 
    texColor = texture2D(s_texture, v_texCoord); 
    if (false){ 
     gradColor = color_tint_color; 
     gradColor.a = texColor.a; 
     texColor = gradColor * color_tint_amount + texColor * (1.0 - color_tint_amount); 
    } 
    gl_FragColor = texColor; 
} 

哪個後者可以達到40+ fps,而第一個是約18 fps。我加倍檢查,所有在第一個傳遞的color_tint都是錯誤的,所以塊不應該執行。

順便說一句,我使用GLES20在Android 2.2編程上述。

任何專家都可以知道着色器出了什麼問題嗎?

回答

6

我不是片段着色器的專家,但我認爲第二個將會更快,因爲整個if語句可以在編譯時刪除,因爲它從來都不是真的。在第一個中,它不能說明color_tint直到運行時才總是爲假,因此每次都需要檢查該分支。分支可能很昂貴,特別是在通常爲可預測的串行編程設計的圖形硬件上。

我建議你嘗試重寫它是無枝的 - 達倫的回答在這方面有一些很好的建議。

+0

謝謝。我做了另一個測試,發現分支非常昂貴:甚至比幾個距離()計算還要重。 – xandy 2011-05-05 00:41:31

6

分支在片段着色器上非常慢,如果可能的話避免它們。使用color_tint_amount 0爲無色。預先乘以color_tint_color並保存每個像素的乘積。使color_tint_amount = 1.0 - color_tint_amount。 (所以現在1.0意味着沒有gradColor)這些着色器每秒運行數百萬次,你必須保存每一個循環。

+0

感謝您的提示。但我不明白爲什麼兩個代碼中的if()不會被執行(因爲我在color_tint中傳遞了false),後面的代碼比第一個更快? – xandy 2011-05-04 06:09:16

+1

因爲在第一種情況下,仍然必須執行if()語句來評估表達式。另一個解決方案是簡單地有2個不同的片段着色器,一個應用色彩,一個不着色。例如,這是2D硬件加速管道在Android 3.0中執行的操作。 – 2011-05-04 06:20:15

+0

@Romain,看起來不同的着色器是最好的解決方案。謝謝。 – xandy 2011-05-05 00:44:03

相關問題