glGetError()
中。据我了解,如果我在调用“正常” OpenGL函数后再调用它,则glGetError()
将返回一个或多个错误代码,前提是我犯了一些错误。另外,我必须在while循环中调用它以获取所有错误。 我对此有多个问题。一个我找不到发生错误的行号,第二个它不能正确告诉我为什么会发生错误(虽然这不是一个大问题),最后我必须在每个OpenGL函数调用之后添加一个while循环。
下面是一个例子,
unsigned int buffer = 0;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(float), vertices, GL_STATIC_DRAW);
现在,如果我用
glGetError()
编写它,它看起来就像unsigned int err = 0;
glGenBuffers(1, &buffer);
while( !(err = glGetError()) ){
std::cout << err;
}
glBindBuffer(GL_ARRAY_BUFFER, buffer);
while( !(err = glGetError()) ){
std::cout << err;
}
glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(float), vertices, GL_STATIC_DRAW);
while( !(err = glGetError()) ){
std::cout << err;
}
当然不是这样,对吧?源代码看起来很丑。
我该如何使用OpenGL进行正确的错误处理?
我的图形卡支持OpenGL 4.4,并且我正在使用C ++。
#1 楼
是的,有更好的方法! 😊OpenGL 4.3和更高版本支持glDebugMessageCallback
API,该API允许您在应用程序中指定GL将调用以发出警告或错误的功能。在此功能中,您可以执行任何操作,例如在调试器中设置断点,或将错误打印到日志文件中。这样,您只需要在初始化期间设置回调即可,这比将glGetError
调用无处不在要好得多。要启用此功能,您的GL上下文也需要是一个“调试上下文”,由创建上下文时设置标志。详细信息将取决于您所使用的OS /窗口系统/框架。调试上下文(在CPU上)可能比常规上下文要慢,但这就是您为更详细的调试信息所付出的代价,就像在编译器中关闭优化一样。
另请参阅此Wiki页面欲获得更多信息。还有很多其他与调试相关的功能。例如,您可以使用
glObjectLabel
为纹理,缓冲区,帧缓冲区等提供易于理解的名称,然后(我假设)它们将用于错误消息中。还有一些API可用于关闭某些消息或某些类别的消息,以防因您不关心或类似的警告而被垃圾邮件感染。#2 楼
尽管“调试输出”很好,并且可以手动使用glGetError
,但通常最好使用更专用的工具来精确查找OpenGL错误的来源。RenderDoc可能是最新的工具用于此过程,但是有很多处于各种功能状态。这些工具还可以为您提供每个OpenGL调用的详细日志。
#3 楼
如果您无法使用OpenGL 4.3(或者您的实现不支持glDebugMessageCallback
),则可以通过多种方式简化代码。第一个方法是将对
glGetError()
的调用移至这样的函数:void checkGLError()
{
GLenum err;
while((err = glGetError()) != GL_NO_ERROR){
std::cout << err;
}
}
将代码减少为:
unsigned int buffer = 0;
glGenBuffers(1, &buffer);
checkGLError();
glBindBuffer(GL_ARRAY_BUFFER, buffer);
checkGLError();
glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(float), vertices, GL_STATIC_DRAW);
checkGLError();
但是,经常调用
glGetError()
可能会损害性能,因此最好对其进行条件化,以便仅通过执行以下操作在调试版本中对其进行调用:#if DEBUG
#define checkGLError() debugCheckGLError()
#else
#define checkGLError()
#endif
,然后将实际函数命名为
debugCheckGLError()
。它会在调试版本中被调用,但不会在发布版本中被调用。评论
$ \ begingroup $
我将debug宏与其他答案一起使用。谢谢。
$ \ endgroup $
–user8277998
17年4月4日在16:23
$ \ begingroup $
您可以对宏进行更进一步的操作,例如:github.com/bkaradzic/bgfx/blob/…这样您的代码就变成了:GL_CHECK(glGenBuffers(1,&buffer));并报告您需要的一切。
$ \ endgroup $
–朱利安·盖尔特(Julien Guertault)
17年12月6日在2:47
$ \ begingroup $
我不明白while(!(err = glGetError())为什么!?不应该是:while(err = glGetError())使它循环并输出错误消息吗?否则,不是吗?它是一个无限循环,在第一个成功调用中反复显示0吗?
$ \ endgroup $
–维克
20 Mar 4 '20 at 5:49
$ \ begingroup $
@Wyck是的,您是正确的。我已经更新了它,使其与正确的错误值进行比较,使其更加明确。
$ \ endgroup $
–user1118321
20 Mar 7 '20 at 21:07
评论
我最近部分回答了类似的问题。请参阅computergraphics.stackexchange.com/a/5773/182不应该在while(err = glGetError())读取)
它返回GL_NO_ERROR,我假定它的值为0,没有错误时,这就是为什么我有!=的原因。无论如何都应该是while((err = glGetError())!= GL_NO_ERROR)。