Zum 3DCenter Forum
Inhalt




Das Floating-Point-Format im Detail

Teil 3 von 3 / 15. März 2004 / von aths / Seite 13 von 13


   Ein Blick in die Zukunft

Wann bekommen wir den Floating-Point-Framebuffer? Vorerst wohl nicht, denn um das Endergebnis zu speichern, reichen 8-8-8 Bits für die Farbinformation fast "für immer" aus. Eher wird der Framebuffer zunächst für 10-10-10 Bit Farbe organsiert. Das können einige Karten schon heute, doch dieses Feature ist weder weit verbreitet, noch wird es breit genutzt. Der Vorteil von 30 Bit Farbe (statt 24) liegt nicht in den zusätzlichen Farben, die das Auge ohnehin nicht mehr unterscheiden kann, sondern darin, dass es nun über 1000 Helligkeitsstufen pro Grundfarbe gibt. Das kommt unserer Empfindlichkeit für feine Schattierungen entgegen.

In gewissem Sinne gibt es die 10 Bit Fixpoint schon heute: Die 8-Bit-Information pro Farbkanal wird bei aktuellen Karten auf 10 Bit aufgebläht, bevor die (von der CPU vorberechnete und auf der Grafikkarte gespeicherte) Gamma-Tabelle appliziert wird. Wenn man 256 Intensitäten auf 256 andere Intensititäts-Stufen abbildet, aber insgesamt nur 256 Stufen hat, gibt es einerseits natürlich zwangsläufig "Löcher", auf der anderen Seite fallen mehrere Stufen zusammen. In der Tat bewirkt die Gamma-Korrektur bei älteren Grafikkarten bestimmte Color-Banding-Artefakte. Bildet man 256 Werte aber auf mögliche 1024 Stufen ab, kommt es praktisch nie dazu, dass zwei unterschiedliche Helligkeitswerte nach der Gamma-Korrektur die gleiche Intensität aufweisen. In Zukunft könnten auch 11- oder 12-bittige RAMDAC-Logiken verwendet werden. Die Windows-GUI sieht bis zu 16 Bit für die Gamma-Tabelle vor.

Dass man mit 8 Bit pro Farbkanal auch in Zukunft überhaupt einigermaßen auskommt, wo die Shader doch immer komplexer werden, liegt darin begründet, dass man dank der heute möglichen Programm-Längen für Shader meistens ohne Zwischenspeichern auskommt - Zwischenergebnisse in den Framebuffer zu schreiben und wieder einzulesen geht nicht nur auf die Performance, sondern natürlich auch auf die Genauigkeit. Anstatt mit Floating-Point-Rendertargets zu arbeiten (was teilweise gemacht wird), sollte man versuchen, ein Pixel immer in einem Rutsch zu rendern.

Pixelshader 2.0 bietet nur 64 arithmetische Instruktionen, das kann bei komplizierten Shadern schon knapp werden. Pixelshader 2.X erlaubt immerhin über 500, mit Pixelshader 3.0 sind - je nach konkreter Hardware - über 32000 möglich (4.0er Shader werden diesbezüglich gar kein Limit mehr setzen). Die nähere Zukunft wird wohl erst einmal von der 3.0er Version dominiert sein, wo der Pixelshader insgesamt mindestens 512 Instruktionen anbieten muss, das reicht auf 2-3 Jahre aus. Der große Vorteil liegt darin, dass mit 3.0 bedingte Sprungbefehle möglich sind. Das heißt zum Beispiel, dass es einfacher wird, verschiedene Lichtquellen (und Material- und Beleuchtungs-Kombinationen) in einen Shader zu packen. ATI wird mit dem neuen R420 zwar keinen Pixelshader 3.0 vorweisen können, aber ebenfalls Programmlängen von bis zu 512 Befehlen erlauben. Jedes Pixel möglichst in einem Rutsch zu rendern, sollte damit machbar sein.

Die Shader-Rechnungen selbst werden mit Floating-Point-Zahlen durchgeführt, für das Endergebnis reicht Fixpoint. Wenn man, aus welchen Gründen auch immer, Multipass-Rendering macht, sind Floating-Point-Zwischenspeicher natürlich dringend anzuraten. Hierzu kann der Umweg über eine Floating-Point-Textur genommen werden. Schöner wäre ein FP-Framebuffer mit 64 Bit. Die Speicherbandbreiten-Anforderungen wären allerdings gigantisch.

Bliebe noch zu fragen, in welchem Format die Input-Daten vorliegen. Momentan nämlich praktisch immer nur als Fixpoint-Textur. Als Floating-Point-Zahl bekommt man zwar so genannte Normalenvektoren und Materialfarben, aber nur pro Eckpunkt jedes Dreiecks (die Farbe wird allerdings über das gesamte Dreieck interpoliert, so dass man sie pro Pixel hat - festlegen lässt sich eine Farbe aber nur für Eckpunkte des Dreiecks). Man braucht ganz klar über kurz oder lang auch FP-Texturen. Die gibt es seit DirectX9 auch, konkret wird meistens FP16 dafür genutzt.

