2012-10-24 12 views
5

Ich habe OpenGL-Rendering-Code glDrawArrays aufrufen, die einwandfrei funktioniert, wenn der OpenGL-Kontext (automatisch/implizit) 4.2, aber konsistent (GL_INVALID_OPERATION) mit einem explizit angeforderten OpenGL-Core-Kontext 3.2. (Shaders gesetzt sind immer 150 in beiden Fällen #Version aber das ist neben dem Punkt hier vermute ich.)Warum scheitert OpenGLs glDrawArrays() mit GL_INVALID_OPERATION unter Core Profile 3.2, aber nicht 3.3 oder 4.2?

Nach Angaben gibt es nur zwei Fälle, in denen glDrawArrays() mit GL_INVALID_OPERATION versagt:

  • „wenn ein nicht-Null-Puffer-Objekt Name Datenspeicher des zu einem aktivierten Array und das Puffer-Objekts zur Zeit abgebildet gebunden ist“ - ich bin ein beliebigen Puffer Mapping

  • „, wenn ein Geometrie-Shader an dieser Stelle nicht tun ist aktiv und Modus ist nicht kompatibel mit [...] "- nein, keine Geometrie Shader ab sofort.

Außerdem:

  1. Ich habe überprüft & doppelt geprüft, dass es nur die glDrawArrays() bei Nicht-Anrufe. Außerdem wurde überprüft, dass alle Argumente, die an glDrawArrays() übergeben werden, in beiden GL-Versionen, auch Pufferbindungen, identisch sind.

  2. Dies geschieht über 3 verschiedenen NVIDIA-GPUs und 2 verschiedene Betriebssysteme (Win7 und OSX, sowohl 64-Bit - natürlich in OSX wir nur den 3.2 Kontext haben, keine 4.2 sowieso).

  3. Es passiert nicht mit einer integrierten "Intel HD" GPU, aber dafür bekomme ich nur einen automatischen impliziten 3.3 Kontext (versucht explizit ein 3.2 Kernprofil mit dieser GPU über GLFW zu erzwingen) scheitert hier aber an der Fenstererstellung das ist eine ganz andere Frage ...)

Für was es wert ist, ist hier die entsprechende Routine von der Schleife machen exzerpiert, in 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) 
} 

So natürlich ist Teil eines größeren Render-Schleife, obwohl das ganze "* TMesh" Konstrukt Für den Augenblick gibt es nur zwei Fälle, einen einfachen Würfel und den anderen eine einfache Pyramide. Entscheidend ist, dass die gesamte Zeichnungsschleife einwandfrei funktioniert und keine Fehler gemeldet werden, wenn GL sowohl unter 3.3 als auch 4.2 nach Fehlern gefragt wird, aber auf 3 NVIDIA GPUs mit einem expliziten 3.2-Kernprofil mit einem Fehlercode, der nur in spec aufgerufen wird Zwei spezifische Situationen, von denen keine, soweit ich das beurteilen kann, hier zutreffen.

Was könnte hier falsch sein? Bist du jemals darauf gestoßen? Irgendwelche Ideen was ich vermisst habe?

+0

Wo ist irgendeine Frage? Klingt eher nach einem Fehlerbericht. – zzzz

+4

"* Laut Spezifikationen gibt es nur zwei Fälle, in denen glDrawArrays() mit GL_INVALID_OPERATION fehlschlägt: *" Eine schöne Fantasie, aber nicht wahr. Es gibt zahlreiche Möglichkeiten, wie alle 'glDraw *' - Aufrufe fehlschlagen können. Sie sind nur nicht bei jedem Aufruf aufgeführt. Ich habe versucht, [viele von ihnen hier zu sammeln] (http://www.opengl.org/wiki/Vertex_Rendering#Causes_of_rendering_failure), aber es kann mehr geben. –

+0

@jnml ah, ja ... natürlich ist die Frage, die in solchen Threads enthalten ist, immer "was könnte hier falsch sein? Hast du jemals in das hineingeraten? Irgendwelche Ideen was ich vermisst habe?". Wird entsprechend aktualisiert ...... – metaleap

Antwort

1

Ich habe eine wilde Vermutung.

Wie ich es verstehe, müssen alle OpenGL-Aufrufe auf dem gleichen Thread geschehen. Diese Einschränkung passt nicht gut zu Goroutines, da dieselbe Goroutine auf verschiedenen Threads an verschiedenen Punkten in ihrer Ausführung laufen kann.

Um dieses Problem zu umgehen, müssen Sie Ihre Haupt goroutine (oder was auch immer goroutine OpenGL Aufrufe) zu seinem aktuellen Thread sperren, sobald es startet, vor der Initialisierung von OpenGL.

import "runtime" 

func main() { 
    runtime.LockOSThread() 

    ... 
} 

Der Grund, warum Sie widersprüchliche Ergebnisse sehen, könnte durch Implementierungsunterschiede erklärt werden.

+0

Goroutines & LockOShread, das wird schon erledigt ... :) – metaleap

+0

Problem aktualisiert: http://stackoverflow.com/questions/13062149/how-do -i-make-this-simple-opengl-code-funktioniert-in-a-lenient-3-3-and-4-2-profile – metaleap

1

Es ist nicht nurDrawArrays, ich war hier falsch. Irgendwie ist meine Art zu rufen glVertexAttribPointer ist das Problem hier: in jeder strengen Kernprofil, ob 3.2 oder 4.2 ... wird weiter untersuchen. In einem 4.2 nicht strikten Kontext kein Problem.

+0

Problem aktualisiert: http://stackoverflow.com/questions/13062149/how- do-i-make-this-einfach-opengl-code-funktioniert-in-a-lenient-3-3-and-4-2-profile – metaleap