Werden hardwarebeschleunigte GUI-Daten auf der GPU gespeichert?


8

Ich recherchiere, wie die meisten hardwarebeschleunigten GUI-Bibliotheken funktionieren. Ich kümmere mich eigentlich nur um die Rendering-Backends von ihnen hier. Ich versuche herauszufinden, was der beste Weg wäre, mein eigenes als eine Art Nebenprojekt zu schreiben. Ich versuche hier ultimative Leistung zu erzielen, anstatt übermäßig ausgefallene Funktionen. Ich möchte Primitive, Text und Animationen zeichnen können.

Einige gute Bibliotheken, die ich kenne, sind Qt, Skia und Kairo (obwohl ich nicht sicher bin, wie der Zustand von HWA darauf ist). Ich habe mir auch NanoVG angesehen, eine kleine Bibliothek, die eine anständige Anhängerschaft zu haben scheint. Ich habe es aber nicht geschafft, mit NanoVG eine anständige Leistung zu erzielen ...

Das einzige, was mir aufgefallen ist, war, dass all diese Bibliotheken das Konzept der "Malerei" zu verwenden scheinen, bei dem es scheint, dass jede primitive Form immer wieder von Grund auf neu gezeichnet wird. Damit meine ich, dass es aus den APIs nicht so aussieht, als ob die Formen als "Objekte" auf der GPU oder wie auch immer die Terminologie erstellt und dann "automatisch" gerendert wird. Mit anderen Worten, sie verbleiben nicht im Speicher der GPU, um in einer großen Schleife neu gezeichnet zu werden. Um es näher zu erläutern, scheint es, dass für jedes zu zeichnende Rechteck ein ganzer OpenGL-Status eingerichtet wird, nur um dieses Rechteck zu rendern, und dann wieder zerstört wird. Es sieht jedoch so aus, als würden diese gerenderten Formen zumindest an ihren endgültigen Zielen gerendert, sodass die GPU dann die gesamte Szene zusammenstellen kann.

Ich habe erwartet, dass diese Bibliotheken funktionieren, indem ich die gesamte Szene auf der GPU speichere (entschuldigen Sie die schreckliche Terminologie). Zum Beispiel würden Grundelemente trianguliert und im Speicher belassen, wo nach einem komplizierten Prozess eine Haupt-Rendering-Schleife für die Szene erstellt würde. Darüber hinaus wären dann Mechanismen vorhanden, um Attribute zu aktualisieren oder Grundelemente zu löschen oder hinzuzufügen. Dies ist eine ziemlich vage Beschreibung, aber ich denke, dass Sie auf die Idee kommen.

Was ich jetzt fragen möchte, ist, ob der "Mal" -Ansatz im Vergleich zum "gespeicherten" Ansatz einen Leistungsvorteil hat (wiederum keine Ahnung, ob es Eigennamen für diese Dinge gibt ...). Vielleicht einige komplizierte Caching-Mechanismen? Oder ist es einfach viel einfacher, damit zu arbeiten?

Mir ist klar, dass der "gespeicherte" Ansatz möglicherweise mehr Speicher auf der GPU benötigt, aber sind alle OpenGL-Aufrufe, die für den "Mal" -Ansatz benötigt werden, nicht sehr teuer? Ich denke, man kann dies möglicherweise durch Zwischenspeichern der gerenderten Formen kompensieren, aber bietet die GPU wirklich einen so großen Vorteil, wenn eine solche einmalige (oder nicht sehr regelmäßige) Rasterung im Vergleich zur CPU durchgeführt wird, insbesondere angesichts der Kommunikation Overhead? Stellt dieser Kommunikationsaufwand keine ernsthaften Probleme für Animationen dar, wenn für jeden Frame gezeichnet werden muss?

Ich bin mir ziemlich sicher, dass NanoVG keinen internen Caching-Mechanismus hat, und ich würde annehmen, dass dies für seine eher mangelhafte Leistung verantwortlich sein könnte. Qt hingegen scheint eine hervorragende Leistung zu haben, daher muss es etwas richtig machen. Google scheint auch in der Lage zu sein, Skia gut zu nutzen.

PS. Ich bin kein Profi und habe erst vor kurzem angefangen, OpenGL zu lernen.

EDIT: Eine andere Möglichkeit, an die ich gedacht habe, ist, dass vielleicht der "Mal" -Ansatz nur wegen der Gedächtnisvorteile als notwendig erachtet wurde? Der Grund, warum ich denke, ist, dass all diese Bibliotheken natürlich in einer anderen Ära gestartet wurden und auch auf eingebettete Plattformen abzielen, was bedeutet, dass der GPU-Speicher auf den Zielplattformen (ed) so knapp sein könnte und dass möglicherweise so wenig wie möglich davon verwendet wird wichtiger als Leistung. In einer solchen Situation bin ich jedoch nicht davon überzeugt, dass eine rahmenweise GPU-Rasterung angesichts des Kommunikationsaufwands eine CPU übertreffen wird, insbesondere angesichts der wahrscheinlich geringen Pixelanzahl auf Plattformen mit so wenig Speicher.