Dieses Format schlägt mehrere Fliegen mit einer Klappe: Man kann ein Vorzeichen verwenden, was bei FX8 durchaus möglich, aber schwierig ist. Die Farben werden mit FP16 achtmal feiner aufgelöst gegenüber FX8 (gegenüber vorzeichenbehaftetem FX8 sogar 16 mal feiner). Zudem kommt man in den Genuss von MDR (Medium Dynamic Range), kann also Zahlen speichern, die weitaus größer als 1,0 sind. Das geht prinzipiell auch mit herkömmlichen Texturen, die Farb-Werte lassen sich ja im Pixelshader hochskalieren, doch Spaß macht das nicht: Angenommen, man skaliert um Faktor 8 hoch, um bis zur 8,0 Werte darstellen zu können. Dann bleiben gerade mal 5 "Nachkommastellen", also 32 Abstufungen.

Anders mit FP16: Da 11 signifkante Bit-Stellen zur Verfügung stehen, bleiben nach der Skalierung um drei binäre Stellen noch acht Nachkommastellen, also 256 Abstufungen. Texturen könnten auch FP32 pro Kanal nutzen, die Zahlenwerte werden von ATIs Hardware für die interne Verrechnung dann natürlich ins FP24-Format "komprimiert". Dabei geht Genauigkeit verloren, wobei allerdings nicht davon auszugehen ist, dass man für Effekte in Spielen auf absehbare Zeit FP32-Texturgenauigkeit braucht.

Leider bieten heutige TMUs noch keinen Filter-Support für FP-Texturen an. Um trotzdem bilineare Samples zu gewinnen, muss der Pixelshader bemüht werden. Das geht natürlich stark auf die Performance. Für Bildinhalte sind FP-Texturen nicht unbedingt notwendig, als Lookup-Tabelle für mathematische Funktionen hingegen oft sinnvoll. Leider unterstützen einige Grafik-Chips nur monochrome FP32-, bzw. zweikanalige FP16-Texturen. Wenn TMUs dereinst auch FP16-Farben verarbeiten und filtern können, wird das den Einsatz von FP16-Texturen für Zwecke wie zum Beispiel IBL (Image-based Lighting) performant und damit sinnvoll machen. Irgendwann, wenn die TMU als diskrete Schaltgruppe verschwindet, wird es wohl auch einmal FP32-Filterung geben.

Wir möchten abschließend noch mal das Thema "The right tool for the right job" ansprechen. Gerenell FP16 für Texturen zu nehmen, wäre klar übertrieben: Das FX8-Format reicht für das meiste aus, und spart sowohl Speicherplatz als auch Bandbreite. Um Farbwerte mit einfachen Operationen zu verrechnen, ist FP16 gerade richtig. Möchte man schönes Bump-Mapping machen, oder Textur-Adressierungs-Operationen durchführen, wäre FP24 anzuraten - mindestens!

FP32 bietet hingegen Genauigkeits-Reserven, die man bei FP24 vermisst. Dass ATI im Pixelshader durchgehend auf FP24 setzt, was einerseits "zu gut", andererseits aber an der Grenze ist, hat aber den Vorteil, dass kaum Format-Umrechnungen stattfinden müssen. Solche Konvertierungen erfordern zusätzliche Stages in der Pipe, wodurch sie gestreckt wird. Wir vermuten, dass der nVidia NV40 weiterhin Performance-Vorteile aus der Verwendung von FP16 ziehen wird. Die Entwickler stehen damit vor zwei Herausforderungen: Wenn sie für GeForceFX optimieren, müssen sie testen, für welche Register FP16 ausreicht. Wenn sie für Radeon optimieren, müssen sie prüfen, ob FP24 garantiert noch keine Artefakte erzeugt. So oder so, Floating-Point-Zahlen werden uns in der Zukunft immer öfter begegnen.


Für diesen Artikel wurde unter anderem auf folgende Quellen zurück gegriffen: nVidia: Texture-Shader (OpenGL), Sun: Dokumente zu IEEE-Arithmetik, Bent E. Petersen: Intel 80x87 Floating Point Data Types, Christopher Vickery: IEEE-754 References und eigene Quellen.

Wir möchten allen danken, die den Artikel im Vorfeld gelesen und kommentiert haben. Aus dem 3DCenter-Forum flossen einige Anregungen und Hinweise in den Artikel mit ein. Ganz besonders sind Demirug, Frank, Xmas und zeckensack zu nennen, ohne deren Hilfe der Artikel in dieser Form nicht möglich gewesen wäre.






Kommentare, Meinungen, Kritiken können ins Forum geschrieben werden - Registrierung ist nicht notwendig Zurück / Back 3DCenter-Artikel - Index Home

Shortcuts
nach oben