(gelöst)[D3D9] Kosten redundanter State Changes

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

(gelöst)[D3D9] Kosten redundanter State Changes

Beitrag von Krishty »

Hi,

ungewöhnliche Frage, die man sicher nur durch Benchmarking testen kann – aber vielleicht hat das ja schon jemand für mich getan oder steckt tief genug in den Treibern:

Es gibt eine schöne Tabelle, wie viele Takte einzelne API-Aufrufe benötigen (hier ganz unten). Bspw. verbraucht SetVertexDeclaration() im Schnitt 6500–11250 Takte. Ich habe hier ein paar tausend Draw-Calls, und rufe jedes Mal vorher SetVertexDeclaration() auf. (Nicht nur diese eine Funktion, eigentlich stelle ich die komplette Pipeline vor jedem Draw Call ein.)

Jetzt des Pudels Kern: Meistens ändert sich garnichts, sondern ich setze die aktuellen Shader / Vertex Declarations / Render States etc. nochmal. Ist die Direct3D Runtime oder der Treiber klug genug, das als redundant zu erkennen und nach hundert Takten im User Mode zurückzukehren, oder sollte ich selber aufpassen, dass ich nichts redundant setze?

Ich würde dem Treiber das durchaus zutrauen, aber andererseits warnt ja die Debug Runtime vor redundanten Render States, was mich irgendwie vermuten lässt, dass die nicht wollen, dass ich mich drauf verlasse …

Gruß
Zuletzt geändert von Krishty am 12.07.2011, 01:45, insgesamt 1-mal geändert.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: [D3D9] Kosten redundanter State Changes

Beitrag von CodingCat »

Im DirectX SDK gibt es eine Beispielanwendung namens StateManager, dort lassen sich Pure und nicht-Pure-Devices mit und ohne Materialsortierung und mit und ohne eigener State-Verwaltung testen. Mein Ergebnis: nicht-Pure sind leicht schneller als Pure-Devices, in beiden Fällen bringt Materialsortierung ca. 50% weniger Framezeit, d.h. in beiden Fällen filtert die Runtime/der Treiber (mglw. abhängig von nicht-Pure/Pure?) zumindest teilweise redundante States, in beiden Fällen bringt der eigene StateManager nur Verlangsamung (der ist aber auch total miserable implementiert, IIRC). Schau einfach mal rein.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [D3D9] Kosten redundanter State Changes

Beitrag von Krishty »

Interessant. Das Pure Device wird durch den State Manager 20 % langsamer, das non-pure dagegen 10 % schneller. Beim zweiten Ausführen ist es, wie du gesagt hast: pure und non-pure ähnlich schnell, mit State Manager bedeutend langsamer.

Die Dokumentation des Beispiels beantwortet meine Frage eigentlich auch schon:
In constrast, a non-pure device (created without D3DCREATE_PUREDEVICE) will check each state change for redundancy, and discard them. This reduces the amount of work that the device will need to perform.
Aber offenbar macht der Treiber das auch nochmal.

Dann baue ich nur sehr grobes State Management ein, das per flinkem Test entweder zehn redundante Aufrufe auf einmal abfängt oder garkeine. Dankesehr!

P.S.: Lohnt es sich, DrawPrimitiveUP() zu batchen? Ich gehe mal stark davon aus, aber Fragen schadet ja nicht …
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Dirk Schulz
Establishment
Beiträge: 130
Registriert: 01.03.2009, 14:21
Alter Benutzername: frittentuete

Re: [D3D9] Kosten redundanter State Changes

Beitrag von Dirk Schulz »

Hi,

vor dem "Problem" stand ich vor kurzem auch, wollte auch schon D3D die Arbeit machen lassen, bis ich über diesen Post stolperte:

http://forums.create.msdn.com/forums/p/ ... spx#108930

20% ist schon ne Ansage. :shock:

Die Batchfrage muss man wohl wirklich nicht beantworten, oder? ;)
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [D3D9] Kosten redundanter State Changes

Beitrag von Krishty »

Verdammt, es wird immer verwirrender :(
Dirk Schulz hat geschrieben:Die Batchfrage muss man wohl wirklich nicht beantworten, oder? ;)
Nochmal aus dem Artikel:
A less obvious secondary effect is that the work for DrawPrimitive is also reduced from 1500 calls to 1 call because all of the conditions for concatenating draw calls are satisfied. When the render sequence is processed, the runtime will process 1500 calls into a single driver call.
Die Runtime führt also automatisch Batching durch, so lange keine anderen API-Aufrufe dazwischenliegen. Falls ich also zwischen den meisten Draw Calls die redundanten State Changes rausoptimiere und keine mehr übrig bleiben, könnte theoretisch auch DrawPrimitiveUP() gebatcht werden. Die Frage ist, ob das auch praktisch der Fall ist …
Zuletzt geändert von Krishty am 04.07.2011, 11:06, insgesamt 1-mal geändert.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Schrompf
Moderator
Beiträge: 4838
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: [D3D9] Kosten redundanter State Changes

Beitrag von Schrompf »

Ich habe die Filterung unnötiger State-Änderungen 2006 oder so in unsere Basisklassen eingebaut und hatte damals eine Verdopplung der Framerate erreicht. Ich muss aber zugeben, dass ich die Ergebnisse seitdem nie wieder überprüft habe.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: [D3D9] Kosten redundanter State Changes

Beitrag von CodingCat »

Dirk Schulz hat geschrieben:20% ist schon ne Ansage.
Allerdings geht es hier um XNA.
An Overview of Managed/Unmanaged Code Interop hat geschrieben:Approximate overhead for a COM interop call: 50 machine instructions (on an x86 processor)
Das dürfte bei +5000 Aufrufen ordentlich reinhauen, egal ob dann auf Runtimeseite gefiltert wird oder nicht.

Selbst in C++ ist der Overhead virtueller Methodenaufrufe jedoch alles andere als zu vernachlässigen, wie ich kürzlich mit Schrecken feststellen musste. Aua, ich habe gerade einen ultrapeinlichen Fehler im Benchmark entdeckt. Wenn man aufhört, die Zeit des falschen Timers abzufragen, ist die Welt wieder sehr viel mehr in Ordnung. In C++ liegt der Overhead Vergleich nach virtuellem Aufruf vs. Vergleich ohne Aufruf bei mir irgendwo bei 80%, bei +5000 Aufrufen ca. +0.008 ms.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [D3D9] Kosten redundanter State Changes

Beitrag von Krishty »

Meine CPU-Limitierung hat sich gerade verflüchtigt wie ein Spendenkoffer auf einem CDU-Parteitag. Ich habe direkt gebencht und kann mit Freude verkünden:
  • DrawIndexedPrimitiveUP() wird gebatcht
  • States sparen ist 0–1 % schneller als States verschwenden
  • Pure Device ist rund 0,5 % langsamer als non-pure
Mit starker CPU-Limitierung fiel die Pure-Device-Sache genau andersrum aus.

Kaum was der Rede wert. Ich bedanke mich dennoch für eure Hilfe!
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Antworten