PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Farcry HDR-Effekt im Detail


Demirug
2004-11-13, 20:36:22
Benutzt wurde die HDR Einstellung 7 bei einer Auflösung von 1024*768. In wie weit sich der Effekt bei anderen Einstellungen ändert müsste noch untersucht werden.

Zuerst wird das gesamte Bild in eine FP16 Texture gerendert. Diese Texture hat die gleiche Größe wie der Framebuffer. Bevor das entgültige Bild aber dort ankommt sind noch viele Zwischenschritte notwendig.

1. Die Inhalt der Texture wird um den Faktor 16 heruntergerechnet. Die Zieltextur ist also 256*192 Pixel gross. Interesanterweise kommt dabei eine Textur mit 2 FP16 Kanälen zum Einsatz. Es wird also nur der Rote und Grüne Farbanteil gespeichert

2. Schritt 1 wird nochmal mit einer anderen Zieltexture wiederholt die aber dann den Blauen sowie den Alphakanal enthält.

3. Die in Schritt 1 und 2 gefüllte Texturen werden nun wieder eingelesen. Aus den RGB Werten wird ein Heligkeitswert errechnet. Gleichzeitig wird das ganze durch Mittelwertbildung weiter in der Auflösung reduziert. Als Ergebniss erhält man eine 64*64 Pixel Texture im FP32 Format mit einem Kanal.

4. Eine weitere Reducktion auf 16*16 Pixel.

5. 4*4 Pixel

6. Eine letzte Mittelwertbildung um auf ein Pixel zu kommen.

7. Der in Schrit 6 gewonne Wert wird nun mit dem Vergleichswert aus dem vorhergehenden Frame verrechnet. Dadurch bekommt der Effekt noch eine Zeitkomponente.

8. Hier werden nun wieder die beiden Texturen aus Schritt 1 und 2 benötigt. Diese ergeben zusammen mit dem Mittelwert aus Schritt 7 ein normalisiertes Bild. Dieses wird in einer 258*194 Pixel Texture gespeichert. In diesem Fall wird allerdings nur eine 8 Bit pro Kanal Textur genutzt.

9. Ein Blur Filter (8 Samples) kommt zum Einsatz. Diese Texture wird im weiteren verlauf noch häufiger gebraucht.

10. Downfilter auf 130*98 Pixel. Es wird immer noch eine 8 Bit Texture genutzt

11. Der Blur Filter kommt erneut zum Einsatz

12. Ein Glow Filter mit ebenfalls 8 Samples.

13. Nocheinmal Glow. Dabei wird auch die Auflösung minimal auf 128*96 reduziert.

14. Ein weiterer Glow Filter. Das Ergebniss wird jetzt allerdings in FP16 Texturen gespeichert. Da wieder nur 2 Kanalige Texturen genutzt werden kommen 2 Rendertargets zum Einsatz. In die erste Textur wird wieder Rot und Grün gespeichert und in der zweiten der Blaue Anteil. Die Auflösung wird wieder auf 256*192 Pixel erhöht.

15-16. Auf die beiden bei 14 gefüllten Texturen wird erneut ein Glow Filter angewendet.

17-18. Nochmal Glow.

19. Auf die bei 9 berechnete Texture wird nun der schon bei Schrit 14 benutze Filter (allerdings andere Gewichtungen) erneut benutzt. Wieder entstehen zwei Texturen.

20-23: Die Schritte 15-18 werden mit anderen Gewischtungen wiederholt.

24-28. 19-23 werden wiederholt.

29-33. 19-23 werden wiederholt.

34-38. 19-23 werden wiederholt.

39-43. 19-23 werden wiederholt.

44. Die 6 Texturen aus den vorangegangen Schritten welchen den Rot/Grün Kanal enthalten werden mit Gewichtungsfaktoren addiert.

45. Die 6 Texturen aus den vorangegangen Schritten welchen den Blau Kanal enthalten werden mit Gewichtungsfaktoren addiert.

46. Das Ausgangsbild, Texture 14, die beiden zuletzt zusammenaddierten Texturen sowie der Mittelwert werden zum finalen Bild verrechnet.

Anmerkungen:

1. Die Verwendung von 2 Kanaligen FP16 Texturen ist unlogisch. Dadurch müssen viele Schritte zweimal ausgeführt. Einmal für den Rot und Grün Anteil und dann nochmal für den Blauen Anteil. Zusätzlich müssen beim Zusammenführen der Kanälen dann auch jeweils beide Texturen gesampelt werden.

2. Der Heligkeitswert wird in einer FP32 Texture gespeichert. Dadurch verliert man beim NV40 die Filterfunktion in den TMUs. Ergebniss 4 facher Fillrateverbrauch und zusätzliche Belastung in den Shadern.

3. Das Downfiltern von 64*64 auf 1*1 erfolgt über 2 Zwischenstufen. Eigentlich hätte man das auch auf einmal machen können und sich so einiges sparen.

