Was macht ddx (hlsl) eigentlich?

17

Ich bin ein bisschen verwirrt. Die offizielle Dokumentation ( http://msdn.microsoft.com/en-us/library/windows/desktop/bb509588(v=vs.85).aspx ) besagt, dass DDX (Eingabe) die partielle Ableitung der Eingabe in Bezug auf auf die "Bildschirm-Raum-X-Koordinate".

Mein Kalkül ist in Ordnung, aber wie kann es erkennen, woher die Eingabe kommt? Wenn ich eine Funktion übergeben würde, kann ich mir gut vorstellen, was sie tun würde, aber die Ableitung einer Zahl ist immer Null ...?

Ist es nur eine Skalierung? Wie würde dies auf ein Zehntel seiner Größe in dieser Entfernung skaliert, so dass es ein Zehntel zurückgibt? Aber dann braucht es keine Eingabe ...

Kann jemand kurz erklären, was tatsächlich passiert?

Richard Rast
quelle
2
ddxund ddyzaubere, was du selbst nicht kannst. Sie haben Zugriff auf zusätzliche Informationen aus der Rasterisierungs-Pipeline, die Sie in einem Pixel-Shader nicht abrufen können. Ich weiß nicht genau, welche Formel sie verwenden. Man hat mich glauben lassen, dass sie eine Schätzungstechnik verwenden, aber ich weiß es nicht genau.
Sean Middleditch
Das ist zutiefst komisch, aber immer noch. Was repräsentiert eigentlich ddx (5)? Wenn es .1 sagt, wie soll ich das interpretieren? Oder -6?
Richard Rast
1
ddx(5)ist irgendwie sinnlos. Verwenden Sie ihn mit einem Eingabewert. Dadurch erhalten Sie die Ableitung dieses Werts in Bezug auf benachbarte Pixel in einem Block. Auch hier weiß ich nicht, wie genau es Werte berechnet, aber die Abfrage nach der Ableitung einer Nicht-Eingabe kann einfach undefiniertes Verhalten sein und Müll produzieren. Weitere Informationen finden Sie unter fgiesen.wordpress.com/2011/07/10/… .
Sean Middleditch
Ich bin nicht sicher, aber es kann durchaus sein, dass der HLSL-Compiler tatsächlich eine vollständige symbolische Differenzierung des Ausdrucks vornimmt, den Sie an ddx / ddy übergeben. blogs.msdn.com/b/chuckw/archive/2011/03/08/… research.microsoft.com/pubs/146019/…
Ziriax
Was tut es? Das EINZIGE etwas vernünftige Ding, offensichtlich.
MickLH

Antworten:

32

Intern führen GPUs niemals jeweils eine Instanz eines Pixel-Shaders aus. Bei höchster Granularität werden unter Verwendung einer SIMD-Architektur immer 32-64 Pixel gleichzeitig ausgeführt. Innerhalb dieses Bereichs sind die Pixel weiter in 2x2-Quadrate unterteilt, sodass jede Gruppe von 4 aufeinanderfolgenden Pixeln im SIMD-Vektor einem 2x2-Pixelblock auf dem Bildschirm entspricht.

Ableitungen werden berechnet, indem Differenzen zwischen den Pixeln in einem Quad genommen werden. Zum Beispiel ddxwerden die Werte in den Pixeln auf der linken Seite des quad aus den Werten auf der rechten Seite subtrahieren, und ddywerden die unteren Pixel vom oberen diejenigen subtrahieren. Die Differenzen können dann als Ableitung zu allen vier Pixeln im Quad zurückgegeben werden.

Da der Pixel-Shader in SIMD ausgeführt wird, ist garantiert, dass der entsprechende Wert für alle Pixel im Quad zur gleichen Zeit im gleichen Register gespeichert ist. Unabhängig davon, welchen Ausdruck oder Wert Sie in ddxoder ddyeingeben, wird er in allen vier Pixeln des Quadrats ausgewertet, und anschließend werden die Werte von verschiedenen Pixeln wie oben beschrieben subtrahiert.

Wenn Sie also die Ableitung eines konstanten Werts nehmen, erhalten Sie eine Null (wie Sie es von der Kalkulation erwarten würden, oder?), Weil es in allen vier Pixeln der gleiche konstante Wert ist.

Beachten Sie auch, dass es "grobe" und "feine" Derivate gibt, ddx_coarse/ ddy_coarseund ddx_fine/ ddy_fine. Eine Erklärung der Unterscheidung wird hier gegeben . Nur schlicht ddx/ ddysind Aliase für die groben Versionen.

Übrigens besteht der Grund für diese Funktionalität darin, dass GPUs intern Ableitungen von Texturkoordinaten verwenden müssen, um eine Mipmap-Auswahl und eine anisotrope Filterung durchzuführen. Da die Hardware diese Funktion sowieso benötigt (Sie können jeden beliebigen Ausdruck für Texturkoordinaten in einem Shader verwenden), war es einfach genug, sie auch Shader-Programmierern direkt zur Verfügung zu stellen.

Nathan Reed
quelle
+1; Ich habe dies für nützlich befunden, wenn eine Textur mit einem Störungseffekt versehen wurde. Die gestörten Texcoords zeigten eine gewisse Farbverzerrung, aber die Verwendung von tex2Dgrad mit Derivaten der ursprünglichen (ungestörten) Texcoords ergab ein unverzerrtes Ergebnis.
Maximus Minimus
Okay, nach einigem Überlegen habe ich meine Verwirrung herausgefunden. In meinen Augen ddxfunktioniert wie jede andere Funktion in einer traditionellen Programmiersprache; Sie werten die Eingabe aus, verwandeln sie in ein Float oder was auch immer und führen dann die Funktion outside ( ddx) aus. Aber das ist anders- sie die Eingabe nimmt Zeichenfolge , wertet sie an mehreren Stellen, berechnet ein Derivat, und meldet das Ergebnis. Ist das ungefähr richtig?
Richard Rast
1
@RichardRast Richtig. Sie können sich vorstellen , eher ddxden Ausdruck zu bearbeiten, den Sie übergeben, als den Wert .
Nathan Reed
Aber sehen Sie, das ist schon komisch genug, dass es in der Dokumentation sein sollte. Ich kann mir keine andere Zeit in meinem Programmierleben vorstellen, in der dies der Fall war.
Richard Rast
Nathan Reed erwähnte, dass GPUs diese Funktionen für die Auswahl von Mipmaps verwenden. Sie können sie auch verwenden, um die GPU zu zwingen, eine gewünschte Mipmap-Ebene auszuwählen, oder um zu verhindern, dass Artefakte eine falsche Auswahl auf Mip-Ebene vornehmen. Der Vorgang ist auf den Seiten 163 und 164 von Shader X3 beschrieben.
JamesHoux