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?
graphics-programming
Gabriele Vierti
quelle
quelle
Antworten:
Ü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.
Wenn ja, warst du erfolgreich.
quelle
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).
quelle
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.
quelle