4. Die Shader für die Blur und Glow Filter sind für 8 Samples pro Pixel programmiert. Allerdings werden immer wieder einzelne Samples mit 0 gewichtet. Hier wird Fillrate und Rechenleistung verschenkt.

5. Jeder der einzelnen Schritten wird mit einem DrawPrimitiveUP ausgeführt. Diese Funktion sollte man eigentlich aus Performancegründen nicht nutzen.

6. Dass addieren (44+45) hätte man auch von der Alphablending Einheit übernehmen lassen können.

Neugieriger Gast
2004-11-13, 21:15:21
meine fresse... crytek lassen ja den prozessor richtig hart arbeiten. ich hätte nie gedacht daß SO viele schritte gebraucht werden. jetzt sehe ich auch daß da vieles komisch ist.
vor allem das aufteilen in 2x 2kanal texturen ist mit sofort als ich anfing den thread zu lesen spanisch vorgekommen, obwohl ich eigentlich nicht so viel von dem zeug verstehe. warum also ? könnte es vielleicht doch irgendwie zu irgendwas gebraucht werden ?
zur FP32 textur mit dem helligkeitswert: hätte auch FP16 ausgereicht ? hätte diese textur in diesem überhaupt gefiltert werden müssen ? (wenn sie denn in einem entsprechenden format gewesen wäre)
wieso werden "seltsame" auflösungen wie 130x98 oder 258x194 verwendet ? (btw, meinst du nicht 256 statt 265 bei 1. ?)
wieso wird die textur erst auf 130x98 runteregrechnet, nur um wenig später um wenige pixel auf 128x96 (wenigstens sind das "normalere" werte) erneut verkleinert zu werden ? wieso nicht gleich 128x96 ?
wieso wird bei den schritten 8-13 eine 8bit/kanal textur genutzt ? da die textur wie ich da lese ziemlich oft verkleinert, vergrößert, mehrmals durch effektfilter bearbeitet wird, usw., wäre FP16bit/kanal nicht besser gewesen um (eventuellen) qualitätsverlusten vorzubeugen ? oder sind die 8bit/kanal hier völlig ausreichend ?

Demirug
2004-11-13, 21:48:23
Das mit dem aufteilen auf zwei Texturen könnte noch eine Experimentier-Leiche sein. Nicht alle Karte beherschen ein 4 Kanal FP16 Format. Beim NV40 der ja derzeit der einzige Chip ist für den man HDR aktivieren kann ist es aber auf jeden Fall sehr ungeschickt.

FP16 sollte für den Helligkeitswert ausreichen. Den Texturefilter hätte man nutzen können um das runterechnen von 64*64 auf 1 Pixel zu beschleunigen. FP32 kann der NV40 ja nicht filtern.

Das bei 1. ist ein Zahlendreher von mir. Warum teilweise merkwürdige Auflösungen benutzt werden kann ich auch nicht sagen.

Die 8 Bit sollten an der Stelle reichen und 8 Bit Texturen sind eben immer noch etwas schneller als FP16. Schon wegen der Bandbreite.

PS: In meinem Testframe (Indoor) wurden mehr als 50% der DX Anweisungen für den HDR Effekt benötigt. Der Rest ist für das eigentliche Bild und das HUD.

Xmas
2004-11-13, 21:57:33
Die "seltsamen" Auflösungen kommen wohl wegen der Größe des Filterkernels. Crytek wollte nur am Rand und an den Ecken keinen anderen Kernel verwenden.

mapel110
2004-11-13, 22:05:12
Lässt sich da durch Dritte programmiertechnisch noch irgendwie Speed rausholen? oder geht das nur im Quellcode bzw durch Crytek?

Kann da nvidia noch was mit dem Treiber richten?

aths
2004-11-13, 22:11:07
Benutzt wurde die HDR Einstellung 7 bei einer Auflösung von 1024*768. In wie weit sich der Effekt bei anderen Einstellungen ändert müsste noch untersucht werden.

Zuerst wird das gesamte Bild in eine FP16 Texture gerendert. Diese Texture hat die gleiche Größe wie der Framebuffer. Bevor das entgültige Bild aber dort ankommt sind noch viele Zwischenschritte notwendig.

1. Die Inhalt der Texture wird um den Faktor 16 heruntergerechnet. Die Zieltextur ist also 256*192 Pixel gross. Interesanterweise kommt dabei eine Textur mit 2 FP16 Kanälen zum Einsatz. Es wird also nur der Rote und Grüne Farbanteil gespeichert

2. Schritt 1 wird nochmal mit einer anderen Zieltexture wiederholt die aber dann den Blauen sowie den Alphakanal enthält.

