Was ist der richtige Weg, um Daten in einem Frame-Puffer zu speichern?

Ich versuche, ein Grafikprozessorprojekt zu planen, das nur Linien rendert. Es wird der Zeilenalgorithmus von Bresenhmam verwendet. Nachdem Sie den Algorithmus gelesen haben, ist es sinnvoll, wie er funktioniert, um Pixelpositionen zu berechnen, aus denen eine Linie besteht. Unklar ist, wie dies auf einem Bildschirm ausgegeben wird. Vielleicht werden die Daten wahrscheinlich in einem externen Speicher gespeichert, aber der offensichtliche Weg, dies zu tun, erscheint höchst ineffizient.

Angenommen, ich habe 10 Zeilen. Ich berechne die Pixelwerte, die jede dieser Zeilen bilden, speichere ich diese Pixel in einem internen FIFO für den "Versand"? Dann liest ein anderer Teil des Entwurfs die zu "verteilenden" Pixelwerte, berechnet, an welcher Stelle sie im Speicher gespeichert werden sollen, und schreibt sie in den Speicher. Dies muss für jede Zeile erfolgen, was bedeutet, dass eine Speicherstelle mehrere Male für einen einzelnen Rahmen gelesen und beschrieben werden kann, wenn mehrere Zeilen nahe beieinander verlaufen. Ist das richtig? Wenn dies der Fall ist, wird es mit zunehmender Anzahl zu zeichnender Zeilen schwieriger, ein Vollbild in den Speicher zu schreiben, indem alle Zeilen gerendert werden, bevor das nächste Bild ausgelesen werden muss, da die Bildrate für die Videoanzeige festgelegt ist.

Das bedeutet, dass es keine Möglichkeit gibt, vom Bildschirmpixel oben links nach unten rechts zu gehen und herauszufinden, ob ein bestimmtes Pixel Teil einer Zeile ist. Ich kann keine einfache Erklärung dafür finden, wie der Frame-Puffer für diese Art von System implementiert wird.

Ich bin mir nicht sicher, ob dieser Ansatz der einfachste ist, es sei denn, es gibt eine sehr begrenzte Anzahl von Zeilen. Traditionell hat ein Display-Controller einen Bildspeicher, der alle Pixelfarben unabhängig darstellt, und Sie zeichnen dann Linien innerhalb dieses Puffers. Aber den Controller zu haben, der sich um das Rendern der Zeilen kümmert, während die Aktualisierung abgeschlossen ist, ist meiner Meinung nach schwierig.
@ quantum231: Sie benötigen eine doppelte Pufferung. Das heißt, ein Bildschirmpuffer wird gerendert, während der andere ausgelesen wird. Sobald das Rendern abgeschlossen ist, schalten Sie die beiden beim nächsten Vsync um. Das Rendern nach aktueller Rasterlinie ist möglich (siehe alte Heimcomputer), bringt aber viele Einschränkungen mit sich.
Sie gehen nicht von oben links ... und finden heraus, ob ein Pixel Teil einer Zeile ist, sondern Sie stoßen für jede Zeile die Pixel an, aus denen diese Zeile besteht, während Sie entlang der Zeile iterieren, die Sie automatisch erzeugen Pixeladressen müssen Sie nichts berechnen, nicht wenn Sie Ihre Zeilen- und Spaltenadressierung richtig angeordnet haben. Die Arbeit skaliert linear mit der Gesamtlänge der Linie, die Sie rendern müssen.
Haben Sie sich jemals gefragt, warum Spiele mit komplizierter Grafik auf schlechteren Computern mit niedrigeren Frameraten laufen? Jetzt weißt du genau warum.

Antworten (1)

Wenn Sie die Pixel in jeder Zeile ausarbeiten, würden Sie die Bits im Frame-Puffer berechnen, die für dieses Pixel eingestellt werden sollen. Dies würde von der Rahmenpufferorganisation und der Anzahl von Bits pro Pixel abhängen. Da Sie vorschlagen, 10 überlappende Linien zu zeichnen, bedeutet dies, dass auf dieselbe Adresse mehrmals zugegriffen wird. Wenn die Anzahl der Linien zunimmt, können Sie möglicherweise nicht alle Linien vor dem Frame-Scan zeichnen.

Dies wirkt sich jedoch nicht auf den Zeichenprozess aus und Sie müssen den Renderprozess nicht abschließen, bevor das Bild an den Bildschirm gesendet wird, aber es führt zu einem Flimmern. Tatsächlich wird es flackern und hier würde ein zweiter Puffer verwendet werden.

Bild Sie haben eine komplizierte Form auf den Bildschirm gezeichnet, die um 5 Grad gedreht werden muss. Die Anzeige erhält die Informationen aus Puffer 1. Sie berechnen die neuen Zeilen und schreiben in Puffer 2, während Puffer 1 weiterhin angezeigt wird. Wenn Sie fertig sind, warten Sie, bis die letzte Zeile aus dem aktuellen Puffer 1 angezeigt wird, und schalten die Anzeigelogik so weiter Beim nächsten Scan wird Buffer2 angezeigt. Alle weiteren Schreibvorgänge erfolgen dann in Puffer 1, bis zum Zurückschalten bereit ist.

Aus diesem Grund kann es bei typischen Spielebenchmarks vorkommen, dass die Bildraten in komplizierten Szenen auf 12 fps sinken. Nicht, weil die Anzeige von 60fps abfällt, sondern weil derselbe Frame fünfmal angezeigt wird, bevor der neue Frame gezeichnet werden kann.