Draw Calls sortieren

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
antisteo
Establishment
Beiträge: 854
Registriert: 15.10.2010, 09:26
Wohnort: Dresdem

Draw Calls sortieren

Beitrag von antisteo »

Hallo,

ich überlege gerade, ob es sinnvoll ist, die Draw Calls in der Grafikengine zu sortieren, bevor man sie rendert. Als Sortierkriterium dachte ich mir Material und Tiefe.
Ich stelle mir folgende Vorteile vor:
- Weniger Statechanges
- Weniger Fragmente zu berechnen, da ich den Tiefentest-Fail provozieren kann
- Glasscheiben, Alphablending wird generell möglich

Die Sortierung der Elemente dürfte nicht der Flaschenhals an sich sein, da man Sortierung gut parallelisieren kann und auch in einen anderen Thread auslagern kann.

Meine Frage: Bringen die hier angezählten Vorteile wirklich etwas? Oder ist ihr Aufwand den Implementierungsaufwand nicht wert? Gibt es genaue Zahlen, wieviel Prozent Speedup man dadurch maximal herausholen kann?
http://fedoraproject.org/ <-- freies Betriebssystem
http://launix.de <-- kompetente Firma
In allen Posts ist das imo und das afaik inbegriffen.
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: Draw Calls sortieren

Beitrag von dot »

antisteo hat geschrieben:Meine Frage: Bringen die hier angezählten Vorteile wirklich etwas? Oder ist ihr Aufwand den Implementierungsaufwand nicht wert?
Hängt davon ab. Wenn du fünf Objekte renderst, ist es vermutlich völlig egal. Wenn du tausend Objekte mit hundert verschiedenen Materialien rendern willst, bringt es wahrscheinlich was. Wobei man bei der Sortierung richtig priorisieren muss. Ein Shaderwechsel ist z.B. vermutlich schwerwiegender als ein Texturwechsel...
antisteo hat geschrieben:Gibt es genaue Zahlen, wieviel Prozent Speedup man dadurch maximal herausholen kann?
Nachdem du's gemessen hast, gibt's genau Zahlen ;)
antisteo
Establishment
Beiträge: 854
Registriert: 15.10.2010, 09:26
Wohnort: Dresdem

Re: Draw Calls sortieren

Beitrag von antisteo »

dot hat geschrieben:
antisteo hat geschrieben:Gibt es genaue Zahlen, wieviel Prozent Speedup man dadurch maximal herausholen kann?
Nachdem du's gemessen hast, gibt's genau Zahlen ;)
Ich dachte da eher an einige Paper, bei denen schon mal gemessen wurde ;)
http://fedoraproject.org/ <-- freies Betriebssystem
http://launix.de <-- kompetente Firma
In allen Posts ist das imo und das afaik inbegriffen.
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: Draw Calls sortieren

Beitrag von dot »

Das hängt wohl viel zu sehr von der konkreten Anwendung, der API, der Hardware, dem Driver etc. ab, als dass man da irgendwelche allgemeineren Aussagen treffen könnte als: Sortieren bringt unter Umständen oft was.
Ich bezweifle also, dass du da Paper mit allgemeinen Analysen finden wirst. Bei der einen Anwendung bringt's vielleicht +20% Performance, bei der nächsten -3%...

Edit: Schaun wir z.B. mal, was der NVIDIA GPU Programming Guide dazu zu sagen hat:
3.2.2. Reduce state changes and constant changes
Group batches by render stage to avoid excessive state changes. In addition don’t re-set render state if it is not necessary. If a state is set to the proper value, then it will cause overhead to set it to the same value.
Be aware that this grouping may not be desired as it might break other sorting that is required by the engine.
If you are not performing a depth pre-pass then in many cases it is better to allow some fragmentation of constants and state changes in favor of sorting front to back.
Das ist im Prinzip alles, was in diesem 65 Seiten langen Dokument dazu steht. Das und
With the introduction of DirectX 10, we have seen a significant change in the performance characteristics of 3D applications.

[...]

One recommendation that has not changed is to sort draw calls by render states.
Zusammenfassung: Ja, Sortieren bringt unter Umständen was...
antisteo
Establishment
Beiträge: 854
Registriert: 15.10.2010, 09:26
Wohnort: Dresdem

