Die Entwicklung der Shader zu "4.0" (WGF)
28. September 2004 / von aths / Seite 1 von 1
Was wir unter Programmierbarkeit verstehen
Bevor wir mit dem eigentlichen Thema beginnen, möchten wir zunächst ein Missverständnis aus der Welt räumen, welches man immer wieder antrifft: Grafikkarten seien erst mit dem Pixelshader programmierbar geworden. Dieser Vorstellung liegt vermutlich das Marketing um die GeForce3-Einführung zugrunde. Pixelshader stellen lediglich eine einheitliche Programmier-Schnittstelle dar. Diese Einheitlichkeit hat natürlich ihren Preis, und zwar dass man in DirectX Probleme hat, die Fähigkeiten einer Grafikkarte voll auszunutzen.
Im gewissen Sinne "programmierbar" ist bereits die erste GeForce. Der Begriff "programmierbar" wird aus unserer Sicht gerne überstrapaziert: So "programmiert" man ja auch Videorekorder. Im Wortsinne ist das richtig, doch im Computerbereich versteht man unter "programmieren" das Erstellen weitaus komplexerer Programme, als Zeitpunkt und Sender für eine TV-Aufnahme festzulegen.
Eine recht freie Konfiguration der Texturverknüpfung-Operationen ist mit DirectX7 kein Problem. Allerdings erlaubt ein DirectX7-Multitexturingsetup nur eine Textur pro Stage, während die GeForce-Hardware auch zwei Texturen pro Stage zulässt. Für gewisse Effekte ist in DirectX7 also eine zusätzliche Stage notwendig, nur um eine zweite Textur zu holen. Der Treiber setzt solche Setups allerdings für die entsprechenden Combiner um, hier kann auch optimiert werden.
Natürlich beherrscht die GeForce256 nicht alle in DirectX7 möglichen Texturblending-Operationen. Kompromisse mussten auch beim Pixelshader gemacht werden. Pixelshader 1.0 hat noch das Limit von einer Textur pro Slot und ist außerdem auf insgesamt 8 Slots begrenzt. Mit Pixelshader 1.1 kann man pro Befehl dann schon aus zwei Texturen lesen, und man hat bis zu 4 Textur-Operationen plus 8 arithmetische Schritte zur Verfügung. In bestimmten Fällen zählen zwei Befehle als eine Anweisung, im Pixelshader 1.2 zählen bestimmte Befehle als zwei Anweisungen, doch solche Details interessieren uns in diesem Zusammenhang nicht.
Bevor wir uns weiter mit den "geschichtlichen" Dingen beschäftigen, sei zunächst der Vorteil des Pixelshader-Standards genannt: Die Sicherheit, dass ein definiertes Set an Operationen vorhanden ist. Beim Multitexturing-Setup ist jeder Combiner optional. Bevor ein Grafikeffekt gerendert werden kann, muss zunächst das Vorhandensein aller notwendigen Verknüpfungsmöglichkeiten abgefragt werden. Selbst wenn alle erforderlichen Funktionen von der Hardware beherrscht werden, darf der Treiber in DirectX7 trotzdem noch das Setup ablehnen.
"DirectX7-Klasse" taugt also nicht viel, um die Mächtigkeit von Grafikhardware zu beschreiben. Bei DirectX8 und der Pixelshader-Definition kann man in der DirectX-Dokumentation nachschlagen, was geboten wird, und dies ist dann bei DirectX8-compliant Hardware auch auf alle Fälle da. "Programmierbar" ist die DirectX8-Pixelpipeline aber nur in Ansätzen.
Einheit hat seinen Preis
Die Shaderversion 1.0 war für den 3dfx Rampage Grafikchip gedacht. Der Rampage kann eigentlich bis zu 8 Texturen pro Pass verarbeiten. GeForce3 (mit Shaderversion 1.1) schafft nur vier Texturen, und damit wurde 1.0 auf 4 Texturen heruntergeschraubt. Doch mit Version 1.1 kann man auch die GeForce3 nicht in Gänze ausnutzen. Diese Karte beherrscht eigentlich schon die Fähigkeit, in der Pixelshader-Hardware den Z-Wert zu ändern. Doch das ist erst ab Version 1.3 erlaubt, da 1.2 auf die ihr zugedachte Hardware (von 3DLabs) Rücksicht nimmt, welche dies eben noch nicht beherrscht - die GeForce3 aber nicht alles kann, was für 1.2 erforderlich ist.
Auch was die Zahl der möglichen Rechenschritte angeht, limitiert Pixelshader 1.1 die GeForce3 und Pixelshader 1.3 die GeForce4 Ti. In OpenGL stehen hingegen (dank Extensions) alle Möglichkeiten zur Verfügung.
Mit der Radeon 8500 führte ATI eine völlig neue Pixel-Architektur ein, welche mit Version 1.3 extrem limitiert würde, weshalb Microsoft Version 1.4 nachschob. Der große Vorteil war, dass man in 1.4 zweimal Texturen sampeln kann, und sich zwischendurch die Texturkoordinaten im arithmetischen Pixelshaderteil ändern lassen. Pixelshader 1.4 ist nun inkompatibel mit den vorherigen Versionen (während man ansonsten z. B. ein 1.0-Programm auch als 1.3-Programm ausführen kann), aber jede 1.4-fähige Hardware muss unbedingt auch alle Vorgänger-Versionen unterstützen. Voller Support von 1.1, 1.2 und 1.3 sind Pflichtfeatures für 1.4-Hardware – wobei praktisch wie gesagt 1.3-Support ausreicht, da jeder gültige Programmcode für eine kleinere Shaderversion immer auch einen validen 1.3-er Shader darstellt.
Das ist ein zweiter Vorteil: Pixelshader Version X beinhaltet den kompletten Support aller Vorgänger-Versionen. In Folge dessen kann man auf DirectX9-Karten bereits fertig programmierte DirectX8-Shader ohne Änderung weiterhin verwenden: DirectX9 umfasst auch Pixelshader 1.4 Support aus DirectX8. Tatsächlich benötigt man für viele angebliche "DirectX9-Effekte" nur den 1.4-er Pixelshader. Wir wollen jedoch die Bindung des Begriffes "Effekt" an eine DirectX-Version vermeiden. Denn die DirectX-Compliance erfordert lediglich bestimmte Features, stellt aber keine Effekte zur Verfügung.
Der Shaderversion 1.0 entledigte man sich dann in DirectX9, da es keine DirectX8-Hardware gibt, die nicht mindestens Shaderversion 1.1 beherrscht. Ein zweites Missverständnis ist nun, dass sich Nvidia mit der GeForceFX nicht an den DirectX9 Pixelshader-Standard gehalten hätte, woraus die bekannten Probleme resultieren würden. Wie die konkrete Hardware aussieht, ist Microsoft egal - Hauptsache, valider Pixelshader-Code wird definitionsgemäß ausgeführt. Das kann übrigens mit dem Reference Rasterizer geprüft werden. Um im fertigen Bild Abweichungen im Bitbereich oder die Qualität von Texturfiltern zu beurteilen, eignet sich der REF allerdings nicht.
Nun führen viele Wege nach Rom. ATI überzeugte Microsoft davon, dass man noch nicht unbedingt durchgehende FP32-Genauigkeit bräuchte (der REF rendert alles mit FP32). Nvidia gelang es jedoch nicht, Microsoft zu überreden, auch noch Fixpoint-Formate zuzulassen. Außerdem zielte Nvidia eigentlich gleich auf Version 3.0. In der Tat hatte Nvidia mit der GeForceFX gegenüber der ATI-Hardware etliche zusätzlichen Features: Dynamic flow control im Vertexshader, static flow control im Pixelshader, mehr temporäre Register, eine deutlich größere Programmlänge, arbitrary swizzles (freie Umsortierung der Register-Komponenten) und mehr. Doch ohne dynamic flow control auch im Pixelshader weigerte sich Microsoft, dafür die "3.0"-Marke zu vergeben.
Unterschiedliche Realisierungen
Die Frage, ob Pixelshader-Hardware eher viel können oder lieber möglichst schnell sein soll, lässt sich nicht pauschal beantworten. Das hängt einfach vom Einsatzgebiet ab. Spieler sind in der Regel mit der schnelleren Hardware besser beraten, auch wenn jene featuremäßig zurückhängt. ATIs Heldentat namens Radeon 9700 bestand darin, den Support der neuen Features so schnell zu machen, dass man sie noch "zu Lebzeiten" der Grafikkarte in Spielen sinnvoll einsetzen kann. Beispielhaft sei Far Cry genannt - aber auch Doom 3 performt anständig (im Vergleich zur GeForceFX).
Das Featureset der GeForceFX 5800 war seiner Zeit zwar voraus, doch die Leistung enttäuschte. In DirectX8 fuhr der NV30-Chip zwar zu Höchstleistungen auf, in DirectX9 wurde er jedoch von der Radeon 9700 geradezu vernichtet. Diese Schwäche kombiniert mit Nvidias Cheatereien im Treiber, z. B. um auf wundersame Weise den 3DMark zu "beschleunigen", führten zu einem Vertrauensverlust in die GeForce-Reihe allgemein. Zusätzlich zog sich Nvidia Spott wegen der GeForceFX 5200 zu: In Spielen ist das Teil eine lahme Krücke.
Doch ausgerechnet der GeForceFX 5200 verdanken wir die Verbreitung von DirectX9-Hardware. Die Radeon 9600 war einfach nicht billig genug, um auch Nicht-Spieler anzusprechen. Für Spieler bot die Radeon 9600 seinerzeit allerdings einen großen Gegenwert: Ausreichend schnelle DirectX9-Beschleunigung selbst für Far Cry und andere moderne Spiele.
Was die hardwaremäßige Realisierung angeht, gingen ATI und Nvidia völlig unterschiedliche Wege. In diesem Zusammenhang wird hin und wieder diskutiert, ob FP24 wirklich ausreicht oder ob es nicht umständlich ist, ständig zwischen FP16 (schnell) und FP32 (schön) abwägen zu müssen. Fakt ist, dass für Spiele das FP24-Format bislang völlig ausreicht. Ebenso ist fakt, dass es eigentlich sinnvoller ist, zwischen zwei Formaten wählen zu können, und mit der FP32/FP16-Lösung die technisch elegantere Lösung gefunden wurde.
Allerdings ist die Radeon-Hardware schnell genug für durchgehendes FP24 (bestimmte Teile werden übrigens sogar in FP32 gerechnet), während die GeForceFX-Hardware eben für besondere Ansprüche auch durchgehende FP32-Genauigkeit bietet, hin und wieder jedoch ein kleines bisschen Qualität geopfert wird, um das schnellere FP16-Format zu nutzen.
Obwohl der Hardware-Aufbau große Unterschiede aufweisen kann, lässt der Pixelshader-Standard dennoch eine Entwicklungslinie erkennen. Zunächst aber noch einige Worte zum Vertexshader.
Programmierbare T&L
Die Vertexshader Version 1.0 war für den 3dfx Sage gedacht, ein extra Geometrie-Chip für den Rampage. Interessanterweise gibt es beim Vertexshader weniger Entwicklungssprünge als im Pixelteil. Das liegt an der Aufgabenstellung für die T&L-Einheit, die so klar umrissen ist, dass die Hardware-Realisierungen nicht ganz so weit auseinander liegen. Der Vertexshader muss zunächst Matrizenmultiplikationen ausführen, das ist die mathematische Realisierung der Transformation. Dafür muss addiert und multipliziert werden. Die Parameter für die Transformation werden in der Regel von der CPU berechnet. Der Vertexshader übernimmt dann die stupide Arbeit, diese Parameter auf -zigtausende Daten anzuwenden.
Um die CPU möglichst weitgehend zu entlasten, können Vertexshader eine ganze Menge mehr als nur addieren und multiplizieren. So können dann zum Beispiel bestimmte Physik-Berechnungen, um Objekte zu verformen, dank DirectX9-Hardware (die eine genügend große Programmlänge bietet) zum größten Teil vom Vertexshader übernommen werden.
Da es nun deutlich weniger Eckpunkte als Bildschirmpixel gibt, ist klar, dass der Vertexshader selten der Flaschenhals sein wird. Er lässt sich, ohne dass die Chipgröße sofort aus dem Ruder läuft, so dimensionieren, dass er für einige Zeit ausreicht. Es wäre ja auch leichtsinnige Verschwendung, wenn der Vertexshader als Flaschenhals den aufwändigen und damit kostenintensiven Pixelteil limitieren würde.
Vertexshader sind nützlich, um Vorberechnungen zu machen, auf die dann die Pixelshader-Effekte aufbauen. Im Shader Model 3.0 unterscheidet sich der Befehlssatz zwischen Pixel- und Vertexshader kaum noch.
Das Ziel
Wir haben es schon angedeutet: Das Ziel ist die Vereinigung von Pixel- und Vertexshader. "Shader 4.0" wäre das praktisch. Allerdings wird es kaum so genannt werden: In WGF, dem Nachfolger von DirectX, gibt es schlicht nur noch "Shader". Diese müssen praktisch alles können. WGF wird mit dem Windows XP Nachfolger "Longhorn" zum Einsatz kommen - allerdings nach derzeitiger Planung auch nur dort, und nicht bei Windows XP oder anderen Betriebssystemen.
Je mehr Texturen man sampelt oder je länger die Programme werden, desto langsamer wird natürlich die Ausführung. Immerhin schreibt WGF eine Mindestausführgeschwindigkeit vor. WGF-Grafikkarten könnten praktisch C-Code ausführen. Um die Annäherung an die CPU-Flexibilität zu gewährleisten, soll FP32 auch nach der IEEE-Definition unterstützt werden. Bislang kommt bei GeForceFX und 6-er Serie eine vereinfachte FP32-Variante zum Einsatz, die (abgesehen von Denorms) zwar bitkompatibel mit dem CPU-Format ist, wobei jedoch die Rechenwerke nicht alle erforderlichen "Features" bieten.
Irgendwann werden wir vielleicht auch FP64-Genauigkeit in Grafikkarten vorfinden. Grafikkarten sind für WGF jedenfalls Co-Prozessoren für die Verarbeitung von Datenströmen. Dabei kann es sich natürlich auch noch um Grafik handeln, aber auch um Audiodaten. Die Bandbreite zur Grafikkarte ist dank PCI-Express kein Problem – warum nicht Audiofilter auf der Grafikkarte ausführen? Die FP32-Genauigkeit beinhaltet volle 24-Bit-Genauigkeit für Integer – in der professionellen Audiotechnik sind 24 Bit Standard.
Einen "Pixelshader 4.0" wird es jedenfalls so gar nicht geben, vielmehr wird es dann schlicht "WGF-Hardware" geben. WGF-compliant Hardware erwarten wir spätestens 2006. Bis dahin werden wir uns mit Shader Model 3.0 begnügen, welches aktuell auf Nvidia-Grafikkarten angeboten wird. 3DLabs könnte nachziehen, von ATI erwarten wir das auch. Sogar XGI setzt bei zukünftigen Chips auf die Shaderversion 3.0. S3 möchte allerdings bishin zu WGF bei der Shaderversion 2.0 bleiben.
Fazit
Shader im allgemeinen erlösten die Entwickler vor der ständigen Furcht, dass eine Grafikkarte bestimmte Rechenoperationen nicht ausführen kann. Version 3.0 ist eine logische und sinnvolle Erweiterung, die deutlich über das 2.0-Featureset der Radeon 9700 (bzw. X800) hinaus geht. Der Hauptvorteil liegt darin, dass die Rechenleistung der Grafikkarte gezielter eingesetzt werden kann.
Die nächste große Revolution nach der Einführung der Shader in DirectX8 steht uns mit WGF mit den vereinigten Shadern bevor, die "praktisch alles" können. Die Combiner-Entwicklung findet damit einen vorläufigen Abschluss, denn jede WGF-Karte wird featuremäßig im Shaderteil so viel können, dass es auf längere Zeit unerheblich ist, ob eine andere Hardware (featuremäßig) noch mehr kann.