Draw Calls sortieren
Draw Calls sortieren
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?
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.
http://launix.de <-- kompetente Firma
In allen Posts ist das imo und das afaik inbegriffen.
- dot
- Establishment
- Beiträge: 1746
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: Draw Calls sortieren
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:Meine Frage: Bringen die hier angezählten Vorteile wirklich etwas? Oder ist ihr Aufwand den Implementierungsaufwand nicht wert?
Nachdem du's gemessen hast, gibt's genau Zahlen ;)antisteo hat geschrieben:Gibt es genaue Zahlen, wieviel Prozent Speedup man dadurch maximal herausholen kann?
Re: Draw Calls sortieren
Ich dachte da eher an einige Paper, bei denen schon mal gemessen wurde ;)dot hat geschrieben:Nachdem du's gemessen hast, gibt's genau Zahlen ;)antisteo hat geschrieben: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.
http://launix.de <-- kompetente Firma
In allen Posts ist das imo und das afaik inbegriffen.
- dot
- Establishment
- Beiträge: 1746
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: Draw Calls sortieren
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:
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:
Das ist im Prinzip alles, was in diesem 65 Seiten langen Dokument dazu steht. Das und3.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.
Zusammenfassung: Ja, Sortieren bringt unter Umständen was...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.
Re: Draw Calls sortieren
Okay,
also lieber möglichst viel Fragmente beim Tiefentest rauskicken, als auf Constant Changes zu optimieren.
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.
http://launix.de <-- kompetente Firma
In allen Posts ist das imo und das afaik inbegriffen.
- dot
- Establishment
- Beiträge: 1746
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: Draw Calls sortieren
Ich denk, du solltest den Satz nochmal genauer lesen:
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...
;)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...
- Schrompf
- Moderator
- Beiträge: 5161
- Registriert: 25.02.2009, 23:44
- Benutzertext: Lernt nur selten dazu
- Echter Name: Thomas
- Wohnort: Dresden
- Kontaktdaten:
Re: Draw Calls sortieren
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
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.
Re: Draw Calls sortieren
Na das ist doch mal ein Wort.Schrompf hat geschrieben:Erfahrung von den Splitterwelten: Sortierung hatte die Framerate etwa verdoppelt. Habe es aber lange nicht mehr nachgemessen.
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.Schrompf hat geschrieben:- teure States, z.B: ZBuffer-Sortierkriterien
http://fedoraproject.org/ <-- freies Betriebssystem
http://launix.de <-- kompetente Firma
In allen Posts ist das imo und das afaik inbegriffen.
http://launix.de <-- kompetente Firma
In allen Posts ist das imo und das afaik inbegriffen.
- CodingCat
- Establishment
- Beiträge: 1857
- Registriert: 02.03.2009, 21:25
- Wohnort: Student @ KIT
- Kontaktdaten:
Re: Draw Calls sortieren
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.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.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Re: Draw Calls sortieren
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":antisteo hat geschrieben: - Glasscheiben, Alphablending wird generell möglich
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.
Re: Draw Calls sortieren
Das "grobe" hat man natürlich im Hinterkopf, wenn man zum Beispiel die Landschaft zeichnet. Dort läuft es auch schön schnell.mOfl hat geschrieben:Sortieren an sich ist generell immer ratsam, zumindest grob nach Shadern und so.
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.
http://launix.de <-- kompetente Firma
In allen Posts ist das imo und das afaik inbegriffen.
- Schrompf
- Moderator
- Beiträge: 5161
- Registriert: 25.02.2009, 23:44
- Benutzertext: Lernt nur selten dazu
- Echter Name: Thomas
- Wohnort: Dresden
- Kontaktdaten:
Re: Draw Calls sortieren
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.
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.