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

Schreibe einen Kommentar