未处理的异常,glGenVertexArrays 调用上的访问冲突

Posted

技术标签:

【中文标题】未处理的异常,glGenVertexArrays 调用上的访问冲突【英文标题】:Unhandled exception, Access violation on glGenVertexArrays call 【发布时间】:2015-06-21 21:09:28 【问题描述】:

我目前在 Windows 8 上进行 OpenGL 开发时遇到了一些问题。我正在为一个在 Linux 中运行的项目设置 OpenGL。

我们在这个项目中同时使用 glfw 和 glew。

我的实际问题是 glGenVertexArrays 为空,当它被调用时它崩溃并且我遇到访问冲突。 glGenVertexArrays 并不是第一个使用 glew 的 gl 调用。

我按照本教程使用 win32 库将 glew 和 glfw 链接到 Visual Studio 项目:http://www.41post.com/5178/programming/opengl-configuring-glfw-and-glew-in-visual-cplusplus-express

以下代码为初始化代码:

glfwSetErrorCallback(error_callback);

    if (!glfwInit())
    
        LOG_FATAL << "Failed to init glfw context";
        exit(EXIT_FAILURE);
    

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    m_window = glfwCreateWindow(1240, 480, "Rubix", NULL, NULL);

    if (!m_window)
    
        glfwTerminate();
        LOG_FATAL << "Failed to create glfw window";
        exit(EXIT_FAILURE);
    

    glfwMakeContextCurrent(m_window);

    #ifdef WIN32
    //glewExperimental = GL_TRUE;
    GLenum glewinit = glewInit();

    if (glewinit != GLEW_OK)
    
        std::cout << "Glew not okay! " << glewinit;
        exit(EXIT_FAILURE);
    
    #endif

    glfwSwapInterval(1);
    glfwSetKeyCallback(m_window, key_callback);

    LOG_INFO << "glfw OpenGL context ready";

    initGL();

下面的代码被调用来显示一个立方体:

float points[] = 
        0.0f, 0.0f, 0.0f, 1.0f,
        1.0f, 0.0f, 0.0f, 1.0f,
        1.0f, 1.0f, 0.0f, 1.0f,
        0.0f, 1.0f, 0.0f, 1.0f,
        0.0f, 0.0f, 1.0f, 1.0f,
        1.0f, 0.0f, 1.0f, 1.0f,
        1.0f, 1.0f, 1.0f, 1.0f,
        0.0f, 1.0f, 1.0f, 1.0f
    ;

    float normals[] = 
        0.0f, 0.0f, 0.0f, 1.0f,
        1.0f, 0.0f, 0.0f, 1.0f,
        1.0f, 1.0f, 0.0f, 1.0f,
        0.0f, 1.0f, 0.0f, 1.0f,
        0.0f, 0.0f, 1.0f, 1.0f,
        1.0f, 0.0f, 1.0f, 1.0f,
        1.0f, 1.0f, 1.0f, 1.0f,
        0.0f, 1.0f, 1.0f, 1.0f
    ;

    unsigned short index_array[] = 
        0, 3, 2,
        0, 2, 1,
        0, 1, 5,
        0, 5, 4,
        1, 2, 6, 
        1, 6, 5,
        2, 3, 7,
        2, 7, 6,
        3, 0, 4,
        3, 4, 7,
        4, 5, 6,
        4, 6, 7,
    ;

    GLuint points_vbo;
    glGenBuffers (1, &points_vbo);
    glBindBuffer (GL_ARRAY_BUFFER, points_vbo);
    glBufferData (GL_ARRAY_BUFFER, 32 * sizeof (float), points, GL_STATIC_DRAW);

    GLuint normals_vbo;
    glGenBuffers (1, &normals_vbo);
    glBindBuffer (GL_ARRAY_BUFFER, normals_vbo);
    glBufferData (GL_ARRAY_BUFFER, 32 * sizeof (float), normals, GL_STATIC_DRAW);

    GLuint index_buffer_object;
    glGenBuffers (1, &index_buffer_object);
    glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, index_buffer_object);
    glBufferData (GL_ELEMENT_ARRAY_BUFFER, 48 * sizeof (unsigned short), index_array, GL_STATIC_DRAW);

    glGenVertexArrays (1, &m_vao);
    glBindVertexArray (m_vao);
    glEnableVertexAttribArray (0);
    glEnableVertexAttribArray (1);

    glBindBuffer (GL_ARRAY_BUFFER, points_vbo);
    glVertexAttribPointer (0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
    glBindBuffer (GL_ARRAY_BUFFER, normals_vbo);
    glVertexAttribPointer (1, 4, GL_FLOAT, GL_FALSE, 0, NULL);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_object);

    glBindVertexArray(0);

    // Creating program

    Program program;

    program.emplace_back("pos.vert", GL_VERTEX_SHADER);
    program.emplace_back("smooth.frag", GL_FRAGMENT_SHADER);

    program.link();

    program.clearShaders();

    m_program = program.getProgram();

