Ich ging also durch das orange Buch (3. Auflage) und stieß auf einen Abschnitt in Kapitel 9 über den invarianten Qualifizierer. Und es sagt:
Das invariante Qualifikationsmerkmal weist den Compiler an und verknüpft, Ausdrücke und Funktionen zu ignorieren, die nicht direkt mit der Berechnung der Ausgabe zusammenhängen.
Diese Passage kommt nach zwei ähnlichen Codeschnipsel:
%Vor%und
%Vor%Das Buch fährt fort mit:
Der erste Fall kann die transformierten Positionen auf genau die gleiche Weise berechnen oder nicht, unabhängig davon, welche nicht verwandte Funktion oder welcher Ausdruck mit dem Shader verknüpft ist. Dies kann zu Problemen beim Rendern führen, wenn ein Multipass-Algorithmus verwendet wird, um dieselbe Geometrie mehr als einmal zu rendern.
Was mich verwirrt hat. Wenn a()
in keiner Weise die Variablen beeinflusst, die an der Berechnung der transformierten Position beteiligt sind, wie würde dann die Berechnung variieren? (Und wie genau hilft das Hinzufügen von invariant
?). Und was meinen Sie mit Bezug auf das erste Zitat, wenn Sie "die nicht verwandten Funktionen ignorieren"? Werden sie einfach nicht hingerichtet?
Der Zweck von invariant
besteht darin, sicherzustellen, dass die von Ihnen durchgeführte Berechnung immer zu dem gleichen Ergebnis führt, unabhängig davon, was der Shader-Optimierer mit dem Shader macht (insbesondere bei mehreren Shader-Kompilierungen).
Ich finde die Formulierung des orangefarbenen Buches schlecht (und irreführend, wie Sie bemerkt haben). Die GLSL-Spezifikation (Sprache 1.2) Abschnitt 4.6 ist viel klarer:
In diesem Abschnitt bezieht sich die Varianz auf die Möglichkeit des Erhaltens verschiedene Werte von demselben Ausdruck in verschiedenen Programmen. Zum Beispiel, zwei Vertex-Shader, in verschiedenen Programmen, jeder Satz gl_Position mit dem gleichen Ausdruck in beiden Shadern und der Eingabe Werte in diesem Ausdruck sind identisch, wenn beide Shader ausgeführt werden. Es ist möglich, aufgrund der unabhängigen Zusammenstellung der beiden Shader, dass die Werte, die gl_Position zugewiesen sind, stimmen nicht genau überein Shader laufen. In diesem Beispiel kann dies zu Problemen bei der Ausrichtung führen Geometrie in einem Multi-Pass-Algorithmus. Im Allgemeinen, solche Varianz zwischen Shadern ist erlaubt. Wenn eine solche Abweichung für a nicht existiert bestimmte Ausgabevariable, diese Variable wird als invariant bezeichnet.
und es wird erklärt, dass der Qualifier invariant
Ihnen Garantien gibt, um dieses Problem zu vermeiden.
invariant
keyword ist (kurz und im Gegensatz zu Bahbars ausführlicherer Antwort) mehr über sehr subtile Berechnungsunterschiede, die in, wie Sie erwähnt haben, mehreren Geometriedurchläufen auftreten können.
Hier ist ein Beispiel: Sie zeichnen ein beliebiges, seltsames (um es schwieriger zu machen) Dreieck auf dem Bildschirm. Der Rasterizer erhält normalisierte Scheitelpunkte und berechnet alle Fragmente, die er einnimmt, und führt dann einen Fragment-Shader auf ihm aus. Stellen Sie sich nun vor, Sie möchten ein weiteres Dreieck genau darüber zeichnen, aber 3 Stunden später, während Ihr PC unter Wasser ist, sinkt die Temperatur und Sie essen in der Zwischenzeit ein Mittagessen. Du kompilierst die Shader dann und bam ...
Alle diese Faktoren können sich potenziell auf den Rasterizer auswirken. Shader-Optimierungen können sich auswirken und die Ausgabe negativ verändern. Obwohl das Ergebnis immer noch technisch korrekt ist, muss das Ergebnis nicht unbedingt genau dasselbe wie das erste Dreieck sein, und "die Probleme" werden einige Pixel vom ersten übrig sein.
invariant
stellt sicher, dass ein potenziell langsamerer Ansatz gewählt wird. Ich bin zwar kein Treiberarchitekt, aber im Allgemeinen könnte das ein paar zusätzliche Statusresets, Aufräumarbeiten oder manchmal State-Stack-Push / Pops bedeuten. Nur dann bleibt der "saubere" Rechenstatus erhalten, und solange Ihre Hardware in Ordnung ist, sollte das Ergebnis genau gleich sein.
Tags und Links opengl