3. Die in Schritt 1 und 2 gefüllte Texturen werden nun wieder eingelesen. Aus den RGB Werten wird ein Heligkeitswert errechnet. Gleichzeitig wird das ganze durch Mittelwertbildung weiter in der Auflösung reduziert. Als Ergebniss erhält man eine 64*64 Pixel Texture im FP32 Format mit einem Kanal.

4. Eine weitere Reducktion auf 16*16 Pixel.

5. 4*4 Pixel

6. Eine letzte Mittelwertbildung um auf ein Pixel zu kommen.

7. Der in Schrit 6 gewonne Wert wird nun mit dem Vergleichswert aus dem vorhergehenden Frame verrechnet. Dadurch bekommt der Effekt noch eine Zeitkomponente.

8. Hier werden nun wieder die beiden Texturen aus Schritt 1 und 2 benötigt. Diese ergeben zusammen mit dem Mittelwert aus Schritt 7 ein normalisiertes Bild. Dieses wird in einer 258*194 Pixel Texture gespeichert. In diesem Fall wird allerdings nur eine 8 Bit pro Kanal Textur genutzt.

9. Ein Blur Filter (8 Samples) kommt zum Einsatz. Diese Texture wird im weiteren verlauf noch häufiger gebraucht.

10. Downfilter auf 130*98 Pixel. Es wird immer noch eine 8 Bit Texture genutzt

11. Der Blur Filter kommt erneut zum Einsatz

12. Ein Glow Filter mit ebenfalls 8 Samples.

13. Nocheinmal Glow. Dabei wird auch die Auflösung minimal auf 128*96 reduziert.

14. Ein weiterer Glow Filter. Das Ergebniss wird jetzt allerdings in FP16 Texturen gespeichert. Da wieder nur 2 Kanalige Texturen genutzt werden kommen 2 Rendertargets zum Einsatz. In die erste Textur wird wieder Rot und Grün gespeichert und in der zweiten der Blaue Anteil. Die Auflösung wird wieder auf 256*192 Pixel erhöht.

15-16. Auf die beiden bei 14 gefüllten Texturen wird erneut ein Glow Filter angewendet.

17-18. Nochmal Glow.

19. Auf die bei 9 berechnete Texture wird nun der schon bei Schrit 14 benutze Filter (allerdings andere Gewichtungen) erneut benutzt. Wieder entstehen zwei Texturen.

20-23: Die Schritte 15-18 werden mit anderen Gewischtungen wiederholt.

24-28. 19-23 werden wiederholt.

29-33. 19-23 werden wiederholt.

34-38. 19-23 werden wiederholt.

39-43. 19-23 werden wiederholt.

44. Die 6 Texturen aus den vorangegangen Schritten welchen den Rot/Grün Kanal enthalten werden mit Gewichtungsfaktoren addiert.

45. Die 6 Texturen aus den vorangegangen Schritten welchen den Blau Kanal enthalten werden mit Gewichtungsfaktoren addiert.

46. Das Ausgangsbild, Texture 14, die beiden zuletzt zusammenaddierten Texturen sowie der Mittelwert werden zum finalen Bild verrechnet.Wenn man das liest, erstaunt mich doch, wie schnell der NV40 dann noch ist.

Demirug
2004-11-13, 22:19:41
Lässt sich da durch Dritte programmiertechnisch noch irgendwie Speed rausholen? oder geht das nur im Quellcode bzw durch Crytek?

Kann da nvidia noch was mit dem Treiber richten?

Im Prinzip ja. Ist aber einiges an Arbeit weil man doch einige Shader und Rendersequemzen patchen muss.

Coda
2004-11-13, 22:47:08
Ist das DrawPrimitiveUP bei so geringen Vertexmengen nicht relativ egal?
Das gleiche gilt ja auch für OpenGL. Wenn man nur nen Quad rendern will ist es eigentlich egal ob man glVertex* oder VBO benützt. Da könnte VBO da sogar mehr Overhead haben.

Demirug
2004-11-13, 22:53:32
Ist das DrawPrimitiveUP bei so geringen Vertexmengen nicht relativ egal?
Das gleiche gilt ja auch für OpenGL. Wenn man nur nen Quad rendern will ist es eigentlich egal ob man glVertex* oder VBO benützt. Da könnte VBO da sogar mehr Overhead haben.

Nein, es ist nicht egal. DrawPrimitiveUP kopiert nämlich die Userdaten in einen Vertexbuffer und führt dann einen normalen DrawPrimitive aus. Die Regel bei DX ist ganz einfach: Nimm immer einen Vertexbuffer.

DrawPrimitiveUP ist eigentlich nur noch aus kompatibilitätsgründen und für Quickhacks in der API.

Coda
2004-11-13, 23:33:43
Nun gut, die Locks sind natürlich nicht schön, aber ob es bei 4 vertices wirklich soviel ausmacht müsste man mal ausprobieren :rolleyes:

