Was ist der Vorteil des OpenGL-Direktzugriffsmechanismus?


11

Ich habe auf opengl.org über OpenGL 4.5 Direct State Access (DSA) gelesen und bin mir nicht sicher, ob ich es richtig mache.

Es scheint zu implizieren, dass der alte Weg weniger effizient ist:

glBind(something)
glSetA(..)
glSetB(..)
glSetC(..)

als der neue Weg:

glSetA(something, ..)
glSetB(something, ..)
glSetC(something, ..)

So wie es aussieht, muss jetzt jeder glSetdarin enthalten sein glBind(something), und wenn OpenGL immer noch eine Zustandsmaschine ist, können gestreamte Änderungen, die auf eine einzelne angewendet werden, nicht genutzt werden something.

Bitte erläutern Sie die Gründe und Vorteile des neuen DSA.

Antworten:


21

So wie es jetzt aussieht, muss jedes glSet glBind (etwas) enthalten

Nicht genau. Es ist umgekehrt, wie in den folgenden Abschnitten beschrieben.

Denken Sie auch dann daran, dass GL-Befehle von der Client-App an den GL-Server (auch als Treiber bezeichnet) im Vergleich zu einem regulären Funktionsaufruf einen hohen Versandaufwand haben. Selbst wenn wir davon ausgehen, dass die DSA-Funktionen nur Wrapper um vorhandene Funktionen sind, handelt es sich um Wrapper, die sich im GL-Server befinden und daher (etwas) weniger Overhead haben können.

Wenn OpenGL immer noch eine Zustandsmaschine ist, können gestreamte Änderungen, die auf ein einzelnes Objekt angewendet werden, nicht genutzt werden.

GPUs sind keine Zustandsautomaten. Die GL-Zustandsmaschinenschnittstelle ist eine Emulation, die DSA-ähnliche Treiberinternale umschließt, nicht umgekehrt.

Das Entfernen einer Wrapping-Schicht - eine Schicht, die eine übermäßige Anzahl von Anrufen auf dem GL-Server erfordert - ist eindeutig ein Gewinn, auch wenn es sich um eine kleine handelt.

Der State-Machine-Ansatz macht auch beim Umgang mit mehreren Threads nicht viel Sinn. GL ist in diesem Anwendungsfall immer noch schrecklich, aber Treiber verwenden häufig Threads hinter den Kulissen, und eine Zustandsmaschine erfordert viel Thread-Synchronisation oder wirklich ausgefallene parallele Algorithmen / Konstrukte, damit die Dinge zuverlässig funktionieren.

Die DSA-Erweiterung formuliert ihre Funktionsweise weiterhin in Bezug auf Statusänderungen, da es sich schließlich um eine Erweiterung eines vorhandenen zustandsbasierten Dokuments und nicht um eine völlig neue API handelt. Daher musste sie bereit sein, sich in die vorhandene GL-Spezifikation einzufügen Sprache und Terminologie des Dokuments. Auch wenn diese vorhandene Sprache für ihre Aufgabe als moderne Grafikhardware-API ziemlich gut geeignet ist.

Bitte erläutern Sie die Gründe und Vorteile des neuen DSA.

Der größte Grund ist, dass der alte Weg ein Schmerz war. Es machte es sehr schwierig, Bibliotheken zusammenzustellen, die jeweils den GL-Status ändern oder sich darauf verlassen könnten. Es machte es schwierig, die GL-API in einem objektorientierten oder funktionalen Stil effizient zu verpacken, da die Wurzeln des prozeduralen Statusmanagements tief verwurzelt waren, was das Verpacken der API in verschiedene Nicht-C-Sprachen schwierig machte und es auch schwierig machte, effiziente Wrapper für Grafikgeräte bereitzustellen diese abstrakte OpenGL von Direct3D.

Zweitens war der prozedurale State-Machine-API-Overhead, wie zuvor beschrieben.

Drittens haben die DSA-Funktionen die Semantik gegebenenfalls gegenüber den alten APIs geändert, die eine verbesserte Effizienz ermöglichten. Dinge, die zuvor veränderlich waren, wurden zum Beispiel unveränderlich gemacht, wodurch viel Buchhaltungscode vom GL-Server entfernt wurde. Anrufe von der Anwendung können an die Hardware gesendet oder früher (oder paralleler) validiert werden, wenn der GL-Server nicht mit veränderlichen Objekten umgehen muss.

- -

Zusätzliche Begründungen und Erläuterungen finden Sie in der Erweiterungsspezifikation EXT_direct_state_access .

- -

Hardwareänderungen, die für das API-Design relevant sind, sind ziemlich zahlreich.

Denken Sie daran, dass OpenGL aus dem Jahr 1991 stammt. Die Zielhardware waren keine Consumer-Grafikkarten (diese gab es nicht), sondern große CAD-Workstations und dergleichen. Die Hardware dieser Ära hatte ganz andere Leistungsbereiche als heute; Multithreading war seltener, Speicherbusse und CPUs hatten eine geringere Geschwindigkeitslücke, und die GPU leistete kaum mehr als das Rendern von Dreiecken mit festen Funktionen.

Es wurden immer mehr Funktionen mit festen Funktionen hinzugefügt. Es wurden verschiedene Beleuchtungsmodelle, Texturmodi usw. hinzugefügt, von denen jedes seinen eigenen Zustand benötigt. Der einfache staatsbasierte Ansatz funktionierte, wenn Sie eine Handvoll Staaten hatten. Als immer mehr Zustände hinzugefügt wurden, begann die API aus allen Nähten zu platzen. Die API wurde umständlicher, weicht jedoch nicht zu weit von den Hardwaremodi ab, da sie tatsächlich auf vielen Statuswechseln basieren.

