Warum erlaubt OpenGL> = 3 nur VBOs?


21

Ich sehe, dass OpenGL-Versionen 3 und höher die Verwendung von clientseitigem Rendering eliminieren. Der Sofortmodus wurde entfernt und Vertex-Arrays scheinen veraltet zu sein. Wenn ich das richtig verstehe, sind VBOs die Hauptmethode zum Rendern von Vertices.

Während ich die Logik dahinter sehe, alles auf einheitliche Weise zu rendern, haben VBOs keine großen Nachteile gegenüber Vertex-Arrays? Ich dachte, VBOs sollten im Allgemeinen große Puffer sein, die mehr als 1 MB Daten enthalten. Was ist, wenn ich eine Szene mit viel kleinerer Geometrie habe? Ich habe ein Szenendiagramm mit einer großen Anzahl von Knoten, von denen jeder eine eigene Transformation usw. benötigt. Jeder Knoten sollte auch separat gelöscht, zu separat hinzugefügt usw. werden können. Ich habe zuvor Vertex-Arrays verwendet. Meine erste Frage ist also, ob beim Umstieg auf VBOs der Aufwand für meine Szenendiagrammobjekte jetzt höher ist, da für jedes Objekt ein VBO zugewiesen werden muss.

Ein weiteres Problem ist, dass die von mir gerenderte Geometrie sehr dynamisch sein kann. Im schlimmsten Fall kann es vorkommen, dass die gesamte Geometrie für einen bestimmten Zeitraum erneut an jeden Frame gesendet werden muss. Haben VBOs in diesem Anwendungsfall eine schlechtere Leistung als Vertex-Arrays, oder funktionieren VBOs im schlimmsten Fall genauso gut wie Vertex-Arrays, jedoch nicht mehr?

In einem präziseren Format lauten meine Fragen also:

1) Ist die Zuweisung / Freigabe von VBOs mit einem erheblichen Aufwand verbunden (ich meine die bloße Einrichtung eines Puffers)?

2) Wenn ich die Daten von der CPU in jedem Frame aktualisiere, kann dies wesentlich schlimmer sein, als wenn ich Vertex-Arrays verwendet hätte?

Und zum Schluss würde ich gerne wissen:

3) Wenn die Antwort auf eine der obigen Fragen "Ja" lautet, warum sollten andere Rendering-Modi, die Vorteile gegenüber VBOs haben könnten, verworfen werden? Fehlt hier etwas, beispielsweise Techniken, mit denen ich einige dieser potenziellen Allokationskosten usw. abmildern soll?

4) Ändern sich die Antworten auf diese Fragen erheblich, je nachdem, welche OpenGL-Version ich verwende? Wenn ich meinen Code so umgestalte, dass er mit OpenGL 3 oder 4 vorwärtskompatibel ist, indem ich VBOs auf performante Weise verwende, werden dieselben Techniken mit OpenGL 2 wahrscheinlich gut funktionieren, oder ist es wahrscheinlich, dass bestimmte Techniken mit OpenGL 3 viel schneller sind + und andere mit OpenGL 2?

Ich habe diese Frage zum Stapelüberlauf gestellt, aber ich poste sie hier erneut, da mir klar wurde, dass diese Site für meine Frage möglicherweise besser geeignet ist.


1
Warum eine Abstimmung abschließen? Ist es ein Trottel? Wenn ja, kann ich einen Link sehen, damit ich davon profitieren kann?
Schwerkraft

Antworten:


23

Ist die Zuweisung / Freigabe von VBOs mit einem erheblichen Aufwand verbunden (ich meine die bloße Einrichtung eines Puffers)?

Definieren Sie "substantiell". Es ist im Allgemeinen ratsam, sie nicht in der Mitte von Frames zu erstellen. Sie sollten während der Initialisierung oder an einem beliebigen Ort eingerichtet werden. Dies gilt jedoch für die meisten OpenGL-Objekte, z. B. Texturen, Renderbuffer oder Shader.

Wenn ich die Daten von der CPU in jedem Frame aktualisiere, kann dies wesentlich schlimmer sein, als wenn ich Vertex-Arrays verwendet hätte?

Kann es? Ja. OpenGL definiert Funktionalität, nicht Leistung . Sie können die Dinge in der Tat viel langsamer machen. Oder Sie können die Dinge schneller machen. Es hängt alles davon ab, wie Sie es verwenden.

Das OpenGL-Wiki bietet einen guten Artikel zum richtigen Streamen von Daten .

Wenn die Antwort auf eine der oben genannten Fragen "Ja" lautet, warum sollten andere Rendering-Modi, die Vorteile gegenüber VBOs haben könnten, verworfen werden? Fehlt hier etwas, beispielsweise Techniken, mit denen ich einige dieser potenziellen Allokationskosten usw. verringern soll?