Coda
2004-11-13, 23:41:17
Ich weiß schon, aber bei 4 Vertices hast du doch eh nen rießigen API Overhead...

micki
2004-11-13, 23:49:08
bei einem DrawPrimitiveUP mit <100triangles ist es absolut egal wenn man das benutzt, man kann sich sonst wie auf den kopfstellen und optimieren, der rendercall an sich ist das einzige was performance kostet.
klar es kann nicht elegant und sauber aussehen, aber performancemässig kann man da nichts raushollen, klar nv tingelt alle developer man soll das nicht machen, aber aus performance sicht bringt das leider nichts.

ich denke mir, dass des vielleicht deswegen 2 textures gibt, weil sie in z.b. innenräumen die blau/alpha textur garnicht erst verwenden. weil man als mensch vom blauwert eh nur 10% zur helligkeitswertung einfliessen lässt, deswegen würde ich das an deren stelle auch nur auf den himmelblauen außenarealen machen.

mich wundert es, weshalb die mehrmals samplen (3. 4. 5. 6.)bis sie auf 1pixel sind, ich mach das immer in einem durchganz *kopfkratz*

MfG
micki

micki
2004-11-14, 00:01:45
bei einem DrawPrimitiveUP mit <100triangles ist es absolut egal wenn man das benutzt, man kann sich sonst wie auf den kopfstellen und optimieren, der rendercall an sich ist das einzige was performance kostet.
klar es kann nicht elegant und sauber aussehen, aber performancemässig kann man da nichts raushollen, klar nv tingelt alle developer man soll das nicht machen, aber aus performance sicht bringt das leider nichts.

ich denke mir, dass des vielleicht deswegen 2 textures gibt, weil sie in z.b. innenräumen die blau/alpha textur garnicht erst verwenden. weil man als mensch vom blauwert eh nur 10% zur helligkeitswertung einfliessen lässt, deswegen würde ich das an deren stelle auch nur auf den himmelblauen außenarealen machen.

mich wundert es, weshalb die mehrmals samplen (3. 4. 5. 6.)bis sie auf 1pixel sind, ich mach das immer in einem durchganz *kopfkratz*

MfG
micki

Demirug
2004-11-15, 08:04:07
bei einem DrawPrimitiveUP mit <100triangles ist es absolut egal wenn man das benutzt, man kann sich sonst wie auf den kopfstellen und optimieren, der rendercall an sich ist das einzige was performance kostet.
klar es kann nicht elegant und sauber aussehen, aber performancemässig kann man da nichts raushollen, klar nv tingelt alle developer man soll das nicht machen, aber aus performance sicht bringt das leider nichts.

Es ist nicht egal. Wenn du mir nicht glaubst frag MS. Bei wenigern als 100 Verticen ist der Unterschied zum regulären Verfahren mit dynamischen Vertexbuffern zwar gering aber vorhanden. Für statische Daten ist es also erst recht eine Sünde weil dynamische VBs ja langsamer als statische sind.

ich denke mir, dass des vielleicht deswegen 2 textures gibt, weil sie in z.b. innenräumen die blau/alpha textur garnicht erst verwenden. weil man als mensch vom blauwert eh nur 10% zur helligkeitswertung einfliessen lässt, deswegen würde ich das an deren stelle auch nur auf den himmelblauen außenarealen machen.

Ich hatte einen Innenraum zum testen und da wurde das Blau schön verrechnet.

micki
2004-11-15, 09:36:14
Es ist nicht egal. Wenn du mir nicht glaubst frag MS. Bei wenigern als 100 Verticen ist der Unterschied zum regulären Verfahren mit dynamischen Vertexbuffern zwar gering aber vorhanden. Für statische Daten ist es also erst recht eine Sünde weil dynamische VBs ja langsamer als statische sind.
es geht nicht um glauben, sondern um wissen, wenn du 30k triangles zeichnest und mal ein batch mit 100 ohne VB, mag das unschön sein, aber messen wirst du da nicht mehr als rauschen.




Ich hatte einen Innenraum zum testen und da wurde das Blau schön verrechnet.
wird der buffer vielleicht nur jedes 2te frame oder so geupdated?

MfG
micki

Demirug
2004-11-15, 09:53:37
es geht nicht um glauben, sondern um wissen, wenn du 30k triangles zeichnest und mal ein batch mit 100 ohne VB, mag das unschön sein, aber messen wirst du da nicht mehr als rauschen.

Es ist ja nicht nur einer. Aber bei all den merkwürdigen Dingen die dort zum Einsatz kommen ist DrawPrimitiveUP sicherlich eines der kleineren Übel.

wird der buffer vielleicht nur jedes 2te frame oder so geupdated?

Die komplete Berechnung mit allen Buffern findet jeden Frame stat.

micki
2004-11-15, 10:43:10
das fand ich ja auch seltsam, wieso verkleinern die der screen nicht gleich auf einen pixel und machen da derart viel tamtam.

