Ich lese gerade ein großartiges OpenGL-Tutorial . Es ist wirklich toll, vertrau mir. Das Thema, an dem ich gerade bin, ist Z-Puffer. Neben der Erklärung, worum es geht, erwähnt der Autor, dass wir benutzerdefinierte Tiefentests wie GL_LESS, GL_ALWAYS usw. durchführen können. Er erklärt auch, dass die tatsächliche Bedeutung von Tiefenwerten (die oben sind und welche nicht) auch sein kann angepasst. Ich verstehe soweit. Und dann sagt der Autor etwas Unglaubliches:
Der Bereich zNear kann größer sein als der Bereich zFar; Wenn dies der Fall ist, werden die Fensterraumwerte in Bezug auf das, was dem Betrachter am nächsten oder am weitesten entfernt ist, umgekehrt.
Früher wurde gesagt, dass der Fensterraum-Z-Wert von 0 am nächsten und 1 am weitesten ist. Wenn jedoch unsere Clip-Space-Z-Werte negiert würden, wäre die Tiefe von 1 der Ansicht am nächsten und die Tiefe von 0 am weitesten. Wenn wir jedoch die Richtung des Tiefentests umkehren (GL_LESS zu GL_GREATER usw.), erhalten wir genau das gleiche Ergebnis. Es ist also wirklich nur eine Konvention. In der Tat war das Umdrehen des Z-Zeichens und des Tiefentests einst eine wichtige Leistungsoptimierung für viele Spiele.
Wenn ich es richtig verstehe, ist das Umdrehen des Vorzeichens von Z und des Tiefentests nichts anderes, als einen <
Vergleich in einen >
Vergleich umzuwandeln. Also, wenn ich das richtig verstanden , und der Autor nicht lügt oder Dinge zu machen, dann Wechsel <
zu >
verwendenden eine wichtige Optimierung für viele Spiele.
Erfindet der Autor Dinge, verstehe ich etwas falsch oder ist es tatsächlich so, dass es einmal <
langsamer war ( lebenswichtig , wie der Autor sagt) als >
?
Vielen Dank für die Klärung dieser ziemlich merkwürdigen Angelegenheit!
Haftungsausschluss: Mir ist völlig bewusst, dass die Komplexität von Algorithmen die Hauptquelle für Optimierungen ist. Außerdem vermute ich, dass es heutzutage definitiv keinen Unterschied machen würde und ich bitte dies nicht, um etwas zu optimieren. Ich bin nur extrem, schmerzhaft, vielleicht unerschwinglich neugierig.
Antworten:
Das habe ich nicht besonders gut erklärt, weil es nicht wichtig war. Ich fand es einfach eine interessante Kleinigkeit, etwas hinzuzufügen. Ich hatte nicht vor, den Algorithmus speziell durchzugehen.
Der Kontext ist jedoch der Schlüssel. Ich habe nie gesagt, dass ein <Vergleich schneller ist als ein> Vergleich. Denken Sie daran: Es handelt sich um Tiefenprüfungen der Grafikhardware, nicht um Ihre CPU. Nicht
operator<
.Ich bezog mich auf eine bestimmte alte Optimierung, bei der Sie einen Frame
GL_LESS
mit einem Bereich von [0, 0,5] verwenden würden. Das nächste Bild rendern SieGL_GREATER
mit einem Bereich von [1.0, 0.5]. Sie gehen hin und her und "drehen buchstäblich das Vorzeichen von Z und den Tiefentest um" jedes Bild.Dies verliert ein bisschen an Tiefengenauigkeit, aber Sie mussten den Tiefenpuffer nicht löschen, was früher eine ziemlich langsame Operation war. Da Tiefenreinigung heutzutage nicht nur kostenlos, sondern auch schneller als diese Technik ist, tun es die Leute nicht mehr.
quelle
Die Antwort ist mit ziemlicher Sicherheit, dass das hierarchische Z für jede Inkarnation von Chip + Treiber nur in die eine Richtung funktionierte - dies war damals ein ziemlich häufiges Problem. Low-Level-Assemblierung / Verzweigung hat nichts damit zu tun - Z-Pufferung erfolgt in Hardware mit festen Funktionen und wird per Pipeline übertragen - es gibt keine Spekulationen und daher keine Verzweigungsvorhersage.
quelle
Eine solche Optimierung beeinträchtigt die Leistung vieler eingebetteter Grafiklösungen, da dadurch die Auflösung von Framebuffern weniger effizient wird. Das Löschen eines Puffers ist ein klares Signal an den Treiber, dass er den Puffer beim Binning nicht speichern und wiederherstellen muss.
Wenig Hintergrundinformationen: Ein Kachel- / Binning-Rasterisierer verarbeitet den Bildschirm in einer Anzahl sehr kleiner Kacheln, die in den On-Chip-Speicher passen. Dies reduziert Schreib- und Lesevorgänge in den externen Speicher, wodurch der Verkehr auf dem Speicherbus verringert wird. Wenn ein Frame abgeschlossen ist (Swap wird aufgerufen oder FIFOs werden geleert, weil sie voll sind, sich die Framebuffer-Bindungen ändern usw.), muss der Framebuffer aufgelöst werden. Dies bedeutet, dass jeder Behälter nacheinander verarbeitet wird.
Der Treiber muss davon ausgehen, dass der vorherige Inhalt erhalten bleiben muss. Die Aufbewahrung bedeutet, dass der Behälter in den externen Speicher geschrieben und später aus dem externen Speicher wiederhergestellt werden muss, wenn der Behälter erneut verarbeitet wird. Die Löschoperation teilt dem Fahrer mit, dass der Inhalt des Fachs gut definiert ist: die klare Farbe. Dies ist eine Situation, deren Optimierung trivial ist. Es gibt auch Erweiterungen, um den Pufferinhalt zu "verwerfen".
quelle
Es hat mit Flag-Bits in hoch abgestimmten Baugruppen zu tun.
x86 hat sowohl jl- als auch jg-Anweisungen, aber die meisten RISC-Prozessoren haben nur jl und jz (kein jg).
quelle
for
Schleifen mit einer bedingungslosen Verzweigung rückwärts und einer bedingten, selten genommenen Verzweigung vorwärts schreiben , um die Schleife dann zu verlassen? Klingt unangenehm.