Erstens waren sie nicht nur veraltet. Verfall bedeutet, dass in zukünftigen Versionen etwas als "zu entfernen" markiert wird. Sie wurden in 3,0 veraltet und entfernt in 3.1 Kern und darüber.

Zweitens hat die ARB allgemein erklärt, warum sie Inhalte aus OpenGL entfernt haben. Dadurch wird die Spezifikation kleiner und einfacher. Dadurch wird die API kleiner und schlanker. Dadurch ist es einfacher zu wissen, welche APIs Sie verwenden sollten. 2.1 hatte 4 Möglichkeiten, Vertexdaten bereitzustellen; 3.1+ hat 1. Es wird viel Cruft los. Etc.

Ändern sich die Antworten auf diese Fragen erheblich, je nachdem, welche OpenGL-Version ich verwende? Wenn ich meinen Code so umgestalte, dass er mit OpenGL 3 oder 4 vorwärtskompatibel ist, indem ich VBOs auf performante Weise verwende, werden dieselben Techniken mit OpenGL 2 wahrscheinlich gut funktionieren, oder ist es wahrscheinlich, dass bestimmte Techniken mit OpenGL 3 viel schneller sind + und andere mit OpenGL 2?

Mehr oder weniger nein. Nur unter MacOSX ist der Unterschied zwischen 3.1 + Core- und Pre-3.0-Versionen wirklich offensichtlich. Das Kompatibilitätsprofil wird von allen Treibern für Linux und Windows implementiert. Sie können also davon ausgehen, dass das Kernprofil dieser Treiber nur Überprüfungen hinzufügt, um zu verhindern, dass Sie Kompatibilitätsfunktionen aufrufen.

Unter Mac OS X 10.7 ist der GL 3.2 Core verfügbar, nicht jedoch das Kompatibilitätsprofil. Das bedeutet nicht unbedingt etwas für die Aufführungstechniken auf der einen Seite gegen die anderen. Wenn es Unterschiede gibt, ist dies jedoch die Plattform, auf der Sie sie sehen.


1
Da Sie diese Frage gerade gekreuzt haben, werde ich meine Antwort nur gekreuzt veröffentlichen.
Nicol Bolas

Ein weiterer Vorteil der API-Kompaktheit besteht darin, dass die OpenGL-API einfacher zu implementieren ist. Dies war eine wichtige Überlegung in der ursprünglichen OpenGL ES-Spezifikation.
notlesh

@stephelton: Macht Sinn. Meine Frage "Warum alles außer VBOs ablehnen" basierte auf der Überlegung, dass es zwar absolut sinnvoll ist, die API schlank zu halten, es jedoch nicht sinnvoll ist, Funktionen abzulehnen, die in vielen Anwendungsfällen besser als VBOs sein könnten. Nach allem, was ich höre, gibt es anscheinend keine Nachteile bei der Verwendung von VBOs. Daher ist es absolut sinnvoll, alles andere zu verwerfen.
Schwerkraft

@gravity Sie nicht haben VBO zu gebrauchen. Sie können auch ein Array von Scheitelpunkten verwenden.
notlesh

18

So wie OpenGL funktioniert, muss der Treiber immer dann, wenn Sie Nicht-VBO-Daten verwenden, eine Kopie davon erstellen - in der Praxis wird ein temporärer VBO erstellt -, da nichts Sie daran hindert, die nackten Arrays im Benutzerbereich zwischen Aufrufen von OpenGL zu ändern.

Möglicherweise gibt es einige Tricks auf der Treiberseite, um die Zuweisung der Temperatur zu beschleunigen, aber Sie können nichts tun, um das Kopieren zu verhindern.

Also ja, solange Sie - und die Treiberentwickler - alles richtig machen, sollten VBOs immer nur die Dinge beschleunigen.


6
Diese Antwort gefällt mir besser. Es ist kürzer und auf den Punkt gebracht, imo.
TravisG

@JariKomppa: Das klingt nach einer sehr vernünftigen Erklärung. Ich habe immer noch ein Problem: VBOs sollten relativ große Objekte sein, die beim letzten Überprüfen häufig als 1 MB - 4 MB große Puffer zugewiesen wurden. Was ist, wenn meine Geometrieobjekte nicht so groß sind, ich mir aber trotzdem Sorgen um die Leistung mache, weil ich viele Objekte habe? Ich mache mir Sorgen, dass VBOs nur für einen anderen Anwendungsfall geeignet sind als ich. Sollte ich mehrere Objekte in einem einzigen VBO zusammenfassen und dann glDrawRangeElementszum Zeichnen jedes einzelnen Objekts verwenden, oder ist das genauso ineffizient wie Vertex-Arrays?
Schwerkraft