und es muss doch auch nen grund geben weshalb die 2 buffer benutzen und nicht 1 oder 3bzw4.
vielleicht bringt es cachemässig etwas? immerhin sind 2*16bit ein 32bit, dwords könnten doch optimal für irgendwelche busse sein in grakas...

war da nicht mal so ein 3dcenterarticle in dem stand dass die gffx gpu ein 32bit register in 2 16bit register aufsplittet?

hmhmhm

das kann doch nicht alles schwachsinn sein was die da machen so lange wie die dran sassen.

MfG
micki

HOT
2004-11-15, 11:02:02
Ist es möglich, die übertrieben Beleuchtung und Blendung, die Nachts herrscht in den Nachtleveln und recht dunklen Gängen abzuschwächen?
Irgendwie wird im HDR Mode alles so behandelt, als wenn es Tag wär und die Sonne scheint.

Demirug
2004-11-15, 11:08:53
das fand ich ja auch seltsam, wieso verkleinern die der screen nicht gleich auf einen pixel und machen da derart viel tamtam.

und es muss doch auch nen grund geben weshalb die 2 buffer benutzen und nicht 1 oder 3bzw4.
vielleicht bringt es cachemässig etwas? immerhin sind 2*16bit ein 32bit, dwords könnten doch optimal für irgendwelche busse sein in grakas...

war da nicht mal so ein 3dcenterarticle in dem stand dass die gffx gpu ein 32bit register in 2 16bit register aufsplittet?

hmhmhm

das kann doch nicht alles schwachsinn sein was die da machen so lange wie die dran sassen.

MfG
micki

IMHO wollte man HDR ursprünglich für alle Chips mit mindestens PS 2.0 einbauen. Da gibt es nun aber einige die keine 4 kanalige FP16 Texturen haben. Auch von 64*64 auf 1 Pixel runter kann man mit PS 2.0 in einem Pass vergessen. Irgendwann hat man dann wohl wegen des Alphablendings diese Pläne aufgebene. Als dann mit dem NV40 dieses Problem weggefallen ist hat man wohl das was schon fertig war genommen leicht angepasst und fertig war HDR. Bei Patches versucht man ja Geld zu sparen und wenn Crytek die Engine nicht lizenzieren würde hätten sie vielleicht auch gar nicht mehr gemacht.

Die einzige Stelle an der 2*16 gegenüber 4*16 vorteile bringen kann ist der Texturecache. Aber IMHO kann der gar nicht so viel besser bei 2*16 funktionieren um den Verlust der halben Fillrate auszugleichen.

Wie gesagt wenn ich mal etwas Zeit habe probiere ich mal aus ob es mit einer 4*16 Textur gegenüber den 2*2*16 Texturen schneller wird.

Demirug
2004-11-15, 11:16:32
Ist es möglich, die übertrieben Beleuchtung und Blendung, die Nachts herrscht in den Nachtleveln und recht dunklen Gängen abzuschwächen?
Irgendwie wird im HDR Mode alles so behandelt, als wenn es Tag wär und die Sonne scheint.

Dieser Effekt entsteht durch das normalisieren bei Schritt 8. Der Mittelwert bestimmt wie und in welche Richtung skaliert wird. Das ganze scheint nun linear zu sein. Wenn man dort noch eine Funktion einbaut die dafür sorgt das bei kleinem Mittelwert nicht mehr so heftig hochskaliert wird würde es auch nicht mehr so hell werden. Das hat also nichts mit "immer Tag" zu tun sondern mit der simulation der Augenanpassung an die Lichtverhältnisse welche etwas unrealistisch umgesetzt ist.

micki
2004-11-15, 11:27:43
Auch von 64*64 auf 1 Pixel runter kann man mit PS 2.0 in einem Pass vergessen.
ich weiß ja jetzt nicht genau was wir als pass hier verstehen.

pass := ein rendercall
pass := 1 overdraw vom pixel

um runter zu filtern von NxN auf 1x1 braucht man nichtmal nen shader, einfach eine geometrie machen die oft genug auf den pixel draufzeichnet und den pixel selbst sollte man additiv draufpappen (dafür eignet sich float(32) natürlich gut), ich glaube die ganzen bei FC nötigen targetbuffer switches oder copys (oder wie die das auch immer machen) suxx sehr, dabei ist es total unnötig.

MfG
micki

Demirug
2004-11-15, 11:54:31
Ich meinte einen Drawcall.

Dein Verfahren ist mir allerdings noch nicht ganz klar. Wenn ich es richtig verstehe bräuchte man dafür ein Objekt aus NxN Points auf der gleichen Position aber mit unterschiedlichen Texturekoordinaten. Das ganze funktioniert dann aber nur wenn man eine passenden Alphablendeinheit hat. Zudem hätte man dann ja die Summe und nicht den Mittelwert im Buffer.

