Archiv verlassen und diese Seite im Standarddesign anzeigen : Shaderemulation und SSE (@Zeckensack)
Demirug
2003-08-02, 16:18:37
Ich hatte gerade ein interesantes Gespräch bezüglich der Emulation von Shadern (hauptsächlich Vertex) auf einer CPU. Bei DX kann man ja bekanntermassen die Vertexshader auch von der CPU emulieren lassen (Unter OpenGL hängt das vom Treiber ab). MS hat ja nun die dafür notwendigen Routinen jeweils von AMD und Intel optimieren lassen.
Die SSE Register entsprechen ja direkt einem Float4 Vector man könnte also damit ein Programm genauso wie auf einer GPU ausführen welche ja auch mit Float4 Vektoren arbeitet. Nun ist aber eine GPU das Vertauschen von eingangs Elementen und ein Maskieren am Ende der Berechung umsonst. Bei SSE muss man dafür AFAIK aber zusätzliche Instruktionen verwenden. Desweiteren werden ja auch oft nicht alle 4 Elemente des Vektors benutzt. Alternativ könnte man ja nun auch immer 4 Verticen gleichzeitig berechnen. Dadurch würde die Ausnutzung der Register erhöht und das Vertauschen und Maskieren vereinfacht. Im Gegenzug reduziert man aber die Anzahl der Register pro Vertex die man in der CPU speichern kann auf ein viertel.
Nun die Frage an unseren Assembler experten. Welche Lösung dürfte die bessere sein? Ich meine vorallem im Bezug auf die Leistung in Verticen/s.
zeckensack
2003-08-02, 17:09:34
Es kommt darauf an :D
SHUFPS xmmreg0,xmmreg1,imm8
erlaubt beliebiege Permutation, womit das Problem schonmal lösbar ist.
Auf AthlonXPs ist das ganze leider 'vector decode' und dauert 4 Takte, also eher nicht so toll. Auf P3/P4 ist das möglicherweise besser, aber von Intel habe ich bisher noch nie brauchbare Dokumentation gesehen :(
Die Instruktion braucht man btw sowieso für beide Möglichkeiten, es sei denn, man will alle Vertexdaten umsortieren. Das kann man vergessen, die Software-Emu muß sich nach außen hin so verhalten wie die HW, sonst geht's nicht.
Ich weiß daß Intel generell empfiehlt, Probleme "um 90° zu drehen", oder so ähnlich. Den Vorteil sehe ich aber eigentlich nur in Spezialfällen, zudem braucht's eben die nötige Anpassung der Datenstrukturen.
Also wenn man das machen will, dann muß man innerhalb des Shaders die Daten umdrehen.
Der Registerverbrauch ist wohl das schwierigste. 8 Register sind so gut wie garnichts, zudem Shader ja großzügige Konstantenspeicher voraussetzen.
Dann sehe ich noch das Problem daß man, wenn man mehr Parallelität haben will, Ausführungseinheiten verstopft.
Ohne das jetzt genau ausgetestet zu haben denke ich mal daß im Schnitt beides gleich schnell sein kann. 'Klassisch' ist halt nur viel leichter zu implementieren, verbraucht weniger Bandbreite (einfach weil mehr Register frei sind) und weniger Code (weil man keinen Spezialfall-Code braucht, wenn mal weniger als 4 vertices durchkommen).
bendel
2003-08-02, 17:12:29
Hatten wir das Thema nicht schon mal?
In der benutzen Implementierung werden immer 4 Vertices auf einmal berechnet. Alles andere würde auch keinen Sinn machen, da viele Shader Befehle nicht auf SSE Befehle gemappt werden können (hautpsächlich aufgrund der Maskierungen). Da sowieso nicht genügned Register vorhanden sind, um die Emulation komplett darin laufen zu lassen, muß eh auf den Speicher zugegriffen werden. Bei PC-CPUs wirkt der First Level Cache aber fast wie ein erweitertes Registerset.
Demirug
2003-08-02, 20:55:09
AFAIK hatte wir das Thema noch nicht und ich glaube auch gehört zu haben das 4 Verticen auf einmal bearbeitet werden.
Ich wollte nur mal von jemandem der damit mehr Erfahrung hat als ich hören was er für den besten weg hält.
zeckensack
2003-08-02, 21:42:24
Ach ja, im Grunde ist für Code der viel Permutation benutzt 3DNow! besser (wobei's erst ab Athlon richtig Spaß macht).
Erstmal ist die Granularität kleiner (was gleichzeitig auch ein Nachteil ist, denn 8x2 ist weniger als 8x4 ...).
Zum gibt's für jede Permutation einen eigenen, 'fast decode'-Befehl mit minimaler Latenz.
PSWAPD vertauscht
PUNPCKLDQ kann man nehmen, um die untere Hälfte zu verdoppeln
PUNPCKHDQ für die obere Hälfte
3DNow hat außerdem nicht die hirnrissigen Alignment-Restriktionen von SSE.
Am besten natürlich beides gleichzeitig, aber dann maulen die Intel-User *eg*
Pitchfork
2003-08-02, 22:52:06
Ist ne offizielle Aussage von Intel auf der GDC 2001.
Gründe:
1. Viele Shaderops sind skalar und werden dadurch trotzdem beschleunigt
2. Shuffle+Writemasks.
Wichtige Konsequenz:
Sobald das Indexregister im Shader benutzt wird, funzt das nicht mehr. Es wird also vom compilierten Shader geprüft, ob alle 4 Vertices den gleichen Wert in a0 haben und die vier Vertices werden parallel bearbeitet oder sie werden einzeln bearbeitet, bzw. die Daten werden sehr kostspielig zusammengesucht.
zeckensack
2003-08-02, 23:07:46
Original geschrieben von Pitchfork
Ist ne offizielle Aussage von Intel auf der GDC 2001.
Gründe:
1. Viele Shaderops sind skalar und werden dadurch trotzdem beschleunigt???
Also wenn man den Aufwand treibt, kann man auch gleich ein bisserl flow analysis betreiben, und danach ist < 5% skalar, behaupte ich mal ...
2. Shuffle+Writemasks.Kleinere Schwäche von SSE, wegen der hohen Granularität. Würde ich aber nicht als kritisch bewerten. Zumal gängige HW das gleiche 'Problem' hat, Shadercode der gut auf HW läuft, läuft ergo auch gut auf SSE.
Wichtige Konsequenz:
Sobald das Indexregister im Shader benutzt wird, funzt das nicht mehr. Es wird also vom compilierten Shader geprüft, ob alle 4 Vertices den gleichen Wert in a0 haben und die vier Vertices werden parallel bearbeitet oder sie werden einzeln bearbeitet, bzw. die Daten werden sehr kostspielig zusammengesucht. "Palette matrix skinning"???
Aber ich denke mir dämmert's so langsam ... Intel muß den Alignment-Krempel umschiffen, und dafür ist das ein ganz guter Ansatz, wenn nicht der beste.
Das ganze sieht mir btw klar nach einer Optimierung auf extrem kurze VS aus, wenn ich so drüber nachdenke. Davon halte ich eigentlich nicht viel, gute Software muß skalieren.
Intel hat sich auf Bandbreiten-Effizienz gestürzt, was bei längeren Shadern aber erstens nicht mehr so wichtig ist (weniger Durchsatz pro Instruktion), zweitens sogar zum Schuß ins Knie wird (mehr Cache-Zugriffe wg zu wenigen freien Registern; komplexere Shader brauchen noch am ehesten viele Register für temporaries und Konstanten).
Welche Relevanz hat VS-CPU-Performance in der Praxis? Ich ging davon aus, Szenen, die massig auf VS setzen, sollten sowieso auf DX8+ HW laufen?
Pitchfork
2003-08-03, 09:10:34
AquaNox 1/2 verwenden zum Beispiel überhaupt kein Fixed Function T&L, sie laufen ausschließlich mit Vertex Shadern in HW und SW. Ich kenne auch andere Entwickler, die nicht zögern VS einzusetzen, auch wenn die Hardware es nicht untersützt, um die gewünschten Effekte zu bekommen. Es dürfte sich insgesamt und einen Mix handeln, nur wenige Spiele benutzen zur Zeit ausschließlich Vertex Shader, auch wenn sie nicht in HW verfügbar sind, aber viele benutzen sie partiell.
Das war nicht genau meine Frage :) Dass VS gerne eingesetzt werden, da sie auch von der CPU ausgeführt werden können (ohne dass die Anwendung da einen extra Pfad braucht) ist klar. Aquanox z.B. erfordert aber ohnehin eine bessere Karte der DX8-Klasse, um brauchbar zu laufen. Dann ist VS 1.1-Support ohnehin da, und die CPU-VS-Performance dürfte dann doch egal sein?
zeckensack
2003-08-03, 09:34:41
Original geschrieben von Pitchfork
AquaNox 1/2 verwenden zum Beispiel überhaupt kein Fixed Function T&L, sie laufen ausschließlich mit Vertex Shadern in HW und SW. Ich kenne auch andere Entwickler, die nicht zögern VS einzusetzen, auch wenn die Hardware es nicht untersützt, um die gewünschten Effekte zu bekommen. Es dürfte sich insgesamt und einen Mix handeln, nur wenige Spiele benutzen zur Zeit ausschließlich Vertex Shader, auch wenn sie nicht in HW verfügbar sind, aber viele benutzen sie partiell. Ist ja auch viel schöner so.
Die DX-Runtime kann ganze Arrays in einem Rutsch "pro Draw-Call", oder noch stärker gebündelt transformieren. Apps tun sich da wesentlich schwerer, weil sich dafür state changes nachverfolgen müssen (eben eine Arbeit die die API sowieso schon erledigt - Zeitverschwendung).
Es ist dagegen extrem unpraktisch, in einem Renderer mit eigener "Software-VS-Emu" nicht pro Vertex, bestenfalls pro Mesh pro Material zu arbeiten.
zeckensack
2003-08-03, 09:35:56
Original geschrieben von aths
Das war nicht genau meine Frage :) Dass VS gerne eingesetzt werden, da sie auch von der CPU ausgeführt werden können (ohne dass die Anwendung da einen extra Pfad braucht) ist klar. Aquanox z.B. erfordert aber ohnehin eine bessere Karte der DX8-Klasse, um brauchbar zu laufen. Dann ist VS 1.1-Support ohnehin da, und die CPU-VS-Performance dürfte dann doch egal sein? Aquanox (und auch Aquamark) läuft aber auch auf R100/Gf2MX. Hab's selbst gesehen ;)
Quasar
2003-08-03, 09:42:11
Aquanox ist einer des wenigen Spiele, die wirklich von AGP8X profitieren.
Und das nicht bei hohen FSAA/AF-Leveln, sondern in erbärmlichen 640x480, selbst auf einer GF4Ti ist ein deutlicher Unterschied messbar - 188 vs. 158fps.
How come?
zeckensack
2003-08-03, 09:46:56
Original geschrieben von Quasar
Aquanox ist einer des wenigen Spiele, die wirklich von AGP8X profitieren.
Und das nicht bei hohen FSAA/AF-Leveln, sondern in erbärmlichen 640x480, selbst auf einer GF4Ti ist ein deutlicher Unterschied messbar - 188 vs. 158fps.
How come? Transferlimitierung? Tja, was kann das für Ursachen haben ... eigentlich nur zwei.
Pro Frame müssen extrem viel Geometrie-Daten über den AGP, oder
Pro Frame müssen extrem viel Textur-Daten über den AGP.
Ich tippe mal auf ersteres. Soviel zur Theorie, bis jemand eine bessere Erklärung liefern kann.
Quasar
2003-08-03, 10:01:29
Das hätte ich jetzt auch getippt, zumal die Unterschiede in höherer Auflösung geringer werden, was aber natürlich auch auf zunehmende Limitierung durch die Renderleistung schliessen lassen könnte.
Noch andere Vorschläge?
bendel
2003-08-03, 11:53:36
Original geschrieben von Quasar
Aquanox ist einer des wenigen Spiele, die wirklich von AGP8X profitieren.
Und das nicht bei hohen FSAA/AF-Leveln, sondern in erbärmlichen 640x480, selbst auf einer GF4Ti ist ein deutlicher Unterschied messbar - 188 vs. 158fps.
How come?
Mal nachrechnen. Was gibt es an dynamischen erzeugten Daten?
Terrain - ca 10T Vertices * 40 Byte
Pflanzen - (wenn viele da sind) ca 10T Vertices * 40 Byte
2D Fogmap - Größe?
HUD Anzeigen Texturen - vielleicht effektiv 256*256*4
nicht alles muß davon jeden Frame neu gesetzt werden. Aber zumindest die dynamischen Vertexbuffer sind wohl immer im AGP Memory. Und ein paar Sachen habe ich sicher vergessen. Und im AGP Memory muß man dann für jeden Pass einzeln zählen. Beim Terrain nehmen wir mal 3 Passes an.
Zusammen macht das schonmal 2MB. Dann kommt noch der Bandbreitenbedarf für die bei DrawPrimitiv übermittelten Daten (VertexKonstanten,Renderstates,Texurestates,...) Schwer abzuschätzen, vielleicht 500Byte pro Aufruf? Bei 1000 Calls (AN ist dort nicht sonderlich effektiv) macht das auch nochmal ein halbes Megabyte.
Bei 150fps sind das 375MB/s. OK, das ist noch nicht an der Grenze von AGPx4(1GB/s). Aber die Schätzung war auch sehr grob und kann durchaus anders aussehen, besonders wenn sowieso nicht alle Daten in den Grafikkartenspeicher passen. Und die Bandbreite wird eventuell auch nicht kontinuierlich gebraucht, sondern nur wenn die Grafikkarte gerade die entsprechenden Sachen bearbeitet.
Da kann man sich schon vorstellen, das es einen Unterschied zwischen AGP4 und 8 gibt.
vBulletin®, Copyright ©2000-2025, Jelsoft Enterprises Ltd.