Ich bezweifle, dass dies einen Unterschied machen wird, aber wenn Sie der Meinung sind, dass es ein Problem ist, vergleichen Sie es.
Jari Komppa

@JariKomppa: Woran zweifeln Sie, wird sich etwas ändern? Verwenden Sie glDrawRangeElementsmehrere Male auf jedem VBO mit ein paar VBOs, anstatt jedem Objekt einen eigenen VBO zuzuweisen?
Schwerkraft

1
Genau. Ich bezweifle, dass Sie dort einen großen Unterschied feststellen werden, aber das Erstellen von Profilen für einige Testfälle sollte Ihnen weitere Informationen liefern. Darüber würde ich mir jetzt auch keine Gedanken machen, da eine solche Änderung später angewendet werden könnte, wenn es nötig ist.
Jari Komppa,

9

und Vertex-Arrays scheinen veraltet zu sein. Stattdessen, wenn ich richtig verstehe,

Nicht ganz. Vertex-Arrays bilden die Grundlage für Vertex-Pufferobjekte. Nur der Speicher wurde vom Client auf die Serverseite verschoben.

Was ist, wenn ich eine Szene mit viel kleinerer Geometrie habe?

Zusammenführen kleinerer Geometriesätze zu größeren VBOs. Es ist kein VBO pro Geometriestapel erforderlich. Sie können Teilmengen eines VBO zum Rendern perfekt adressieren. Verwenden Sie einen Nicht-Stereo-Offset für den Parameter Zeigerdaten.

2) Wenn ich die Daten von der CPU in jedem Frame aktualisiere, kann dies wesentlich schlimmer sein, als wenn ich Vertex-Arrays verwendet hätte?

Hierfür gibt es die Pufferverwendungs-Flags GL_DYNAMIC_DRAW und GL_STREAM_DRAW.

Wenn die Antwort auf eine der oben genannten Fragen "Ja" lautet, warum sollten andere Rendering-Modi, die Vorteile gegenüber VBOs haben könnten, verworfen werden?

Weil es keine Vorteile gibt. Die Geometriedaten müssen in jedem Fall auf die GPU übertragen werden. Die Verwendung eines regulären clientseitigen Vertex-Arrays führt weiterhin zu einer DMA-Übertragung an die GPU, und im unmittelbaren Modus wird ein Stapel erstellt, der ebenfalls zuerst übertragen wird.

Es hat absolut keinen Vorteil, keine VBOs zu verwenden.


Daher sollte meine Leistung bei VBOs im Allgemeinen nicht schlechter sein als bei Vertex-Arrays, sondern nur, wenn ich den Modus korrekt auf GL_STREAM_DRAW gesetzt habe.
Schwerkraft

@ Schwerkraft: In der Tat. Der Puffermodus ist jedoch nur ein Hinweis auf die zu erwartende Verwendung, aber dieser Hinweis sollte natürlich dem entsprechen, was Sie tun werden. Vergessen Sie auch nicht, dass Sie Puffer für Aktualisierungen in Ihren Prozessadressraum abbilden können (glMapBuffer, glUnmapBuffer).
Datenwolf

aber dann konnte der Puffer nicht im VRAM sein, oder? Oder wäre es immer noch im VRAM, aber nur über Prozessraumadressen adressierbar? Wäre ein wahlfreier Zugriff mit dieser Technik günstig, oder sollte ich trotzdem versuchen, nur eine kleine Anzahl zusammenhängender Bereiche zu aktualisieren?
Schwerkraft

@Gravity: Ein Puffer kann schreibgeschützt, schreibgeschützt oder schreibgeschützt zugeordnet werden. Für Updates, die Sie auswählen, schreiben Sie nur. Jetzt wird es wichtig zu wissen, wie moderne Betriebssysteme den virtuellen Adressraum verwalten, und zwar über den ausgelagerten Speicher. Bei einer reinen Schreibzuordnung wird ein Teil des DMA-Übertragungsspeichers zugeordnet, und Ihre Schreibvorgänge in diesen zugeordneten Bereich werden mehr oder weniger direkt in den GPU-Speicher übertragen (der Inhalt wird zuerst in den CPU-RAM geschrieben, dann von DMA an die GPU übertragen) Transfer). Es ist wichtig, dass dies ein direkterer Pfad ist, als wenn die Daten ein clientseitiges Vertex-Array durchlaufen: Der reguläre Prozessspeicher ist für DMA nicht geeignet
datenwolf
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.