Diese Variante reduziert zwar die Drawcalls und Rendertarget Switches hat IMHO dafür aber andere Probleme:

a) für jeden Pixel hat man den vollen Trisetup Overhead.
b) Wenn man nur ein Pixel Dreiecke hat bekommt man die Pipe nicht voll weil der Dreiecksspeicher nicht reicht.
c) Für das Alphablending kommt nochmal ein ordentlicher Bandbreitenverbrauch dazu.
d) Da man immer wieder den Wert braucht den man gerade in den Speicher geschrieben hat dürfte das üble blockierungen geben.

Daher würde ich dafür einen Pixelshader benutzen der die gesamte Ausgangstexture einmal abläuft dabei die Pixel addiert und am Ende mit der Anzahl verrechnet. Kein unnötiger Vertex und Trisetup Overhead und auch keine Alphablendbandbreite.

micki
2004-11-15, 14:20:00
Ich meinte einen Drawcall.

Dein Verfahren ist mir allerdings noch nicht ganz klar. Wenn ich es richtig verstehe bräuchte man dafür ein Objekt aus NxN Points auf der gleichen Position aber mit unterschiedlichen Texturekoordinaten.
natürlich ist die point anzahl ca N^2/(Texturesamplezahl*4(wegen linear zwischen 4texel))
würde bei 512*512 also optimal auf 4096fachen overdraw kommen, natürlich kann man auch auf 2x2 samplen um die pipe besser auszunutzen.


Das ganze funktioniert dann aber nur wenn man eine passenden Alphablendeinheit hat. Zudem hätte man dann ja die Summe und nicht den Mittelwert im Buffer.
1. du brauchst kein alphablend, lediglich additive colorzeichnung (ich weiß dass float blend teuer ist, aber float add ist es wohl nicht)
2. du hast die summe und weißt wieviel pixel aufaddiert wurden, daraus bekommt man doch bestimmt durch ne komplexe mathematische formal den mittelwert raus ;)


a) für jeden Pixel hat man den vollen Trisetup Overhead.
[Quote]
4096 triangles sollten zu verkraften sein, zur not kann man ja points zeichnen (ich weiß nicht was effizienter auf ner graka wäre für 1pixel

[QUOTE=Demirug]
b) Wenn man nur ein Pixel Dreiecke hat bekommt man die Pipe nicht voll weil der Dreiecksspeicher nicht reicht.

man kann fertig transformierte vertices nehmen, die sollten eigentlich direkt zum pixelshader durchgeschleift werden, klar der VS idled. macht er bei den 2rects pro call nun aber auch.


c) Für das Alphablending kommt nochmal ein ordentlicher Bandbreitenverbrauch dazu.

naja, ob 4096 reads modify writes in den cache wirklich so schlimm sind?, wenn man das auf 2x2 pixel macht, ist der overdraw sogar nur 1024 und man kann die 2x2 mit einem texread dann aus der textur (durch lineares interpolieren der texunit) for free zusammengeblendet ablesen.


d) Da man immer wieder den Wert braucht den man gerade in den Speicher geschrieben hat dürfte das üble blockierungen geben.

kommt auf die architektur an, könnte auch sein dass der wert die ganze zeit im cache mit viel kürzerer latenz liegt als die durchschnittslatenz ist wenn man einen pixel in den buffer setzen möchte (bei der FC methode)


Daher würde ich dafür einen Pixelshader benutzen der die gesamte Ausgangstexture einmal abläuft dabei die Pixel addiert und am Ende mit der Anzahl verrechnet. Kein unnötiger Vertex und Trisetup Overhead und auch keine Alphablendbandbreite.
würde jeder machen, wenn man genug texturereads hätte.
aber mehr als 64texel zu samplen schafft man leider nicht. (zur zeit)

MfG
micki

HOT
2004-11-15, 14:23:32
Dieser Effekt entsteht durch das normalisieren bei Schritt 8. Der Mittelwert bestimmt wie und in welche Richtung skaliert wird. Das ganze scheint nun linear zu sein. Wenn man dort noch eine Funktion einbaut die dafür sorgt das bei kleinem Mittelwert nicht mehr so heftig hochskaliert wird würde es auch nicht mehr so hell werden. Das hat also nichts mit "immer Tag" zu tun sondern mit der simulation der Augenanpassung an die Lichtverhältnisse welche etwas unrealistisch umgesetzt ist.

Danke :)

Gast
2004-11-15, 14:54:34
1. du brauchst kein alphablend, lediglich additive colorzeichnung (ich weiß dass float blend teuer ist, aber float add ist es wohl nicht)
2. du hast die summe und weißt wieviel pixel aufaddiert wurden, daraus bekommt man doch bestimmt durch ne komplexe mathematische formal den mittelwert raus ;)

