Почему 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:
"Если ненулевое имя объекта буфера привязано к включенному массиву, и хранилище данных объекта буфера в настоящее время сопоставлено" - я не делаю никакого сопоставления буфера в этой точке
"если активен геометрический шейдер и режим несовместим с [...]" - нет, на данный момент геометрических шейдеров нет.
Более того:
Я проверил и дважды проверил, что это только вызовы glDrawArrays(). Также дважды проверьте, что все аргументы, передаваемые в glDrawArrays(), идентичны в обеих версиях GL, в том числе и в привязках буфера.
Это происходит на 3 разных графических процессорах nvidia и 2 разных ОС (Win7 и OSX, обе 64-битные - конечно, в OSX у нас только контекст 3.2, но все равно 4.2).
Этого не происходит со встроенным графическим процессором 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()
...
}
Причина, по которой вы видите противоречивые результаты, может быть объяснена различиями в реализации.