我确实尝试过 glewExperimental = GL_TRUE;有了这个代码运行,但它不显示任何东西。

我使用的 gpu 是 nvidia GT 730M,它支持最高 4.2 的 opengl。

我还运行了 glewinfo.exe,它说 glGenVertexArrays 应该没问题。 我还注意到,当我在 Windows 工具包下的 gl 文件夹中打开位于(使用 Visual Studio 2013)的 glcorearb.h 时,opengl 中的大多数版本都是灰色的,我认为问题可能与此有关。

【问题讨论】:

【参考方案1】:

如果存在不足的 OpenGL 环境,您的代码不会检查是否满足所需的运行时先决条件,因此它不会捕捉到这种情况。很可能是 OpenGL 驱动程序安装不正确,这就是 GLEW 无法初始化您需要的函数指针的原因。

请注意,Microsoft 正在破坏 OpenGL,并删除了通过 Windows 更新或初始 Windows 设置安装的驱动程序中的 OpenGL ICD。请仔细检查您直接从 NVidia 网站下载的驱动程序是否已正确安装。

【讨论】:

我已经通过 Nvidia 的工具 GeForce Experience 安装了我的驱动程序。它们是我的 GPU 的最新驱动程序。 我刚刚测试过并且 glGetString(GL_VENDOR);" 返回英特尔,即使我确实更改了 nvidia 控制面板中的设置以使用它而不是英特尔集成 gpu... 其实我在nvidia的控制面板中设置的是release .exe,我正在用debug .exe进行测试。我也将调试 .exe 添加到配置文件中,但它仍然崩溃。 @AlexandreCoulon-Hamelin:有一个技巧可以强制在 Optimus 系统中使用 NVidia GPU。它在 Optimus 使用指南中有描述,这个 *** 答案提到了它:***.com/a/14041061/524368 – 我建议你也将启用变量导出到你的程序中(带有 mainWinMain 函数的源文件就足够了)。 现在我将调试文件夹中的 .exe 添加到了 nvidia 控制面板,它确实使用了我的 nvidia gpu。 glGetString(GL_VENDOR) 返回 nvidia【参考方案2】:

好的,问题是 Visual Studio 没有使用正确的 GPU。为了修复它,我进入了 Nvidia 控制面板 -> 管理 3D 设置 -> 程序设置并添加了我的调试 exe 和发布 exe。

之后它不起作用的原因是我忘记将 glewExperimental 设置为 true 进行尝试。

在设置完这两项后,我的问题就解决了。

【讨论】:

以上是关于未处理的异常,glGenVertexArrays 调用上的访问冲突的主要内容,如果未能解决你的问题,请参考以下文章

为啥使用 GTKGLArea 时在 PyOpenGL 中未定义 glGenVertexArrays

LWJGL OpenGL glGenVertexArrays() 错误:此函数不可用

glGenVertexArrays 没有给出唯一的 vaos

了解顶点数组对象(glGenVertexArrays)

sop代码未处理系统线程异常

WPF捕获全局未处理异常