1. Bei DX gehört das alles Zusammen. Funktioniert aber derzeit auf jeden Fall sowieso nur mit NV40 Chips.

2. Das ist mir schon klar. Man bräuchte dann noch ein zweiter Pass um die Summe auf den Mittelwert zu bekommen. Ergo Pixelshader und ein Pass.

man kann fertig transformierte vertices nehmen, die sollten eigentlich direkt zum pixelshader durchgeschleift werden, klar der VS idled. macht er bei den 2rects pro call nun aber auch.

Maximal kann man bis zum Trisetup schieben und das blockiert in der Regel bei Points.


naja, ob 4096 reads modify writes in den cache wirklich so schlimm sind?, wenn man das auf 2x2 pixel macht, ist der overdraw sogar nur 1024 und man kann die 2x2 mit einem texread dann aus der textur (durch lineares interpolieren der texunit) for free zusammengeblendet ablesen.

Wenn das Rendertarget im Cache liegt ist das sicherlich ein Argument. Nur bin ich mir nicht sicher in wie weit Rendertargets im Cache liegen.

kommt auf die architektur an, könnte auch sein dass der wert die ganze zeit im cache mit viel kürzerer latenz liegt als die durchschnittslatenz ist wenn man einen pixel in den buffer setzen möchte (bei der FC methode)

Wäre denkbar. Ist theoretisch alles etwas schwer kalkulierbar da bei dieser Sache eine ganze Menge ungünstiger Fälle zusammentreffen.

würde jeder machen, wenn man genug texturereads hätte.
aber mehr als 64texel zu samplen schafft man leider nicht. (zur zeit)

MfG
micki

Wie kommst du auf 64?

Auf meiner Liste stehen da andere zahlen (für DX):

R3XX: 32
R4XX: 512
NV3X: 512
NV4X: sehr viele (habe mir bisher nicht die mühe gemacht das genau auszurechen)

In Summe blockiert sich der Chip beim Runterechnen auf einen Pixel aber wohl sowieso an allen Ecken und Enden egal wie man es macht.

Als primären Leistungsfresser sehe ich bei Farcry nach wie vor die FP16 Rendertargets mit nur zwei Kanälen.

Demirug
2004-11-15, 14:55:56
^^ Das war ich. Keks war weg.

micki
2004-11-15, 15:22:59
*hehe*, du keks

1. Bei DX gehört das alles Zusammen. Funktioniert aber derzeit auf jeden Fall sowieso nur mit NV40 Chips.
das ändert ja nichts dran, dass blend viel langsammer als add ist, weil 2floatmul pro chan vorhanden sind.
beim additiven sollte doch angeblich nicht der fallback auf 1/5 der performance sein wie beim blend.


2. Das ist mir schon klar. Man bräuchte dann noch ein zweiter Pass um die Summe auf den Mittelwert zu bekommen. Ergo Pixelshader und ein Pass.

das könnte man entweder schon beim aufaddieren verrechnen oder dann beim auslesen der werte, so ein mull sollte nicht die welt sein.



Maximal kann man bis zum Trisetup schieben und das blockiert in der Regel bei Points.
aber bei einer karte die mehrere hundert millionen triangles glaubt zu schaffen sollten doch die 4k triangles nicht der pain sein.




Wenn das Rendertarget im Cache liegt ist das sicherlich ein Argument. Nur bin ich mir nicht sicher in wie weit Rendertargets im Cache liegen.

ich weiß auch nicht wieviel davon im cache liegt, aber ich bin mir sehr sicher dass ein teil davon im cache ist, weil die ja nicht pixelgenau aus dem ram lesen und schreiben können, sondern nur ihrer speicherbandbreite entsprechend, und deswegen denk ich mir das ein pixel durchaus im cache liegen sollte.


Wäre denkbar. Ist theoretisch alles etwas schwer kalkulierbar da bei dieser Sache eine ganze Menge ungünstiger Fälle zusammentreffen.
soweit ich weiß, ist das switchen der rendertargets ziemlich teuer, ich würde drauf tippen dass die 4k triangles billiger sein würden, vor allem, da eigentlich der pixelshader für das samplen der 16points auch seine zeit braucht, da sollte das nächste triangle schon verarbeitet worden sein.



Wie kommst du auf 64?

Auf meiner Liste stehen da andere zahlen (für DX):

R3XX: 32
R4XX: 512
NV3X: 512
NV4X: sehr viele (habe mir bisher nicht die mühe gemacht das genau auszurechen)

hab mich versehen (du dich aber auch ein wenig)
ps2.0 sollte 32 reads können (hatte 16 im kopf), jeder read liegt in mitten von 4texeln, somit sollte man auf 128 texel pro pixel kommen die man runterrechnen kann. das wären dann für 512*512 2048 triangles.



