Woher weiß ich, ob ich Grafik-APIs zu eng abstrahiere?

23

Wenn Sie einen Renderer erstellen, der mehrere Grafik-APIs unterstützt, möchten Sie Ihren Code normalerweise in einer Bibliothek auf niedriger Ebene abstrahieren, die mit einigen Grafik-APIs wie OpenGL, Vulkan, D3D11 usw. verknüpft ist.

Sie arbeiten sehr unterschiedlich voneinander, daher ist es unerlässlich, eine gute generische API zu erstellen. Ich habe gelesen, dass Sie normalerweise ein "Back-End" verwenden möchten, das die grundlegenden Funktionen für jede zu unterstützende API implementiert, und ein "Front-End", das vom Programmierer zum Zeichnen von Inhalten verwendet wird Bildschirm.

Woher weiß ich, ob ich eine zu enge Abstraktion mache?

Gabriele Vierti
quelle
5
Sind Sie zu 100% sicher, dass Ihr Wrapper + Vulkan oder D3D11 schneller ist als immer mit OpenGL?
Mooing Duck
@Mooing Ente wenn richtig verwendet, ja.
Gabriele Vierti
4
Das würde ich ernsthaft bezweifeln. Die meisten Vorteile von Vulkan resultieren daraus, dass man auf sehr niedrigem Niveau arbeitet und die Dinge auf eine sehr spezielle Art und Weise ausführt. Etwas, das generisch genug ist, um es auch in OpenGL oder D3D nahtlos zu machen, kann das mit ziemlicher Sicherheit nicht. Die Neuimplementierung des gleichen Materials wie OpenGL (wie es ironischerweise viele Vulkan-Tutorials tun) führt zu 99,99% der gleichen Leistung bei 20-facher Arbeitsleistung.
Damon
@Damon Das stimmt, aber neuere APIs wurden speziell für die Arbeit mit modernen GPUS entwickelt (und nicht wie OpenGL angepasst ). Wo wir gerade von Vulkan sprechen: Sie können auf jeder unterstützten Plattform so ziemlich die gleiche API verwenden, im Gegensatz zu OpenGL, wo Sie die Version "Embedded Systems" verwenden müssen. Abgesehen von weniger CPU-Overhead und ausgefallenen Funktionen haben wir nicht viel, aber in Zukunft werden wir vielleicht einige ziemlich überraschende Techniken haben, die mit Vk oder D3D12 schneller laufen als mit OGL oder D3D11
Gabriele Vierti

Antworten:

44

Überlegen Sie zunächst, ob es sich tatsächlich lohnt, mehrere Grafik-APIs zu unterstützen. Die Verwendung von OpenGL deckt die meisten Plattformen ab und ist "gut genug" für alle außer den grafisch anspruchsvollsten Projekten. Es sei denn, Sie arbeiten für ein sehr großes Spielestudio, das es sich leisten kann, mehrere Tausend Arbeitsstunden für die Implementierung und das Testen mehrerer Rendering-Backends aufzuwenden, und es sei denn, es gibt einige DirectX- oder Vulcan-spezifische Funktionen, die Sie wirklich zur Schau stellen möchten, ist der Aufwand in der Regel nicht wert . Vor allem, wenn man bedenkt, dass man viel Arbeit sparen kann, wenn man eine Abstraktionsschicht verwendet, die eine andere Person erstellt hat (eine Drittanbieter-Bibliothek oder eine Spiele-Engine).

Nehmen wir jedoch an, Sie haben Ihre Optionen bereits evaluiert und sind zu dem Schluss gekommen, dass es sich lohnt, Ihre eigenen Optionen zu erstellen.

Dann sind die Front-End-Programmierer der Hauptkenner der Softwarearchitektur Ihrer Abstraktionsschicht.

  • Können sie die Spielsysteme implementieren, die sie implementieren möchten, ohne sich über Details auf niedriger Ebene wundern zu müssen?
  • Können sie völlig ignorieren, dass es mehr als eine Grafik-API gibt?
  • Wäre es theoretisch möglich, ein weiteres Rendering-Backend hinzuzufügen, ohne den Frontend-Code zu ändern?

Wenn ja, warst du erfolgreich.

