微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

间歇性GLSL顶点着色器编译错误

我一直在编译一个顶点着色器的间歇性错误,准备第一次渲染一个新创build的OpenGL上下文。 这是相同的顶点着色器,通常在同一个硬件上工作。 失败之后, glGetShaderInfoLog返回的信息日志通常显示如下:

Vertex shader Failed to compile with the following errors:

是的,就是这样。 它发生在Windows上,同时拥有ATI和NVidia GPU,不过我大部分都是在ATI上进行testing。 如果我在Visual Studiodebugging器下运行,可能会在glCompileShader或随后的glGetShaderiv调用中检测到访问冲突。

我没有看到Mac上的错误,但由于重现它并不总是很容易,我不能确定它不会发生。

我注意到,如果我在创build我的上下文时不打电话给wglShareLists ,错误就会消失(至less我不能轻易再现)。 我认为这意味着一些不好的信息正在从之前创build的(也许以前被破坏的)OpenGL上下文stream向新的。 然而,我一直在调整的东西,直到没有太多应该共享:没有纹理对象,显示列表,维也纳组织,公益组织。 就我所知,剩下的唯一东西就是着色器和程序对象。

如何通过Idispatch公开COM函数的服务器可以区分不同的客户端调用函数而不传递任何ID参数?

获取点击鼠标button的窗口句柄

检测何时卸载模块(DLL)

当Visual Studio停止debugging时,我真的不能清理吗?

如何使用Application Verifier在我的代码中find真正的问题行?

在为窗口创build一个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,&fragShaderSource,NULL ); glCompileShader( fragmentShader ); glGetShaderiv( vertexShader,&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上下文。 后来,我在同一个窗口中创build了一个新的OpenGL上下文,以相同的方式初始化它,但顶点着色器无法编译。

如果我没有渲染任何几何graphics,我不能得到重现的bug,但渲染一个点就足够了。

它仍然发生在一个简化的顶点着色器上:

#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 OpenGLdebugging器,将其设置为打破错误。 它只是告诉我编译失败了,我已经知道了。

失败的OpenGL上下文位于一个窗口中,在这个窗口中,先前创build了不同的上下文,并成功呈现并销毁。 重新使用这样的窗户没有任何问题,是吗? (我知道,一旦你调用SetPixelFormat ,你不能改变窗口的像素格式,我确保每次都使用相同的像素格式。)

补充:在调整渲染代码的同时,我发现如果我注释掉了这一行

glEnable( GL_VERTEX_PROGRAM_TWO_SIDE );

那么错误就消失了。 但是随着更多真实世界的渲染(例如纹理)的恢复,似乎没有什么区别。

添加3/7/2014:我终于做了一个自包含的Visual C ++项目,可以在某些情况下重现该错误,以便任何感兴趣的各方可以尝试它: ShaderBugTest项目为了使错误重现,您需要有微软的“应用程序validation程序“设置为监视堆错误。 随附的Read Me有更详细的重现步骤。

将包类对象指针装入char *作为消息队列

作为另一个用户启动Windows进程,而不直接知道密码

调用它的时候删除仿函数是否安全?

在任何情况下使用C#检索Java安装目录

closuresWindows框C#

你的例子有很多的GL对象的分配和取消分配,但很少或没有错误检查。

vertexShader = glCreateShader( GL_VERTEX_SHADER );

需要检查返回值vertexShader,以确保它是有效的。

glGetShaderiv( vertexShader,&status );

你得到这个值,但是不显示你正在检查状态。

program = glCreateProgram();

同样,在开始使用之前,需要检查返回值。

glAttachShader( program,vertexShader ); fragmentShader = glCreateShader( GL_FRAGMENT_SHADER ); glShaderSource( fragmentShader,NULL ); glCompileShader( fragmentShader );

在将它们附加到程序之前,您应该先创建片段着色器和顶点着色器。 如果出现问题,它会减少清理工作。

glGetShaderiv( fragmentShader,&status );

再一次检查后,检查编译状态。 您编译失败,但到目前为止,我们不知道哪个着色器无法编译。 是片段着色器还是顶点着色器。

glAttachShader( program,fragmentShader ); glDeleteShader( fragmentShader );

在这里删除着色器很奇怪。 是的,它应该只被标记删除,因为它实际上是附加到程序,但这似乎仍然是一个危险的做法。 此外,您正在采取不同的方法来处理片段着色器,而不是顶点着色器,原因不明。

glLinkProgram( program ); 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表示正在渲染的三角形的面的插补颜色。

但是,这是一个固定的管道功能,在现代的OpenGL中, gl_Color已经被弃用了。 这可能是你的错误背后的原因。 您需要使用以下代码获取编译器错误消息:

GLint SuccessFlag = 0; GLsizei Length = 0; GLsizei MaxLength = 0; glGetShaderiv( ShaderID,&SuccessFlag ); glGetShaderiv( ShaderID,GL_INFO_LOG_LENGTH,&MaxLength ); char* Log = ( char* )alloca( MaxLength ); glGetShaderInfoLog( ShaderID,MaxLength,&Length,Log );

将日志添加到您的问题将有助于更好地诊断您的问题。

你使用什么版本的OpenGL? 它是核心还是兼容性配置文件

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