为什么OpenGL的glDrawArrays()在Core Profile 3.2下使用GL_INVALID_OPERATION失败,而不是3.3或4.2?

met*_*eap 5 opengl go vertex-buffer vertex-array opengl-3

我有一个调用glDrawArrays的OpenGL渲染代码,当OpenGL上下文(自动/隐式获取)时,它可以完美地运行4.2但是在显式请求的OpenGL核心上下文3.2中一致地失败(GL_INVALID_OPERATION).(在两种情况下,着色器始终设置为#version 150,但这与我怀疑的点不同.)

根据规范,glDrawArrays()在GL_INVALID_OPERATION失败时只有两个实例:

  • "如果非零缓冲区对象名称绑定到已启用的数组,并且缓冲区对象的数据存储当前已映射" - 此时我没有进行任何缓冲区映射

  • "如果几何着色器处于活动状态且模式与[...]不兼容" - nope,则截至目前没有几何着色器.

此外:

  1. 我已经验证并仔细检查了它只是glDrawArrays()调用失败了.还要仔细检查传递给glDrawArrays()的所有参数在GL版本,缓冲区绑定下是否相同.

  2. 这发生在3个不同的nvidia GPU和2个不同的操作系统(Win7和OSX,都是64位 - 当然,在OSX中我们只有 3.2上下文,无论如何都不是4.2).

  3. 使用集成的"Intel HD"GPU不会发生这种情况,但对于那个,我只获得一个自动的隐式3.3上下文(试图通过GLFW明确强制使用此GPU的3.2核心配置文件在这里无法创建窗口,但这是一个完全不同的问题...)

对于它的价值,这里是在Golang中从渲染循环中摘录的相关例程:

func (me *TMesh) render () {
    curMesh = me
    curTechnique.OnRenderMesh()
    gl.BindBuffer(gl.ARRAY_BUFFER, me.glVertBuf)
    if me.glElemBuf > 0 {
        gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, me.glElemBuf)
        gl.VertexAttribPointer(curProg.AttrLocs["aPos"], 3, gl.FLOAT, gl.FALSE, 0, gl.Pointer(nil))
        gl.DrawElements(me.glMode, me.glNumIndices, gl.UNSIGNED_INT, gl.Pointer(nil))
        gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, 0)
    } else {
        gl.VertexAttribPointer(curProg.AttrLocs["aPos"], 3, gl.FLOAT, gl.FALSE, 0, gl.Pointer(nil))
        /* BOOM! */
        gl.DrawArrays(me.glMode, 0, me.glNumVerts)
    }
    gl.BindBuffer(gl.ARRAY_BUFFER, 0)
}
Run Code Online (Sandbox Code Playgroud)

所以当然这是更大的渲染循环的一部分,尽管现在整个"*TMesh"构造只是两个实例,一个是简单的立方体,另一个是简单的金字塔.重要的是整个绘图循环完美无缺,在3.3和4.2下查询GL时没有报告错误,但是3个具有显式3.2核心配置文件的nvidia GPU失败并且错误代码根据规范只调用了两个具体情况,据我所知,这里没有一个适用.

这可能有什么问题?你碰到过这个吗?我缺少什么想法?

Eva*_*haw 1

我有一个大胆的猜测。

据我了解,所有 OpenGL 调用必须发生在同一线程上。此限制与 Goroutine 不能很好地混合,因为同一个 Goroutine 可以在执行过程中的不同点在不同线程上运行。

为了解决这个问题,您需要在初始化 OpenGL 之前,在主 Goroutine(或任何正在执行 OpenGL 调用的 Goroutine)启动后立即将其锁定到其当前线程。

import "runtime"

func main() {
    runtime.LockOSThread()

    ...
}
Run Code Online (Sandbox Code Playgroud)

您看到不一致结果的原因可以通过实现差异来解释。