In Summe blockiert sich der Chip beim Runterechnen auf einen Pixel aber wohl sowieso an allen Ecken und Enden egal wie man es macht.
Als primären Leistungsfresser sehe ich bei Farcry nach wie vor die FP16 Rendertargets mit nur zwei Kanälen.
aber sowas offensichtliches müßten die ja selber sehen, das muss einen wichtigen grund haben. ich bin immer noch dafür dass BA abgeschaltet wird in gewissen fällen, vielleicht wenn der speicher knapp wird/ist?

MfG
micki

Demirug
2004-11-15, 15:30:24
aber sowas offensichtliches müßten die ja selber sehen, das muss einen wichtigen grund haben. ich bin immer noch dafür dass BA abgeschaltet wird in gewissen fällen, vielleicht wenn der speicher knapp wird/ist?

MfG
micki

Der Speicher für Rendertargets wird ja nur einmal am Anfang angelegt. Zudem habe ich auch keine passenden Shader gefunden welche ohne BA arbeiten würden.

Wie gesagte vermute ich das es ursprünglich als universelle Lösung für alle DX9 Karten geplannt war. Deswegen eben die Begrenzung auf PS 2.0 und FP16 2 Kanal.

Xmas
2004-11-15, 19:09:25
Wenn das Rendertarget im Cache liegt ist das sicherlich ein Argument. Nur bin ich mir nicht sicher in wie weit Rendertargets im Cache liegen.
Mindestens die aktuelle Kachel für die Color Compression. Und wenn man sowieso auf 1x1 will...


das ändert ja nichts dran, dass blend viel langsammer als add ist, weil 2floatmul pro chan vorhanden sind.
beim additiven sollte doch angeblich nicht der fallback auf 1/5 der performance sein wie beim blend.
Ich verstehe hier nicht ganz was du meinst. Auch "simples" aufaddieren zum Framebuffer-Inhalt gehört zum Blending, und wird nicht von den Shader-ALUs sondern von den ROPs erledigt.


hab mich versehen (du dich aber auch ein wenig)
ps2.0 sollte 32 reads können (hatte 16 im kopf), jeder read liegt in mitten von 4texeln, somit sollte man auf 128 texel pro pixel kommen die man runterrechnen kann. das wären dann für 512*512 2048 triangles.
Genau genommen sollte man pro Read sogar 64 statt 4 Texel lesen können. Nur kann man sich auf die AF-Implementation nicht verlassen ;)

Demirug
2004-11-15, 19:48:43
Genau genommen sollte man pro Read sogar 64 statt 4 Texel lesen können. Nur kann man sich auf die AF-Implementation nicht verlassen ;)

Die Idee hatte ich auch schon nur war mir das dann doch zu unsicher. Vorallem was die Gewichtung angeht.

micki
2004-11-16, 06:01:50
Ich verstehe hier nicht ganz was du meinst. Auch "simples" aufaddieren zum Framebuffer-Inhalt gehört zum Blending, und wird nicht von den Shader-ALUs sondern von den ROPs erledigt.

es geht nicht darum um welche einheit es geht (das sollte ja allen klar sein), sondern darum dass man für einen learp mindestens einen mul braucht, für die addition aber nicht. beim blenden (soweit ich weiß) sind die GFFX karten auf dem framebuffer langsammer als beim additiven zeichnen.

am I wrong?

MfG
micki

Xmas
2004-11-16, 15:10:17
es geht nicht darum um welche einheit es geht (das sollte ja allen klar sein), sondern darum dass man für einen learp mindestens einen mul braucht, für die addition aber nicht. beim blenden (soweit ich weiß) sind die GFFX karten auf dem framebuffer langsammer als beim additiven zeichnen.

am I wrong?

MfG
micki
Ich weiß nicht wo du das her hast, oder auch das mit dem 1/5 Geschwindigkeit (Tippfehler -> 1/2?).

Additives Blending gehört auch zum Blending, und wird AFAIK auch von denselben Einheiten, mit derselben Geschwindigkeit, erledigt.
Die Operation ist immer FragmentColor * A + FramebufferColor * B, wobei für Addition einfach A und B gleich 1 gesetzt werden.

Ob es bei GeForceFX-Karten eine reduzierte Blend-Rate gibt weiß ich nicht, vielleicht bei NV31/34.
Beim NV40 halbiert sich die Füllrate mit Blending, mit FP16-Rendertarget noch einmal, allerdings schließt "Blending" dabei die Addition mit ein. Additives Blending ist nicht schneller. Es gibt nicht mehr Add-Einheiten in den C-ROPs, weil die Bandbreite sowieso nicht reicht.


Dazu muss noch gesagt werden, dass sich zum Aufsummieren von sehr vielen Werten weder ein 8bit Framebuffer noch ein FP16-Framebuffer eignet. Und Blending (auch nur additiv) auf ein FP32-Rendertarget kann bisher kein Chip. Deswegen ist IMO die Berechnung im Pixelshader die einzig gangbare Lösung.