使用GLAD加载OpenGL时出现GL_INVALID_OPERATION错误求助
OpenGL 3.3 + GLAD调试版加载时触发GL_INVALID_OPERATION错误
问题背景
使用GLAD(配置为core profile、C调试版、OpenGL 3.3、启用loader)搭配GLFW 3.3.8创建OpenGL上下文,每次启动程序时,GLAD的调试后置回调会弹出ERROR 1282 in glGetIntegerv错误,经排查错误触发于gladLoadGLLoader()调用过程中,而非程序退出阶段。此前使用GLEW加载时无此问题,怀疑是GLEW屏蔽了该错误。
测试代码
#include <iostream> #include <glad/glad.h> #include <GLFW/glfw3.h> int main() { if(glfwInit() != GLFW_TRUE) throw std::runtime_error{"Unable to initialize GLFW."}; glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); GLFWwindow * w{glfwCreateWindow(100, 100, "title", nullptr, nullptr)}; if(w == nullptr) throw std::runtime_error{"Unable to create window."}; glfwMakeContextCurrent(w); if(not gladLoadGLLoader(GLADloadproc(glfwGetProcAddress))) throw std::runtime_error{"Unable to load OpenGL functions."}; glViewport(0, 0, 100, 100); while(not glfwWindowShouldClose(w)) { glfwPollEvents(); glClearColor(1.f, 0.f, 0.f, 1.f); glClear(GL_COLOR_BUFFER_BIT); glfwSwapBuffers(w); } glfwMakeContextCurrent(nullptr); glfwDestroyWindow(w); glfwTerminate(); std::cout << "Hey!" << std::endl; return 0; }
程序输出
Hey! ERROR 1282 in glGetIntegerv
调用栈
#0 0x00416f91 in _post_call_callback_default_gl (name=0x446d40 <_glfwDataFormat+10036> "glGetIntegerv", funcptr=0x41c1ec <glad_debug_impl_glGetIntegerv@8>, len_args=2) at <glad.c>:45 #1 0x0041c265 in glad_debug_impl_glGetIntegerv@8 (arg0=33309, arg1=0x4526cc <num_exts_i>) at <glad.c>:1385 #2 0x00417168 in get_exts () at <glad.c>:220 #3 0x0042691f in find_extensionsGL () at <glad.c>:3742 #4 0x00426d12 in gladLoadGLLoader (load=0x402a2e <glfwGetProcAddress>) at <glad.c>:3821 #5 0x004016f8 in main () at <main.cpp>:33
疑问
错误1282对应GL_INVALID_OPERATION,拆分代码逻辑后问题依旧。请问操作哪里有误?是否需要卸载OpenGL?
问题原因与解决方案
原因分析
从调用栈看,错误发生在GLAD尝试获取GL_NUM_EXTENSIONS(值为33309)时。在OpenGL 3.2及以上的Core Profile中,glGetIntegerv(GL_NUM_EXTENSIONS)是无效调用——Core Profile移除了这个枚举值,必须改用glGetStringi(GL_EXTENSIONS, ...)来查询扩展,而GLAD的调试版会严格检查每一次OpenGL调用的合法性,所以抛出了错误。GLEW之所以没报错,是因为它内部做了兼容处理,屏蔽了这类无效调用的错误反馈。
解决方案
- 切换GLAD为非调试版本:如果不需要严格的调试检查,可以重新生成GLAD时选择
language=c而非c-debug,这样调试回调不会触发,也就不会弹出错误提示。 - 自定义GLAD调试回调(保留调试功能可选):如果需要保留调试功能,可以自定义后置回调函数,过滤掉这个特定错误。示例代码如下:
#include <glad/glad.h> #include <cstdarg> #include <cstdio> #include <cstring> void custom_post_callback(const char* name, void* funcptr, int len_args, ...) { GLenum err = glGetError(); // 忽略GL_NUM_EXTENSIONS导致的GL_INVALID_OPERATION错误 if (err == GL_INVALID_OPERATION && strcmp(name, "glGetIntegerv") == 0) { va_list args; va_start(args, len_args); GLenum pname = va_arg(args, GLenum); va_end(args); if (pname == 33309 /* GL_NUM_EXTENSIONS */) { return; } } // 其他错误按原有逻辑输出 if (err != GL_NO_ERROR) { fprintf(stderr, "ERROR %d in %s\n", err, name); } } // 在gladLoadGLLoader之前设置自定义回调 gladSetPostCallback(custom_post_callback);
- 无需卸载OpenGL:这不是OpenGL本身的问题,只是GLAD调试版的严格检查与Core Profile的API差异导致的,卸载OpenGL完全没必要,反而可能导致系统图形功能异常。
内容的提问来源于stack exchange,提问作者postcoital-solitaire
相关产品推荐
相关产品推荐