Außerdem habe ich auf http://blog.qt.io/blog/2010/01/06/qt-graphics-and-performance-opengl/ gelesen, dass Qt anscheinend Shader-Code aus vorcodierten Segmenten zur Laufzeit vor dem "Malen" und zusammenmischt hofft dann, dass der OGL-Compiler den Code zur Laufzeit richtig einbindet. Das klingt für mich nach noch mehr OGL-Initialisierungsaufwand ...


2
TL; DR; würde hier nicht schaden
Kromster

Antworten:


6

Das Speichern des gesamten Fensters als einzelnes Objekt in der GPU (es wären mehrere Rechtecke, die als VBO gespeichert werden) und das anschließende Rendern in einem einzelnen OpenGL-Draw-Aufruf wäre schnell, hat jedoch mehrere Nachteile:

  • Die gesamte Geometrie müsste mit einem einzigen Shader gerendert werden. Es ist nützlicher, separate Shader zu haben (für undurchsichtige Kopien, transparente Kopien, Farbverläufe usw.).
  • Die gesamte Geometrie kann nur aus einer begrenzten Anzahl von Texturen verwendet werden. Selbst wenn Sie Atlanten verwenden, benötigen Sie viele Texturen für die GUI. (Teile des GUI-Themas, Symbole, Schriftarten, ...)
  • Sie müssen das gesamte Objekt nach jeder Änderung neu erstellen und in die GPU laden.
  • Jedes Widget muss in der Lage sein, ein Stück Geometrie zu erstellen, das schwerer zu abstrahieren ist als 2D-Malerei.
  • Auf einigen GPUs können Sie 2D-Inhalte (Füllen des Bereichs mit Farbe, Kopieren von Bild zu Bild, ...) mit 2D-Befehlen rendern, was schneller ist als mit der 3D-Pipeline.

Wenn Sie es in mehrere Objekte aufteilen, erhalten Sie schließlich einzelne oder wenige Rechtecke pro Objekt. Es ist einfacher und schneller, sie ohne gespeicherte Objekte zu rendern.

GUI-Frameworks verfolgen, welche genauen Teile des Fensters geändert wurden, und malen nur diese neu. Das alte Image wird in der GPU zwischengespeichert. Dieser Ansatz kann mit verschiedenen Zeichnungs-Backends verwendet werden, nicht nur mit OpenGL / DirectX-beschleunigtem Rendering.

Wenn Sie ein Beispiel für eine GUI-Bibliothek überprüfen möchten, die Geometrien generiert, die Sie in OpengGL (oder in eine andere 3D-API) einspeisen können , sehen Sie sich librocket an . Es kann tatsächlich statische Geometrien zusammen backen und sie in einem einzigen Zeichnungsaufruf rendern, aber jedes Element, das sich häufig ändert oder mit einem eigenen Shader gerendert werden muss, muss getrennt bleiben.


OK danke. Wird der gesamte vorherige Frame als Bild zwischengespeichert oder werden alle Elemente in einem Atlas zwischengespeichert? Der Grund, den ich frage, ist, dass ich nicht sehe, wie das Zwischenspeichern des Frames beispielsweise das Übersetzen eines einzelnen Elements unterstützen würde. Einen Atlas zu pflegen wäre natürlich ein großer Aufwand.
Gerharddc

Der gesamte Fensterinhalt wird normalerweise zwischengespeichert. Ich wette, einige GUI-Frameworks zwischenspeichern auch einige Zwischenstufen. Der Inhalt von allem, was scrollbar ist, wäre ein guter Kandidat. Ich denke nicht, dass das Übersetzen in der GUI eine übliche Operation ist, abgesehen von den scrollbaren Bereichen. Die meisten Neulackierungen sind klein und werden durch Widgets verursacht, die sich beim Klicken oder Klicken ändern, Text ändern, ... Dinge wie Dialoge und Menüs sind technisch getrennte Fenster. Moderne Fensterkomponenten sorgen dafür, dass sie ohne Neulackierungen verschoben werden.
michalsrb

Ich denke das macht Sinn. Würde das bedeuten, dass das gesamte Fenster neu gezeichnet werden müsste, wenn ich unerwartet so etwas wie einen Knopf bewegen würde?
Gerharddc

Das hängt wirklich davon ab, wie das spezifische Framework implementiert wird. Es ist jedoch wahrscheinlich, dass das Bewegen einer Schaltfläche eine Art Layout-Aktualisierung auslöst und ein großer Teil des Fensters, wenn nicht ganz, neu gestrichen werden muss.
michalsrb
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.