Dann kam programmierbare Hardware. Die Hardware ist immer programmierbarer geworden, bis zu dem Punkt, an dem die Hardware jetzt einen kleinen Status, einige vom Benutzer bereitgestellte Programme und viele Puffer unterstützt. All dieser Zustand aus der vorherigen Ära musste emuliert werden, genauso wie alle Funktionen mit festen Funktionen dieser Ära von den Fahrern emuliert wurden.

Auch die Hardware wurde immer paralleler. Dies erforderte andere Hardware-Redesigns, die Änderungen des Grafikstatus sehr teuer machten. Die Hardware arbeitet in großen Blöcken mit unveränderlichem Zustand. Aufgrund dieser Änderungen konnte der Treiber nicht einfach jedes kleine Stück des vom Benutzer sofort festgelegten Status anwenden, sondern musste die Änderungen automatisch stapeln und bei Bedarf implizit anwenden.

Moderne Hardware arbeitet noch weiter vom klassischen OpenGL-Modell entfernt. DSA ist eine kleine Änderung, die vor mehr als 10 Jahren benötigt wurde (ursprünglich als Teil von OpenGL 3.0 versprochen), ähnlich wie D3D10. Viele der oben genannten Hardwareänderungen erfordern weit mehr als nur DSA, um OpenGL relevant zu halten, weshalb noch mehr große Erweiterungen verfügbar sind, die das OpenGL-Modell drastisch ändern . Dann gibt es die ganz neue GLnext-API plus D3D12, Mantle, Metal usw., von denen keine die veraltete Abstraktion der Zustandsmaschine beibehält.


Danke für die Antwort. Es scheint also, dass vor einem bestimmten Zeitpunkt die Zustandsmaschine (Nicht-DSA) ein Gewinn war, aber irgendwann hat sich etwas geändert, und jetzt ist DSA von Vorteil. Können Sie etwas Licht ins Dunkel bringen, was sich geändert hat?
Kromster

@KromStern: habe mein Bestes gegeben. Wenn Sie mehr Details benötigen, muss jemand, der besser informiert ist als ich, diese liefern.
Sean Middleditch

@KromStern Ich habe gesehen (aus meiner begrenzten Forschung in der Geschichte), dass openGL zu immer weniger Draw Calls CPU-Seite pro Frame übergeht; Anzeigelisten (für das, was sie wert waren), glDrawArrays (in einem Aufruf zeichnen), VBOs (einmal auf GPU hochladen), VAOs (einmal Puffer an Attribute binden), einheitliches Pufferobjekt (Uniformen auf einmal festlegen). Ich bin mir sicher, dass mir noch mehr fehlt.
Ratschenfreak

@ratchetfreak: Lustigerweise bewegen wir uns jetzt in die andere Richtung. Die modernen APIs / Erweiterungen konzentrieren sich darauf, unsere Draw-Aufrufe pro Frame zu erhöhen, hauptsächlich indem der gesamte Status entfernt wird, der pro Draw-Aufruf festgelegt / versendet werden muss, und die Draw-Aufrufe kaum mehr als "Draw-Befehl in Befehlswarteschlange einfügen" gegen eine große Anzahl ausführen Satz von statischen Status und bindless Ressourcen. Oooh, unverbindlich, ich habe vergessen, diesen Teil in meiner Antwort überhaupt zu erwähnen.
Sean Middleditch

@ SeanMiddleditch Ich hätte Anrufe pro Frame setzen sollen.
Ratschenfreak

1

Die Übersicht begründet dies mit:

Mit dieser Erweiterung sollen Bibliotheken effizienter werden, um eine Störung des Selektors und des verriegelten Zustands zu vermeiden. Die Erweiterung ermöglicht auch eine effizientere Verwendung von Befehlen, da keine Selektoraktualisierungsbefehle erforderlich sind.

Ich denke, "effizienter" bezieht sich hier sowohl auf einen geringeren Buchhaltungsaufwand für Bibliotheksautoren als auch auf eine daraus resultierende höhere Leistung. Mit der aktuellen API müssen Sie den Status abfragen, ihn speichern, den Status ändern, um das zu tun, was Sie benötigen, und dann den ursprünglichen Status wiederherstellen, um sich "gut zu benehmen".

Mögen

oldState = glGet()
glBind()
glDoThings...
glSet(oldState)  // restore, in case anyone needs it just as they left it

Vermutlich könnte ältere Hardware mit der expliziten API zur Statusänderung leistungsfähiger gemacht werden. Ansonsten ist es ein ziemlich seltsames Ritual. Diese Erweiterung impliziert (und sehen Sie sich nur die Autorenliste an!), Dass das Vermeiden des Abrufens, Setzens und Wiederherstellens von Tanz auf der aktuellen Hardware jetzt eher ein Leistungsgewinn ist, selbst wenn der zusätzliche Parameter bei jedem Aufruf verwendet wird.


"müssen abfragen / verstauen / ändern / wiederherstellen" - wie ist es besser mit DSA?
Kromster

..addierter Pseudocode zum Anzeigen. Mit DSA ist nichts davon notwendig. Vermutlich benötigt die aktuelle Hardware nicht wirklich den "Bindungsstatus", sondern kann bei Bedarf einfach auf alles zugreifen.
David van Brink

Die Kette get/bind/do/setwird selten verwendet, da 'Get' sehr langsam ist. Normalerweise müssen Apps die Replik der Variablen ohnehin beibehalten, sodass sie auf nur noch reduziert werden bind/do. Ich verstehe den Punkt.
Kromster

2
@krom vom Treiberstatus abrufen kann schnell sein, ein Teil des abrufbaren Status hat nichts mit der GPU zu tun, so dass es nur aus dem RAM abgerufen werden kann, der schnell ist.
Ratschenfreak
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.