Soll man Puffer lösen?

12

Ich mache einige Tests mit OpenGL ES 2 und habe einige Fragen, mein aktuelles Programm sieht so aus:

Init
-------
-> create index buffer
-> fill index buffer glBufferData 
-> create vertex buffer
-> fill vertex buffer glBufferData 

Draw
-------
 1. Apply vertex buffer

    -> Bind VAO
       -> bind vertex buffer
          - enable attributs (glVertexPointer, …)
       -> unbind vertex buffer
    -> Unbind VAO
    -> Bind VAO

 3. Apply index buffer
 4. Draw

Das Problem

Nach einigen Nachforschungen habe ich nach dem angegebenen Codeabbruch verstanden, warum: Ich muss meinen Indexpuffer im Init-Teil (nach "fill index buffer glBufferData") oder vor dem ersten "Bind VAO" entbinden.

Meine Fragen sind:

  • Kann ich meinen Indexpuffer in VAO (VAO Stock Index Buffer?) Ablegen?
  • Musste ich nach jedem Update die Pufferbindung aufheben (glBufferData)?

In meiner Anwendung habe ich einige Puffer, die auf jedem Frame aktualisiert werden (Beispiel: Partikel), sodass ich einen OpenGL-Stapel wie diesen habe:

-> bind buffer 1
-> update buffer 1
-> close buffer 1
-> bind buffer 1
-> draw

Die ersten drei Zeilen aktualisieren den Vertex-Puffer, die beiden letzten Zeichenobjekte, die ungefähr so ​​aussehen sollten:

-> bind buffer 1
-> update buffer 1
-> draw

Vielen Dank

user30088
quelle

Antworten:

12

Sie scheinen viel auf unnötige Bindung / Unbinding zu tun. Wenn Sie ein VAO verwenden, sollten Sie das VAO nur binden, wenn Sie es einrichten und wenn Sie die Geometrie zeichnen. Sie binden den VBO / IBO erst wieder, wenn Sie sie aktualisieren müssen.

Nach dem Zeichnen oder Aktualisieren eines Puffers müssen Sie ihn nicht unbedingt lösen, obwohl dies möglicherweise eine gute Idee ist, um versehentliches Schreiben in Puffer zu vermeiden, die gebunden bleiben.

Nehmen wir nun Ihre erste Abfolge von Operationen. Dies ist die Gesamtreihenfolge, die ich erwarten würde:

Bei Init:

  1. VAO erstellen und binden. Jedes VBO und IBO, das Sie in der Sequenz binden, wird dem aktuellen VAO (diesem) zugeordnet.

  2. Indexpuffer erstellen und binden.

    • Füllen Sie den Indexpuffer mit glBufferData/glMapBuffer.
  3. Scheitelpunktpuffer erstellen und binden.

    • Füllen Sie den Scheitelpunktpuffer glBufferData/glMapBuffer.
  4. Richten Sie Scheitelpunktattribute mit glEnableVertexAttribArray/glVertexAttribPointerusw. ein.

  5. Optional können Sie alle Verbindungen lösen, um ein versehentliches Verändern der Puffer und des VAO zu vermeiden. Denken Sie daran, die VAO zuerst zu lösen . Z.B:glBindVertexArray(0);

Bei Auslosung:

  1. Wenn nur die Puffer gezeichnet werden :

    • Binde die VAO.
    • Führen Sie die Zeichnungsaufrufe aus.
  2. Beim Aktualisieren und Zeichnen :

    • Binden Sie die VAO, VBO, IBO;
    • Aktualisieren Sie die Puffer (die Aktualisierung der Scheitelpunktattribute ist nur erforderlich, wenn sich das Scheitelpunktformat geändert hat).
    • Führen Sie die Zeichnungsaufrufe aus.
  3. Optional können Sie die Bindung aufheben, um eine versehentliche Änderung der Puffer und des VAO zu vermeiden.

So einfach ist das. Diese Reihenfolge sollte problemlos funktionieren.

glampert
quelle
2
Ich möchte hinzufügen, dass ich in meinen Experimenten (2014) mit realen Fällen (aber einfachen Shadern, um einen Engpass bei der GPU zu vermeiden) die Leistungsverbesserungen mit VAO nach ordnungsgemäßer Bestellung als unbedeutend (<2% CPU-Ersparnis) empfand von Render-Aufrufen wurde implementiert, um das VBO-Setup vollständig zu überspringen, wenn derselbe VBO bei aufeinanderfolgenden Render-Aufrufen verwendet wurde (10 bis 33% CPU-Ersparnis), und ich habe einige Treiber-Bugs mit VAO festgestellt, sodass ich sie standardmäßig deaktiviert habe. Bei der Verwendung komplexer Shader, MSAA usw. war dies noch weniger wichtig. Dieser Engpass bei der GPU ließ die CPU auch auf Mobilgeräten ohnehin im Leerlauf warten.
Stephane Hockenhull
2
Beachten Sie, dass eine Fehlausrichtung von Vertex-Daten auf eine Weise, die von der Hardware nicht unterstützt wird, die GPU-Treiber dazu zwingt, die VBO-Daten bei jedem Setup neu zu ordnen, während die Treiber sie mit VAO einmal neu ordnen können, solange nichts an YMMV geändert wird. Es ist sowieso am besten, Eckdaten auszurichten und aufzufüllen.
Stephane Hockenhull
1
Warum muss die VAO vor allem anderen nicht gebunden sein?
Daniel Safari
@DanielSafari, meinst du nach dem Setup? Wenn Sie zuerst die Bindung eines Puffers aufheben (Bindungspuffer 0 / null), wird dieser Bindungspunkt in der aktuellen VAO gelöscht. Deshalb sollte zuerst der Null-VAO eingestellt werden.
Glampert
@glampert - nein, so funktionieren Bindungen nicht; Die Pufferbindung wird verwendet, wenn glVertexAttribPointer aufgerufen wird, und nicht anders (Ausnahme: GL_ELEMENT_ARRAY_BUFFER). Das Ändern der Pufferbindung nach dem Aufruf von glVertexAttribPointer hat keine Auswirkungen.
Maximus Minimus