(gelöst) [D3D 11] Dispatch() erzwingen

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

(gelöst) [D3D 11] Dispatch() erzwingen

Beitrag von Krishty »

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?
Zuletzt geändert von Krishty am 19.02.2014, 21:24, insgesamt 1-mal geändert.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Artificial Mind
Establishment
Beiträge: 802
Registriert: 17.12.2007, 17:51
Wohnort: Aachen

Re: [D3D 11] Dispatch() erzwingen

Beitrag von Artificial Mind »

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)
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [D3D 11] Dispatch() erzwingen

Beitrag von dot »

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!?
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [D3D 11] Dispatch() erzwingen

Beitrag von Krishty »

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?
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:Du könntest mal versuchen, was passiert, wenn du ein Event in den Command Stream packst und drauf wartest. Vermutlich aber nicht so ideal...
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:Um was für Ressourcen handelt es sich da? Möglicherweise könnte man mit DXGI Resource Sharing irgendwie den Driver zwingen!?
2048² 128-Bit-HDR-Texturen. Macht im Augenblick satte 64 MiB nach jedem Arbeitsschritt um eine Kopie im RAM zu erzwingen m[
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [D3D 11] Dispatch() erzwingen

Beitrag von dot »

http://msdn.microsoft.com/en-us/library ... 69747.aspx :(
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:
  • 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.
Note that the user-mode display driver also always initiates a command-buffer submission whenever the command buffer is full.
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...
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [D3D 11] Dispatch() erzwingen

Beitrag von Krishty »

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?
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [D3D 11] Dispatch() erzwingen

Beitrag von dot »

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.
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [D3D 11] Dispatch() erzwingen

Beitrag von Krishty »

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:
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.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [D3D 11] Dispatch() erzwingen

Beitrag von dot »

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.
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...
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [D3D 11] Dispatch() erzwingen

Beitrag von Krishty »

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.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [D3D 11] Dispatch() erzwingen

Beitrag von dot »

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... ;)
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: (gelöst) [D3D 11] Dispatch() erzwingen

Beitrag von Krishty »

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 :)
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Antworten