[英]intermittent GLSL vertex shader compile errors
我一直在編寫一個頂點着色器的間歇性錯誤,為新創建的OpenGL上下文的第一次渲染做准備。 它是通常在同一硬件上工作的相同頂點着色器。 失敗后, glGetShaderInfoLog
返回的信息日志通常顯示如下:
Vertex shader failed to compile with the following errors:
是的,這就是全部。 它發生在Windows上,包括ATI和NVidia GPU,但我主要是在ATI上進行測試。 如果我在Visual Studio調試器下運行,則可能會在glCompileShader
或隨后的glGetShaderiv
調用中檢測到訪問沖突。
我沒有看到Mac上的錯誤,但由於重現它並不總是很容易,我不能確定它不會發生。
我注意到如果我在創建上下文時不調用wglShareLists
,則錯誤消失(或者至少我不能輕易地重現它)。 我認為這意味着一些不良信息正從先前創建的(可能是先前破壞的)OpenGL上下文流向新的。 然而,我一直在修剪東西,直到沒有太多應該分享的東西:沒有紋理對象,顯示列表,VBO,PBO。 據我所知,剩下的唯一剩下的就是着色器和程序對象。
在為窗口創建OpenGL上下文之后,我大致初始化着色如下:
// Program initialization
GLint vertexShader = glCreateShader( GL_VERTEX_SHADER );
glShaderSource( vertexShader, 1, &vertexShaderSource, NULL );
glCompileShader( vertexShader );
GLint status;
glGetShaderiv( vertexShader, GL_COMPILE_STATUS, &status );
if (status == GL_TRUE)
{
GLint fragmentShader = glCreateShader( GL_FRAGMENT_SHADER );
glShaderSource( fragmentShader, 1, &fragShaderSource, NULL );
glCompileShader( fragmentShader );
glGetShaderiv( vertexShader, GL_COMPILE_STATUS, &status );
if (status == GL_TRUE)
{
GLint program = glCreateProgram();
if (program != 0)
{
glAttachShader( program, vertexShader );
glAttachShader( program, fragmentShader );
glLinkProgram( program );
glDetachShader( program, fragmentShader );
glDetachShader( program, vertexShader );
glDeleteShader( fragmentShader );
// check for link success...
}
}
}
else
{
char logBuf[1024];
glGetShaderInfoLog( vertexShader, sizeof(logBuf), NULL, (GLchar*)logBuf );
LogToFile( (char*)logBuf );
}
然后我渲染多個幀,並在某些時候清理
glDeleteProgram( program );
glDeleteShader( vertexShader );
並破壞OpenGL上下文。 稍后,我在同一窗口中創建一個新的OpenGL上下文,以相同的方式初始化它,但頂點着色器無法編譯。
如果我不渲染任何幾何體,我無法重現錯誤,但渲染單點就足夠了。
它仍然使用簡化的頂點着色器:
#version 120
void main()
{
gl_Position = ftransform();
gl_FrontColor = gl_Color;
gl_BackColor = gl_Color;
}
和一個簡化的片段着色器:
#version 120
void main()
{
gl_FragColor = gl_Color;
}
我嘗試了AMD的CodeXL OpenGL調試器,將其設置為打破錯誤。 它只是告訴我編譯失敗,我已經知道了。
失敗的OpenGL上下文是在一個窗口上,其中先前創建,成功呈現和銷毀了不同的上下文。 重新使用這樣的窗口沒有錯,是嗎? (我知道一旦你調用了SetPixelFormat
,你就無法改變窗口的像素格式。我確保每次都使用相同的像素格式。)
補充:在修剪渲染代碼時,我發現如果我注釋掉了這條線
glEnable( GL_VERTEX_PROGRAM_TWO_SIDE );
然后錯誤就消失了。 但隨着更多真實世界的渲染(例如,紋理)恢復,它似乎沒有什么區別。
添加2014年3月7日:我最終創建了一個獨立的Visual C ++項目,可以在某些情況下重現該錯誤,以便任何感興趣的人都可以嘗試: ShaderBugTest項目為了使錯誤可重現,您需要擁有Microsoft的“應用程序”驗證程序“設置為監視堆錯誤。 隨附的Read Me有更詳細的步驟來重現。
你的例子有很多GL對象的分配和釋放,但幾乎沒有錯誤檢查。
vertexShader = glCreateShader( GL_VERTEX_SHADER );
需要檢查返回值vertexShader,以確保它有效。
glGetShaderiv( vertexShader, GL_COMPILE_STATUS, &status );
您獲得此值,但不顯示您正在檢查狀態。
program = glCreateProgram();
同樣,需要在開始使用之前檢查返回值。
glAttachShader( program, vertexShader );
fragmentShader = glCreateShader( GL_FRAGMENT_SHADER );
glShaderSource( fragmentShader, 1, &fragShaderSource, NULL );
glCompileShader( fragmentShader );
您應該在將片段着色器和頂點着色器附加到程序之前創建它們。 如果出現故障,它可以減少清理工作。
glGetShaderiv( fragmentShader, GL_COMPILE_STATUS, &status );
再次,在獲取后檢查編譯狀態。 編譯失敗,但到目前為止我們還不知道哪個着色器無法編譯。 它是片段着色器還是頂點着色器。
glAttachShader( program, fragmentShader );
glDeleteShader( fragmentShader );
在這里刪除着色器很奇怪。 是的,它應該只被標記為刪除,因為它實際上附加到程序,但這似乎仍然是一種危險的方式。 此外,由於沒有明顯的原因,您采用了不同的方法來管理片段着色器而不是頂點着色器。
glLinkProgram( program );
glDetachShader( program, fragmentShader );
glDetachShader( program, vertexShader );
同樣,對我來說,這對着色器管理來說是一種莫名其妙的方法。 再次,類似地處理片段着色器和頂點着色器。
glDeleteProgram( program );
glDeleteShader( vertexShader );
為什么片段着色器的處理方式不同?
當您正在診斷問題時,您應該使用glGetError()
並在每次GL調用后報告任何異常情況時停止程序,以便您可以隔離第一個錯誤發生的位置。 編譯失敗完全有可能是之前發生的事情的級聯效應。
使用glGetShaderInfoLog查看編譯錯誤消息。 有關示例,請參閱http://www.opengl.org/wiki/Shader_Compilation#Shader_error_handling
看起來你沒有給gl_Color
寫任何東西。
gl_Color
屬性可以表示不同地方的不同事物。
在頂點着色器中, gl_Color
表示用戶使用glColor*
或glColorPointer
調用傳遞的每頂點顏色屬性。
在片段着色器中, gl_Color
表示正在渲染的三角形的面對的插值顏色。
但是,這是一個固定的管道功能, gl_Color
在現代OpenGL中已被棄用。 這可能是您的錯誤背后的原因。 您需要使用以下代碼獲取編譯器錯誤消息:
GLint SuccessFlag = 0;
GLsizei Length = 0;
GLsizei MaxLength = 0;
glGetShaderiv( ShaderID, GL_COMPILE_STATUS, &SuccessFlag );
glGetShaderiv( ShaderID, GL_INFO_LOG_LENGTH, &MaxLength );
char* Log = ( char* )alloca( MaxLength );
glGetShaderInfoLog( ShaderID, MaxLength, &Length, Log );
將日志添加到您的問題將有助於更好地診斷您的問題。
你用的是什么版本的OpenGL? 它是核心還是兼容性配置文件?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.