Re: Draw Calls sortieren

Beitrag von antisteo »

Okay,
also lieber möglichst viel Fragmente beim Tiefentest rauskicken, als auf Constant Changes zu optimieren.
http://fedoraproject.org/ <-- freies Betriebssystem
http://launix.de <-- kompetente Firma
In allen Posts ist das imo und das afaik inbegriffen.
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: Draw Calls sortieren

Beitrag von dot »

Ich denk, du solltest den Satz nochmal genauer lesen:
If you are not performing a depth pre-pass then in many cases it is better to allow some fragmentation of constants and state changes in favor of sorting front to back.
;)

Da steht nicht, dass es im Prinzip immer besser ist und dass du das daher in deiner Anwendung so machen solltest. Wenn deine Anwendung nicht fragment bound ist, dann ist es evtl. völlig egal, ob du nun mit early z cull renderst oder nicht...

Probiers eben aus und miss, was es in deiner Anwendung bringt. Wenn du vorher genauer analysieren willst, solltest du erstmal rausfinden, wo bei deiner konkreten Anwendung im Moment das Bottleneck liegt, falls es eines gibt. Dann kann man sich überlegen, ob es potentiel was bringen könnte, oder eher nicht...

Prinzipiell ist es natürlich so, dass sortiert Rendern effizienter ist als völlig durcheinander. Die Frage ist eben, ob du unterm Strich was gewinnst. Denn das Sortieren ist in der Regel ja auch mit Overhead verbunden, nur halt eine andere Art von Overhead. Es ist eben ein Trade-off: Rechtfertigt der CPU seitige Overhead durchs Sortieren die Gewinne an anderer Stelle? Wenn ja, super, wenn du damit effektiv 0.05ms gut machst, bringts wohl nix und wenn du in deiner Anwendung sowieso schon CPU bound bist und die GPU sich langweilt, ist es vermutlich weniger sinnvoll, in jedem Frame auch noch 10000 Objekte zu sortieren...
Benutzeravatar
Schrompf
Moderator
Beiträge: 4884
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Draw Calls sortieren

Beitrag von Schrompf »

Erfahrung von den Splitterwelten: Sortierung hatte die Framerate etwa verdoppelt. Habe es aber lange nicht mehr nachgemessen.

Reihenfolgen-Empfehlung (absteigend nach Performance-Wichtigkeit):
- Vertex Declaration
- Vertex/PixelShader
- teure States, z.B: ZBuffer-Sortierkriterien
- Texturen
- Vertex-/IndexBuffer
- billige States
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
antisteo
Establishment
Beiträge: 854
Registriert: 15.10.2010, 09:26
Wohnort: Dresdem

Re: Draw Calls sortieren

Beitrag von antisteo »

Schrompf hat geschrieben:Erfahrung von den Splitterwelten: Sortierung hatte die Framerate etwa verdoppelt. Habe es aber lange nicht mehr nachgemessen.
Na das ist doch mal ein Wort.
Schrompf hat geschrieben:- teure States, z.B: ZBuffer-Sortierkriterien
Ich rede mal von ATI (bin mir aber sicher, dass NVIDIA es nicht sonderlich anders macht): Jeder Statechange ist gewissermaßen "teuer" in dem Sinne, dass die Pipeline auslaufen muss. Wie teuer hängt dann nur noch davon ab, wie viele Befehle zum Setzen des neuen State benötigt werden (proportional zur Anzahl der zu ändernden Register). Ich vermute mal, dass Shaderwechsel sehr teuer sind (komplettes Programm auswechseln), während andere State Changes sich bei 6 Registern Delta eintümpeln werden. Die Hauptkosten sind aber das Leerlaufen der Pipeline, was ich verhindern will.
http://fedoraproject.org/ <-- freies Betriebssystem
http://launix.de <-- kompetente Firma
In allen Posts ist das imo und das afaik inbegriffen.
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Draw Calls sortieren

Beitrag von CodingCat »