Philipp
quelle
2
Ein weiterer Vorschlag: Ist es wichtig zu betonen, dass das Ziel darin besteht, die in den Aufzählungspunkten genannten Ziele mit minimalem Aufwand zu erreichen - nur das Ziel zu treffen und nicht weiterzugehen? Andernfalls kann aus jedem ein Kaninchenbau für den typischen Entwickler werden, der (einschließlich mir) oft nicht weiß, wann er gut genug in Ruhe lassen soll. :) Und auch, dass der einzige zuverlässige Weg, um den Erfolg zu beurteilen, darin besteht, die API iterativ mit tatsächlichen Benutzern zu entwickeln und zu testen . Es ist unmöglich, genau zu raten, und dies führt zu einem Hasenloch-Szenario der Überentwicklung.
Bob
5
Ich möchte hinzufügen, dass , wenn Sie wirklich haben , um mehrere Grafikbibliotheken zu unterstützen, gibt es mit ziemlicher Sicherheit ein Off-the-shelf ein , dass alles , was Sie brauchen tut, so dass selbst dann Sie wirklich sollten nicht Ihre eigene Rolle. (Natürlich gibt es Ausnahmen, aber wenn Sie unerfahren genug sind, um zu fragen, "wie eng eine Abstraktion sein soll", arbeiten Sie wahrscheinlich nicht an einem Projekt, das Sie dazu auffordert.)
Fund Monicas Klage
Ich bin kein Grafikentwickler, aber angesichts der Kompatibilitäts-Frameworks aus der Geschichte der Datenbanken und Betriebssysteme würde ich hinzufügen, dass es sich mit ziemlicher Sicherheit nicht lohnt, ein eigenes allgemeines Framework zu erstellen. Das Framework muss mit ziemlicher Sicherheit Leistungseinbußen in Bezug auf die Kompatibilität hinnehmen, was wahrscheinlich bedeutet, dass Sie mit diesen speziellen Funktionen sowieso nicht viel anfangen können. Bestehende Frameworks werden diese Probleme mit größerer Sicherheit besser bewältigen, da sie häufiger verwendet werden. Wenn Sie nun über das enorme Budget verfügen, das Sie beschreiben, und ein spezielles Framework erstellen möchten (beispielsweise für ein Spiel oder eine Serie), ist dies möglicherweise praktikabler.
jpmc26
6

Beginnen Sie, indem Sie aus dem "Wrapper" -Teil der API herausfinden, was Sie tatsächlich benötigen. Es ist im Allgemeinen sehr, sehr einfach: Sie benötigen die grundlegenden Ressourcen (Puffer, Shader, Texturen, Pipeline-Status) und eine Möglichkeit, diese Ressourcen zum Erstellen eines Frames durch Übermitteln einiger Draw-Aufrufe zu verwenden.

Versuchen Sie, eine übergeordnete Logik aus dem Wrapper-Teil der API herauszuhalten . Wenn Sie in diesem Teil der API eine clevere Szenen-Culling-Technik implementieren, sind Sie jetzt auf dem richtigen Weg, diese Logik in allen Backend-Implementierungen zu duplizieren. Das ist eine Menge zusätzlicher Aufwand, also halte es einfach. Die Szenenverwaltung sollte Teil eines übergeordneten Teils der API sein der den Wrapper verwendet, anstatt Teil des Wrappers selbst zu sein.

Wählen Sie die Ziele, die Sie unterstützen, und verstehen Sie sie. Es ist schwer, anständige Wrapper für "alles" zu schreiben, und das müssen Sie wahrscheinlich nicht (wohl auch nicht) brauchte eine einzelne Wrapper, entweder zu schreiben, wie es in Philipps Antwort darauf hingewiesen ). Es ist fast unmöglich, einen anständigen Wrapper zu schreiben, wenn Sie nicht wissen, welche APIs Sie bereits einbinden werden.

Bewerten Sie regelmäßig den Status Ihrer API. Es sollte im Allgemeinen eine kleinere Oberfläche als die zugrunde liegenden umhüllten APIs haben. Wenn Sie feststellen, dass Sie eins-zu-eins-Wrapper-Typen für jede D3D-Struktur oder jeden OpenGL-Funktionsaufruf erstellen, sind Sie wahrscheinlich vom Kurs abgekommen.

Schauen Sie sich an, welche Arbeit zuvor geleistet wurde. Sokol und BGFX sind APIs, die einen Grad an Agnostizität bieten, der für Sie nützlich sein kann, und die relativ einfach zu verstehen sind (insbesondere die ersteren).

Josh
quelle
3

Ein weiterer noch nicht genannter Punkt, den Sie berücksichtigen sollten, sind Ihre Leistungsziele. Wenn Sie eine Grafikbibliothek haben möchten, die eine gute Leistung auf einer billigen Hardwareplattform erzielt, aber auch auf einer Vielzahl von Plattformen verwendet werden kann, die wesentlich leistungsfähiger sind, aber eine andere API verwenden, ist es möglicherweise sinnvoll, die API entsprechend zu gestalten Alle Abstraktionen werden nativ auf der Plattform verwendet, auf der die Leistung eine Rolle spielt. Selbst wenn dies auf den leistungsstärkeren Plattformen zu einer Geschwindigkeitsverschlechterung von 50% führt, kann es sich lohnen, wenn auf der Plattform, auf der die Leistung am wichtigsten ist, eine Geschwindigkeitsverbesserung von 20% erzielt wird.

Superkatze
quelle