(gelöst) [D3D 11] Dispatch() erzwingen
- Krishty
- Establishment
- Beiträge: 8350
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
(gelöst) [D3D 11] Dispatch() erzwingen
Hi,
Ich habe einen Batzen Aufgaben zu berechnen und Dispatch()e sie an einen Compute Shader. Der Grafiktreiber führt die Aufgaben jedoch (natürlich) nicht sofort aus, sondern sammelt sie.
Also staut sich eine riesige Menge Aufgaben an, und wenn ich dann via Map() auf das Ergebnis zugreife, bricht das Programm aufgrund eines GPU-Timeouts zusammen. Wie viele einzelne Dispatch()-Aufrufe es sind spielt keine Rolle; nur die Summe ist entscheidend (es bringt also nichts, das Problem in kleinere Häppchen aufzuteilen).
Mappe ich die Ressourcen nach jedem Dispatch() um die Berechnung zu erzwingen, funktioniert das Programm tadellos, weil die Aufgaben einzeln schnell genug verarbeitet sind. Aber das ist der schlimmstmögliche Weg, weil ich dauernd um die 100 MiB Ressourcen allokieren, kopieren, auf die CPU herunterladen, und wieder freigeben muss. Wenn ich einzelne Sub-Ressourcen (wie bestimmte Mip-Levels) berechnen muss, wird es umso schlimmer.
ID3D11DeviceContext::Flush() ist wirkungslos. Direct3D 11.1 hat ein Flag um den Timeout abzuschalten, aber ich habe hier nur 11.0 zur Verfügung.
Wat do?
Ich habe einen Batzen Aufgaben zu berechnen und Dispatch()e sie an einen Compute Shader. Der Grafiktreiber führt die Aufgaben jedoch (natürlich) nicht sofort aus, sondern sammelt sie.
Also staut sich eine riesige Menge Aufgaben an, und wenn ich dann via Map() auf das Ergebnis zugreife, bricht das Programm aufgrund eines GPU-Timeouts zusammen. Wie viele einzelne Dispatch()-Aufrufe es sind spielt keine Rolle; nur die Summe ist entscheidend (es bringt also nichts, das Problem in kleinere Häppchen aufzuteilen).
Mappe ich die Ressourcen nach jedem Dispatch() um die Berechnung zu erzwingen, funktioniert das Programm tadellos, weil die Aufgaben einzeln schnell genug verarbeitet sind. Aber das ist der schlimmstmögliche Weg, weil ich dauernd um die 100 MiB Ressourcen allokieren, kopieren, auf die CPU herunterladen, und wieder freigeben muss. Wenn ich einzelne Sub-Ressourcen (wie bestimmte Mip-Levels) berechnen muss, wird es umso schlimmer.
ID3D11DeviceContext::Flush() ist wirkungslos. Direct3D 11.1 hat ein Flag um den Timeout abzuschalten, aber ich habe hier nur 11.0 zur Verfügung.
Wat do?
Zuletzt geändert von Krishty am 19.02.2014, 21:24, insgesamt 1-mal geändert.
- Artificial Mind
- Establishment
- Beiträge: 802
- Registriert: 17.12.2007, 17:51
- Wohnort: Aachen
Re: [D3D 11] Dispatch() erzwingen
Ich hätte dir jetzt ja glFinish angeboten. Aber erste Recherchen ergeben kein Dx-Äquivalent :(
(Flush sendet ja nur den Command Buffer aber wartet natürlich nicht auf die Ausführung)
(Flush sendet ja nur den Command Buffer aber wartet natürlich nicht auf die Ausführung)
- dot
- Establishment
- Beiträge: 1746
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: [D3D 11] Dispatch() erzwingen
Hilft es vielleicht, einfach dummyhalber immer im jeweils nächsten Dispatch() ein ShaderResourceView in eine im vorhergehenden Dispatch() verwendete Ressource zu binden?
Du könntest mal versuchen, was passiert, wenn du ein Event in den Command Stream packst und drauf wartest. Vermutlich aber nicht so ideal...
Um was für Ressourcen handelt es sich da? Möglicherweise könnte man mit DXGI Resource Sharing irgendwie den Driver zwingen!?
Du könntest mal versuchen, was passiert, wenn du ein Event in den Command Stream packst und drauf wartest. Vermutlich aber nicht so ideal...
Um was für Ressourcen handelt es sich da? Möglicherweise könnte man mit DXGI Resource Sharing irgendwie den Driver zwingen!?
- Krishty
- Establishment
- Beiträge: 8350
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [D3D 11] Dispatch() erzwingen
Nein; absolut nicht. Das wird genau so spät ausgewertet wie CopyResource(). ALLES wird aufgeschoben bis entweder ein Map() oder ein Present() folgt; sowohl auf Nvidia als auch auf AMD – aber bei letzteren wird beim endgültigen Abarbeiten zumindest nicht der Grafiktreiber zurückgesetzt :(dot hat geschrieben:Hilft es vielleicht, einfach dummyhalber immer im jeweils nächsten Dispatch() ein ShaderResourceView in eine im vorhergehenden Dispatch() verwendete Ressource zu binden?
Ui … habe ich noch nie mit gearbeitet; muss ich mir erstmal ansehen. Schaut aber so aus als ob man damit die Wirkungen auf der GPU abfragt – könnte wirklich funktionieren :) Spätestens morgen weiß ich mehr.dot hat geschrieben:Du könntest mal versuchen, was passiert, wenn du ein Event in den Command Stream packst und drauf wartest. Vermutlich aber nicht so ideal...
2048² 128-Bit-HDR-Texturen. Macht im Augenblick satte 64 MiB nach jedem Arbeitsschritt um eine Kopie im RAM zu erzwingen m[dot hat geschrieben:Um was für Ressourcen handelt es sich da? Möglicherweise könnte man mit DXGI Resource Sharing irgendwie den Driver zwingen!?
- dot
- Establishment
- Beiträge: 1746
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: [D3D 11] Dispatch() erzwingen
http://msdn.microsoft.com/en-us/library ... 69747.aspx :(
Was du auch noch probieren könntest: Pack deine Aufrufe per Deferred Context in eine separate Command List und stopf die ganze Command List dann in den Immediate Context. Zumindest wenn der Driver Command Lists supported, könnte das vielleicht was nützen...MSDN hat geschrieben:The user-mode display driver initiates a command-buffer submission if the Direct3D runtime calls one of the following user-mode display driver functions to perform the specified operation:Note that the user-mode display driver also always initiates a command-buffer submission whenever the command buffer is full.
- The Present function to display graphics.
- The Flush function to submit hardware commands.
- The Lock function to lock a resource, which is used in the current command batch.
- Krishty
- Establishment
- Beiträge: 8350
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [D3D 11] Dispatch() erzwingen
Inwiefern könnten Command Lists was nützen? Sollte es nicht eigentlich keinen Unterschied machen ob ich die Befehle direkt gebe oder indirekt durch eine Command List?
- dot
- Establishment
- Beiträge: 1746
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: [D3D 11] Dispatch() erzwingen
Falls der Driver im Hintergrund Command Lists als echte Command Buffer implementiert, könnte es ja sein, dass ein ExecuteCommandList() am Immediate Context den entsprechenden Command Buffer zum Kernel flushed...
Zuletzt geändert von dot am 18.02.2014, 10:33, insgesamt 1-mal geändert.
- Krishty
- Establishment
- Beiträge: 8350
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [D3D 11] Dispatch() erzwingen
Ah; verstehe. Kommt mit auf die Liste :-)
Gespannt bin ich auf die Queries. Theoretisch hält den Treiber AFAIK nichts davon ab, die Befehle trotzdem aufzustauen und meine Query-Anfragen mit „dauert noch“ abzuschmettern:
Gespannt bin ich auf die Queries. Theoretisch hält den Treiber AFAIK nichts davon ab, die Befehle trotzdem aufzustauen und meine Query-Anfragen mit „dauert noch“ abzuschmettern:
GPU PROFILING IN DX11 WITH QUERIES (http://mynameismjp.wordpress.com/2011/10/13/profiling-in-dx11-with-queries/) hat geschrieben:Like any query, you need to wait for the GPU to actually execute all of the commands you submitted for the data to be ready.
Zuletzt geändert von Krishty am 18.02.2014, 10:37, insgesamt 1-mal geändert.
- dot
- Establishment
- Beiträge: 1746
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: [D3D 11] Dispatch() erzwingen
Ja, im schlimmsten Fall wird es sogar schlechter laufen als jetzt, aber probieren kann man es ja. In OpenGL gibt es explizite Memory Fence Events, die afaik genau das machen würden, was du gerne hättest. Man kann hoffen, dass D3D Events (Query vom Typ D3D11_QUERY_EVENT) die selbe Wirkung haben, da sie konzeptionell identisch sind. Da du durch das Warten auf der Event Query ja einen expliziten Sync Point mit der GPU erzeugst, sollte der Driver dazu veranlasst werden, zu flushen, da er ja deine Anwendung sonst potentiell in eine Endlosschleife schicken würde. Ist von allen Optionen, die mir so einfallen, wohl bei weitem die vielversprechendste...Krishty hat geschrieben:Gespannt bin ich auf die Queries. Theoretisch hält den Treiber AFAIK nichts davon ab, die Befehle trotzdem aufzustauen und meine Query-Anfragen mit „dauert noch“ abzuschmettern.
- Krishty
- Establishment
- Beiträge: 8350
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [D3D 11] Dispatch() erzwingen
Klingt vielversprechend. Zumal auch Chromium D3D11_QUERY_EVENT in einer Datei namens fence11.cpp einsetzt: https://chromium.googlesource.com/exter ... ence11.cpp
Demnach wäre das Vorgehen ungefähr:
ID3D11Query * toQuery;
D3D11_QUERY_DESC desc = { D3D11_QUERY_EVENT, 0 };
device.createQuery(&desc, &toQuery);
deviceContext.End(toQuery); // "When using this type of query, ID3D11DeviceContext::Begin is disabled."
while(S_OK != deviceContext.GetData(toQuery, nullptr, 0, 0)) {
Sleep(1);
}
toQuery->Release();
Wofür ist das End() ohne Begin() da? Steht auf MSDN – D3D11_QUERY Enumeration.
Demnach wäre das Vorgehen ungefähr:
ID3D11Query * toQuery;
D3D11_QUERY_DESC desc = { D3D11_QUERY_EVENT, 0 };
device.createQuery(&desc, &toQuery);
deviceContext.End(toQuery); // "When using this type of query, ID3D11DeviceContext::Begin is disabled."
while(S_OK != deviceContext.GetData(toQuery, nullptr, 0, 0)) {
Sleep(1);
}
toQuery->Release();
- dot
- Establishment
- Beiträge: 1746
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: [D3D 11] Dispatch() erzwingen
Jap, wobei du das Query Objekt nur einmal erzeugen musst und dann behalten kannst; nur für den Fall, dass das aus dem Beispielcode nicht ganz klar wird... ;)
- Krishty
- Establishment
- Beiträge: 8350
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: (gelöst) [D3D 11] Dispatch() erzwingen
Stimmt; weil es sich um offline-Berechnungen handelt war das für mich nebensächlich – danke für den Hinweis :)
Auf der GeForce GTX klappt der Code ganz hervorragend. Ich kann immer noch nicht für hundertprozentiges Fencing garantieren (die anderen GPU-Aufgaben verwässern meine Tests), aber jedenfalls sind die Pakete jetzt klein genug dass der Grafiktreiber nie zurückgesetzt werden muss! Vielen Dank für eure Hilfe :)
Auf der GeForce GTX klappt der Code ganz hervorragend. Ich kann immer noch nicht für hundertprozentiges Fencing garantieren (die anderen GPU-Aufgaben verwässern meine Tests), aber jedenfalls sind die Pakete jetzt klein genug dass der Grafiktreiber nie zurückgesetzt werden muss! Vielen Dank für eure Hilfe :)