antisteo hat geschrieben:Jeder Statechange ist gewissermaßen "teuer" in dem Sinne, dass die Pipeline auslaufen muss. Wie teuer hängt dann nur noch davon ab, wie viele Befehle zum Setzen des neuen State benötigt werden (proportional zur Anzahl der zu ändernden Register). Ich vermute mal, dass Shaderwechsel sehr teuer sind (komplettes Programm auswechseln), während andere State Changes sich bei 6 Registern Delta eintümpeln werden. Die Hauptkosten sind aber das Leerlaufen der Pipeline, was ich verhindern will.
Nein, die Pipeline muss nicht permanent auslaufen. Wenn dem so wäre, würden wir vermutlich heute noch maximal 100 Objekte rendern, weil sich pro Objekt mindestens ein paar Konstanten ändern. Ganz im Gegenteil, es gibt große Unterschiede bei den Kosten von State Changes. Es ist offensichtlich, dass es sich weniger lohnt, Hardware-seitig das Wechseln von selten verändertem Zustand wie Render Targets zu optimieren, als zum Beispiel das Wechseln von Shader-Konstanten oder Texturen. Letztere dürften auf aktueller Hardware kaum zu vollständigen Pipeline Flushes führen, auch wenn ich bezweifle, dass es hierzu offizielle Spezifikationen oder Garantien gibt. Einen Überblick über mögliche Behandlungsweisen von State Changes gibt folgender Artikel von Fabian Giesen: A trip through the Grphics Pipeline 2011: GPU memory architecture and the Command Processor.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
mOfl
Beiträge: 37
Registriert: 23.10.2010, 21:53

Re: Draw Calls sortieren

Beitrag von mOfl »

antisteo hat geschrieben: - Glasscheiben, Alphablending wird generell möglich
Auch wenn es weniger mit der eigentlichen Frage zu tun hat: Du solltest bedenken, dass eine Per-Object- oder Per-Polygon-Sortierung kein Garant für korrekte Transparenz ist. Klassisches Beispiel hierfür ist der "Tripe Overlap": Bild

Um das korrekt zu sortieren, müsstest du die Polygone vorher korrekt zerteilen. Da ist es bequemer, einfach Depth Peeling oder auf neueren Grafikkarten Linked Lists für Fragmente zu machen. Das gilt jetzt aber wirklich nur für die "korrekte" Transparenz, Sortieren an sich ist generell immer ratsam, zumindest grob nach Shadern und so.
antisteo
Establishment
Beiträge: 854
Registriert: 15.10.2010, 09:26
Wohnort: Dresdem

Re: Draw Calls sortieren

Beitrag von antisteo »

mOfl hat geschrieben:Sortieren an sich ist generell immer ratsam, zumindest grob nach Shadern und so.
Das "grobe" hat man natürlich im Hinterkopf, wenn man zum Beispiel die Landschaft zeichnet. Dort läuft es auch schön schnell.
Bei den Objekten ist es aber nicht immer vorhersehbar, in welcher Reihenfolge diese in der Liste liegen. Deshalb wäre es dort vielleicht sinnvoll, zu sortieren.
Noch ein Problem: Der Pixel Shader der Landschaft ist irre teuer. Den sollte man so oft wie möglich mit Z-Tests rauskicken und möglichst alle Objekte schon vorher zeichnen, damit die auch noch Landschafts-Pixel rauskicken. (Oder meint ihr, hier wäre Occlusion culling besser geeignet?)
http://fedoraproject.org/ <-- freies Betriebssystem
http://launix.de <-- kompetente Firma
In allen Posts ist das imo und das afaik inbegriffen.
Benutzeravatar
Schrompf
Moderator
Beiträge: 4884
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Draw Calls sortieren

Beitrag von Schrompf »

Definiere "irre teuer". Ich habe einen PräZ-Pass in die Splitterwelten eingebaut, der bis zu 30% Performance gebracht hat. Das war 2005 auf einer ATI Radeon 9800. Seitdem ist viel Wasser die Flüsse herabgeflossen. Meine letzte Messung 2008 oder so zeigte, dass die doppelte Menge DrawCalls im Vergleich zum Gewinn eine barbarische Rechenzeitverschwendung ist. Nur leider bin ich inzwischen für diverse PostProcessingFX und Spezialeffekte auf die Daten angewiesen.

Irgendwann demnächst wechsel ich auf einen Deferred Renderer. Vielleicht gleich mit DX11, tile-based und mit Fragment Lists, um auch den Bewuchs deferred shaden zu können.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Antworten