Почему OpenDGL glDrawArrays() не работает с GL_INVALID_OPERATION в Core Profile 3.2, но не 3.3 или 4.2?

У меня есть код рендеринга OpenGL, вызывающий glDrawArrays, который работает безупречно, когда контекст OpenGL (автоматически / неявно получен) 4.2, но не работает последовательно (GL_INVALID_OPERATION) с явно запрашиваемым основным контекстом OpenGL 3.2. (В обоих случаях шейдеры всегда установлены на #version 150, но я подозреваю, что это не относится к делу)

Согласно спецификации, есть только два случая, когда glDrawArrays() завершается ошибкой с GL_INVALID_OPERATION:

  • "Если ненулевое имя объекта буфера привязано к включенному массиву, и хранилище данных объекта буфера в настоящее время сопоставлено" - я не делаю никакого сопоставления буфера в этой точке

  • "если активен геометрический шейдер и режим несовместим с [...]" - нет, на данный момент геометрических шейдеров нет.

Более того:

  1. Я проверил и дважды проверил, что это только вызовы glDrawArrays(). Также дважды проверьте, что все аргументы, передаваемые в glDrawArrays(), идентичны в обеих версиях GL, в том числе и в привязках буфера.

  2. Это происходит на 3 разных графических процессорах nvidia и 2 разных ОС (Win7 и OSX, обе 64-битные - конечно, в OSX у нас только контекст 3.2, но все равно 4.2).

  3. Этого не происходит со встроенным графическим процессором Intel HD, но для этого я получаю только автоматический неявный контекст 3.3 (попытка явно форсировать профиль ядра 3,2 с этим графическим процессором через GLFW здесь не удается создать окно, но это совершенно другая проблема...)

Для чего стоит, вот соответствующая процедура, извлеченная из цикла рендеринга в 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)
}

Так что, конечно, это часть большего цикла рендеринга, хотя вся конструкция "*TMesh" на данный момент представляет собой всего два экземпляра: один простой куб, а другой простая пирамида. Важно то, что весь цикл рисования работает без сбоев, и об ошибках не сообщается, когда GL запрашивается на наличие ошибок как в 3.3, так и в 4.2, однако на 3 графических процессорах NVIDIA с явным профилем ядра 3.2 происходит сбой с кодом ошибки, который в соответствии со спецификацией вызывается только в две конкретные ситуации, ни одна из которых, насколько я могу судить, не применима здесь.

Что здесь может быть не так? Вы когда-нибудь сталкивались с этим? Есть идеи, чего мне не хватало?

2 ответа

Это не просто DrawArrays, я ошибся здесь. Каким-то образом мой способ вызова glVertexAttribPointer является проблемой здесь: в любом строгом профиле ядра, будь то 3.2 или 4.2... будет проведено дальнейшее исследование. В нестрогом контексте 4.2 проблем нет.

У меня есть дикое предположение.

Насколько я понимаю, все вызовы OpenGL должны происходить в одном потоке. Это ограничение плохо сочетается с процедурами, так как одна и та же программа может работать в разных потоках в разных точках своего выполнения.

Чтобы обойти эту проблему, вам нужно заблокировать вашу основную программу (или любую другую программу, которая делает вызовы OpenGL) с ее текущим потоком, как только он запускается, перед инициализацией OpenGL.

import "runtime"

func main() {
    runtime.LockOSThread()

    ...
}

Причина, по которой вы видите противоречивые результаты, может быть объяснена различиями в реализации.

Другие вопросы по тегам