2013-10-27 37 views
1

該着色器程序在Radeon 3450M,GT 550Ti,GT430等上運行正常,但在Intel HD4000上運行失敗。任何想法可能是錯誤的,或建議使着色器更友好?GLSL着色器程序無法在Intel HD4000上運行

頂點着色器:

uniform mat4 uniform_Projection; 
attribute vec4 attribute_Position; 
attribute vec4 attribute_Color; 
varying vec4 varying_Color; 
vec4 varying_Color_Bak; 

void main(void) 
{ 
    varying_Color.x = clamp(abs((attribute_Position.x + 3.0f)/5.0f), 0.1f, 1.0f); 
    varying_Color.y = clamp(abs((attribute_Position.y + 3.0f)/5.0f), 0.1f, 1.0f); 
    varying_Color.z = 0.0f;//clamp(abs((attribute_Position.x + attribute_Position.y + 4.0f)/7.0f), 0.1f, 1.0f); 
    varying_Color.w = 0.9f; 
    gl_Position = uniform_Projection * attribute_Position; 
} 

片段着色器:

uniform mat4 uniform_Projection; 
varying vec4 varying_Color; 
vec4 varying_Color_Bak; 
void main (void) 
{ 
    varying_Color_Bak = varying_Color; 
    varying_Color = uniform_Projection * varying_Color; 
    for (int i = 0; i < 3; i++) { 
     varying_Color = sin(varying_Color); 
     varying_Color = inversesqrt(abs(varying_Color)); 
     varying_Color = abs(log(varying_Color)); 
    } 
    varying_Color = clamp(varying_Color, 0.1f, 1.0f); 
    varying_Color = mix(varying_Color, varying_Color_Bak, 0.9f); 
    gl_FragColor = sin(varying_Color); 
} 
+1

如果你在'glGetProgramInfoLog(...)','glGetShaderInfoLog(...)'等等的輸出中包含任何錯誤代碼,它將會有所幫助。它可能就像着色器編譯器在'f'上窒息一樣簡單,後綴,因爲直到最近單精度浮點纔是唯一的精度,'f'實際上在一些stupider GLSL編譯器中產生了解析錯誤。您正在處理GLSL 130之前的語法,所以我必須假設您的目標是一個非常古老的GLSL編譯器 - 您也可以剝去精度後綴以實現可移植性。 –

+0

謝謝,我將一些日誌記錄添加到了我的應用程序的下一個版本中,但我想確保在發佈下一個版本之前,我已經避免了最明顯的可移植性問題。我會嘗試刪除'f'後綴。 – Ags1

+0

@ Ags1:理想情況下不應該有任何問題。按照GLSL規範添加後綴是完全有效的。如果GLSL編譯器對此抱怨,應考慮向英特爾提交錯誤報告以幫助改進其驅動程序。我不同意Andon的看法,你可能使用的是舊編譯器,因爲Ivy Bridge CPU需要最新的驅動程序才能運行,因此會帶來相當新的GLSL編譯器。另外,我不知道在Sandy Bridge CPU上有這樣的事情 - 至少在Linux上。 – thokra

回答

3

的一件事,你可以做,使這種便攜式的是添加#version 120着色器的頂部。正如評論中所討論的那樣,可選的f浮點精度後綴是GLSL 1.2的補充。在GLSL 1.1中,規範不包含此內容,嚴格符合的編譯器如果在GLSL 1.1着色器中遇到此錯誤,則會發出解析錯誤。

這裏的根本問題是,如果你不包括着色器的頂部#version指令,符合GLSL的編譯器應該承擔着色器對GLSL 1.1規範編寫的。許多編譯器會放鬆這些規則,並且您可以使用GLSL 1.1中不存在的語法,而不用提出警告,但其他語言則非常嚴格。如果沒有辦法提示GLSL編譯器的實現在其警告中更加冗長,那麼您需要熟悉自己的GLSL版本之間的區別。 ANGLE項目提供了一個可移植的着色器驗證器(大多數WebGL實現都使用這個驗證器),但是它的目標是OpenGL ES 2.0的GLSL版本,並且在這裏對你沒有幫助。

着色器中的其他內容似乎對GLSL 1.1有效。這裏傳達的信息是,GLSL着色器頂部的#version指令比您想象的要重要得多。也就是說,這是非常難以診斷着色問題,如果你不讀的glGetShaderInfoLog (...)glGetProgramInfoLog (...)輸出 - 每個實現都有不同的詳細程度,但他們一般都產生東西有用在編譯/鏈路故障;)

2

謝謝大家的建議。我花了一段時間纔得到測試人員的反饋,但最終我的程序在英特爾HD4000上運行,而沒有在其他平臺上打破該程序。

我製成幾乎沒有任何變化,頂點着色器:我刪除「F」改性劑

#version 120 

uniform mat4 uniform_Projection; 
attribute vec4 attribute_Position; 
attribute vec4 attribute_Color; 
varying vec4 varying_Color; 

void main(void) 
{ 
    varying_Color.x = clamp(abs((attribute_Position.x + 3.0)/5.0), 0.1, 1.0); 
    varying_Color.y = clamp(abs((attribute_Position.y + 3.0)/5.0), 0.1, 1.0); 
    varying_Color.z = 0.0;//clamp(abs((attribute_Position.x + attribute_Position.y + 4.0)/7.0), 0.1, 1.0); 
    varying_Color.w = 0.9; 
    gl_Position = uniform_Projection * attribute_Position; 
} 

,增加了一個語言版本,並去除未使用的變量聲明。

我進行更多的更改到片段着色器:

#version 120 

uniform mat4 uniform_Projection; 
varying vec4 varying_Color; 
void main (void) 
{ 
    vec4 varying_Color_Bak; 
    vec4 varying_Color_2; 
    varying_Color_Bak = varying_Color; 
    varying_Color_2 = uniform_Projection * varying_Color; 
    for (int i = 0; i < 3; i++) { 
     varying_Color_2 = sin(varying_Color_2); 
     varying_Color_2 = inversesqrt(abs(varying_Color_2)); 
     varying_Color_2 = abs(log(varying_Color_2)); 
    } 
    varying_Color_2 = clamp(varying_Color_2, 0.1, 1.0); 
    varying_Color_2 = mix(varying_Color_2, varying_Color_Bak, 0.9); 
    gl_FragColor = sin(varying_Color_2); 
} 
從重複全部來自頂點着色器的變化

之外,我還複製了varying_Color值的局部變量。這解決了HD4000上的錯誤,即英特爾芯片不允許片段着色器修改變化。

我還發現,如果我宣佈我的局部變量(varying_Color_bakvarying_Color_2)以外的main()我用我的NVidia GT430在Linux上崩潰。但一切似乎運行穩定與main()內聲明的局部變量。