VAO- und Element-Array-Pufferstatus
Ich war vor kurzem schriftlich einige OpenGL-3.3-code mit Vertex Array Objects (VAO) und Teste es später auf der Intel Grafikkarte gefunden, wo ich, zu meiner Enttäuschung, dass element-array-Puffer Bindung ist offenbar nicht Teil des Abschnitts VAO-Zustand, Aufruf:
glBindVertexArray(my_vao);
glDrawElements(GL_TRIANGLE_STRIP, count, GL_UNSIGNED_INTEGER, 0);
hatte keine Wirkung, während:
glBindVertexArray(my_vao);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, my_index_buffer); //?
glDrawElements(GL_TRIANGLE_STRIP, count, GL_UNSIGNED_INTEGER, 0);
gerenderte geometrie. Ich dachte, es war nur ein Fehler in der Intel-Implementierung von OpenGL (denn es ist klar in GL_ARB_vertex_array_object (und auch in GL_OES_vertex_array_object), das element-array ist Teil der gespeicherten Zustand), aber dann kam auf mobilen NVIDIA Quadro 4200. Das ist kein Spaß.
Ist es ein Treiber-bug, ein Daten-bug, oder ein Fehler irgendwo in meinem code? Der code funktioniert einwandfrei auf GeForce 260 und 480.
Hatte jemand ähnliche Erfahrung?
Was auch seltsam ist, dass GL_EXT_direct_state_access nicht über eine Funktion zum binden eines element-Arrays buffer in VAO (, aber es hat auch Funktionen, um anzugeben, vertex attrib-arrays, und damit array-Puffer). Sind die GPU-Hersteller Schrauben die technischen Angaben und betrügt uns, oder was?
BEARBEITEN:
Ich ursprünglich nicht beabsichtigt, um zu zeigen, jede source-code, weil ich glaubte, es sei hier nicht notwendig. Aber wie gewünscht, hier ist der minimale Testfall, der das problem reproduziert:
static GLuint n_vertex_buffer_object, p_index_buffer_object_list[3];
static GLuint p_vao[2];
bool InitGLObjects()
{
const float p_quad_verts_colors[] = {
1, 0, 0, -1, 1, 0,
1, 0, 0, 1, 1, 0,
1, 0, 0, 1, -1, 0,
1, 0, 0, -1, -1, 0, //red quad
0, 0, 1, -1, 1, 0,
0, 0, 1, 1, 1, 0,
0, 0, 1, 1, -1, 0,
0, 0, 1, -1, -1, 0, //blue quad
0, 0, 0, -1, 1, 0,
0, 0, 0, 1, 1, 0,
0, 0, 0, 1, -1, 0,
0, 0, 0, -1, -1, 0 //black quad
};
const unsigned int p_quad_indices[][6] = {
{0, 1, 2, 0, 2, 3},
{4, 5, 6, 4, 6, 7},
{8, 9, 10, 8, 10, 11}
};
glGenBuffers(1, &n_vertex_buffer_object);
glBindBuffer(GL_ARRAY_BUFFER, n_vertex_buffer_object);
glBufferData(GL_ARRAY_BUFFER, sizeof(p_quad_verts_colors), p_quad_verts_colors, GL_STATIC_DRAW);
glGenBuffers(3, p_index_buffer_object_list);
for(int n = 0; n < 3; ++ n) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, p_index_buffer_object_list[n]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(p_quad_indices[n]), p_quad_indices[n], GL_STATIC_DRAW);
}
glGenVertexArrays(2, p_vao);
glBindVertexArray(p_vao[0]);
{
glBindBuffer(GL_ARRAY_BUFFER, n_vertex_buffer_object);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), p_OffsetInVBO(0));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), p_OffsetInVBO(3 * sizeof(float)));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, p_index_buffer_object_list[0]); //red
}
glBindVertexArray(0);
glBindVertexArray(p_vao[1]);
{
glBindBuffer(GL_ARRAY_BUFFER, n_vertex_buffer_object);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), p_OffsetInVBO(0));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), p_OffsetInVBO(3 * sizeof(float)));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, p_index_buffer_object_list[1]); //blue
}
glBindVertexArray(0);
#ifdef BIND_BLACK_QUAD_ELEMENT_ARRAY_BUFFER
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, p_index_buffer_object_list[2]);
//bind the buffer with the black quad (not inside VAO, should NOT be seen)
#endif //BIND_BLACK_QUAD_ELEMENT_ARRAY_BUFFER
//[compile shaders here]
return true; //success
}
Dem obigen code erstellt einen vertex-buffer, der mit drei quads, rote, Blaue und schwarze. Dann schafft es drei index-Puffer, zeigen Sie auf die einzelnen quads. Dann zwei VAOs erstellt und eingerichtet ist, sollte man sich enthalten rot-quad-Indizes und das andere sollte enthalten blau quad Indizes. Das schwarze quad sollte nicht gerendert werden (übernehmen BIND_BLACK_QUAD_ELEMENT_ARRAY_BUFFER ist definiert).
void onDraw()
{
glClearColor(.5f, .5f, .5f, 0);
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
glUseProgram(n_program_object);
static int n_last_color = -1;
int n_color = (clock() / 2000) % 2;
if(n_last_color != n_color) {
printf("now drawing %s quad\n", (n_color)? "blue" : "red");
n_last_color = n_color;
}
glBindVertexArray(p_vao[n_color]);
#ifdef VAO_DOESNT_STORE_ELEMENT_ARRAY_BUFFER
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, p_index_buffer_object_list[n_color]); //fixes the problem
#endif //VAO_DOESNT_STORE_ELEMENT_ARRAY_BUFFER
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
}
Dadurch wird der viewport auf Grau und rendert entweder blau oder rot quad in sich wiederholenden Weise (es gibt auch welche). Während dies funktioniert auf desktop-GPU, aber es funktioniert nicht auf notebook-GPU (schwarz quad gerendert wird, es sei denn, die VAO_DOESNT_STORE_ELEMENT_ARRAY_BUFFER makro definiert ist. 'Undefining' die BIND_BLACK_QUAD_ELEMENT_ARRAY_BUFFER makro macht das quad blau, wie das Blaue index-buffer gebunden ist, ist letzten. Es heißt aber nicht, machen die rot quad, egal was.
So wie ich das sehe, entweder ist es ein fataler Irrglaube in meinem Verständnis von, wie sollte VAO arbeiten, einen Fehler in meinem code, oder einen Treiber Fehler.
Vollständige Quelle
Binaries (windows, 32 bit)
InformationsquelleAutor der Frage the swine | 2012-01-23
Du musst angemeldet sein, um einen Kommentar abzugeben.
Nach einiger Zeit fand ich heraus, das war tatsächlich mein Fehler. Der laptop mit dem mobilen NVIDIA Quadro 4200 Grafikkarte war so eingestellt, dass alle apps laufen die Intel-Grafik ist Standard, auch wenn der laptop war in den performance-Modus. Ich verstehe nicht, warum würde jemand wollen, das zu tun, dann gab es keine Möglichkeit, für jede Anwendung zu verwenden die leistungsfähigere GPU von OpenGL (es war immer noch möglich für die OpenCL als die explizite Auswahl der Geräte, vielleicht auch für DirectX - das würde erklären, warum einige Spiele reibungslos).
Dennoch, der beschriebene fehlerhafte Verhalten ist einfach ein bug im Intel Treiber, das ist alles dort ist zu es. Intel-Treiber nicht speichern ELEMENT_ARRAY_BUFFER_BINDING. Es.
Ich bin aufrichtig Leid für die Frage, denn es gab keine Möglichkeit zu geben, eine gute Antwort, ohne zu wissen, die oben genannten.
InformationsquelleAutor der Antwort the swine
Glaube ist nicht erforderlich; die spec sagt die Fakten.
Aus der ARB_vertex_array_object Spezifikation:
So, da haben wir es: der ganze Staat umgeben von VAOs sind die Inhalte der drei Tabellen, wobei die genannten Ausnahmen.
Die Erweiterung geschrieben ist, gegen Die OpenGL-Grafik-Spezifikation, version 2.1 (PDF-Datei). Daher werden alle Seitenzahlen, Abschnitt Beschriftungen oder Tabelle zahlen verwiesen wird, relativ zu der, spec.
Ich bin nicht zu kopieren, diese drei Tabellen hier. Aber wenn man sich auf Seite 273 (von der spec-Seite zu zählen)/Seite 287 (durch die Anzahl der physikalischen Seiten), finden Sie in der Tabelle 6.8. Und auf dieser Tabelle ist das folgende:
Es gibt keine Ambiguität. Die Informationen sind möglicherweise nicht deutlich gesagt. Aber es ist esfraglos. Die ELEMENT_ARRAY_BUFFER_BINDING ist Teil des VAO Zustand.
Daher kann dein problem kommt aus einer von zwei Quellen:
Treiber Fehler. Wie ich bereits in einem Kommentar, ein Treiber-bug scheint unwahrscheinlich. Nicht unmöglich, nur unwahrscheinlich. NVIDIA-Treiber sind ziemlich selbst-ähnlich wie für andere hardware, und VAOs werden kaum gespiegelt in der hardware. Es sei denn, Sie sind mit verschiedenen Versionen der Treiber, gibt es wenig Grund zu erwarten, dass ein Fehler durch einen Treiber-bug.
Benutzer Fehler. Ich weiß, Sie behaupten, dass Ihr code funktioniert, und deshalb ist es in Ordnung. Jeder macht, dass die Behauptung, code. Und es gab viele Zeiten, wenn ich schwöre hoch und runter, der code war gut arbeiten. Doch es wurde gebrochen, es ist einfach so passiert, durch zu bekommen. Passiert es. Wenn Sie nach Ihrem code, dann sind wir wenigstens in der Lage sein würde, um Rabatt diese Möglichkeit. Ansonsten, wir haben nichts mehr als Ihr Wort. Und wenn man bedenkt, wie oft Menschen sind falsch, dass ist nicht viel Wert.
InformationsquelleAutor der Antwort Nicol Bolas
Eine wahrscheinliche Ursache HIERFÜR ist, dass die Intel adapter keine OpenGL 3.3 Kontext -, sondern standardmäßig auf 2.1 oder so. Wie andere haben darauf hingewiesen, die in früheren Versionen von OpenGL, das element-array Puffer-Staat war nicht Teil einer VAO.
InformationsquelleAutor der Antwort bduc
Kann ich mir vorstellen, das
ELEMENT
Puffer nicht zwischengespeichert werden, wenn Sie dies tun:Es ist wie zu sagen:
In anderen Worten,
glBindBuffer()
nicht alles tun, aber den Wert desGL_ARRAY_BUFFER
. Es ist anglVertexAttribPointer()
hier ändern Sie die VAO.Also, wenn Sie tun:
Du wirklich tun:
Wo es Sinn macht, dass die
GL_ELEMENT_ARRAY_BUFFER
Bindung nichts zu tun.Ich bin mir nicht sicher, ob es eine
glVertexAttribPointer()
-wie Variante für Elemente, die zwar (wieglElementPointer()
), die wirklich wirken auf die VAO.InformationsquelleAutor der Antwort Ruud van Gaal