Freigeben über


Kopieren und Zugreifen auf Ressourcendaten

Verwendungskennzeichnungen geben an, wie die Anwendung die Ressourcendaten verwenden möchte, um Ressourcen im leistungsstärksten Speicherbereich zu platzieren. Ressourcendaten werden über Ressourcen hinweg kopiert, sodass die CPU oder GPU ohne Auswirkungen auf die Leistung darauf zugreifen kann.

Es ist nicht erforderlich, ressourcen als im Videospeicher oder im Systemspeicher zu erstellen, oder um zu entscheiden, ob die Laufzeit den Speicher verwalten soll. Mit der Architektur des WDDM (Windows Display Driver Model) erstellen Anwendungen Direct3D-Ressourcen mit unterschiedlichen Verwendungskennzeichnungen, um anzugeben, wie die Anwendung die Ressourcendaten verwenden möchte. Dieses Treibermodell virtualisiert den von Ressourcen verwendeten Arbeitsspeicher; es liegt in der Verantwortung des Betriebssystem-/Treiber-/Speicher-Managers, Ressourcen im leistungsstärksten Speicherbereich zu platzieren, da die erwartete Nutzung möglich ist.

Der Standardfall ist, dass Ressourcen für die GPU verfügbar sind. Es gibt Zeiten, in denen die Ressourcendaten für die CPU verfügbar sein müssen. Das Kopieren von Ressourcendaten, damit der entsprechende Prozessor darauf zugreifen kann, ohne dass die Leistung beeinträchtigt wird, erfordert einige Kenntnisse darüber, wie die API-Methoden funktionieren.

Kopieren von Ressourcendaten

Ressourcen werden im Arbeitsspeicher erstellt, wenn Direct3D einen Create-Aufruf ausführt. Sie können im Videospeicher, im Systemspeicher oder in anderen Speicherarten erstellt werden. Da das WDDM-Treibermodell diesen Speicher virtualisiert, müssen Anwendungen nicht mehr nachverfolgen, in welcher Art von Speicherressourcen erstellt werden.

Im Idealfall befinden sich alle Ressourcen im Videospeicher, sodass die GPU sofortigen Zugriff darauf haben kann. Es ist jedoch manchmal erforderlich, dass die CPU die Ressourcendaten liest oder die GPU auf Ressourcendaten zugreifen kann, in die die CPU geschrieben hat. Direct3D behandelt diese verschiedenen Szenarien, indem die Anwendung eine Verwendung anfordert, und bietet dann bei Bedarf mehrere Methoden zum Kopieren von Ressourcendaten.

Je nachdem, wie die Ressource erstellt wurde, ist es nicht immer möglich, direkt auf die zugrunde liegenden Daten zuzugreifen. Dies kann bedeuten, dass die Ressourcendaten aus der Quellressource in eine andere Ressource kopiert werden müssen, auf die der entsprechende Prozessor zugreifen kann. In Bezug auf Direct3D kann direkt über die GPU auf Standardressourcen zugegriffen werden, auf dynamische Ressourcen und Stagingressourcen kann direkt von der CPU zugegriffen werden.

Nachdem eine Ressource erstellt wurde, kann die Verwendung nicht mehr geändert werden. Kopieren Sie stattdessen den Inhalt einer Ressource in eine andere Ressource, die mit einer anderen Verwendung erstellt wurde. Sie kopieren Ressourcendaten aus einer Ressource in eine andere, oder kopieren Sie Daten aus dem Speicher in eine Ressource.

Es gibt zwei Hauptarten von Ressourcen: zuordnungsfähig und nicht zugeordnet. Ressourcen, die mit dynamischen oder Staging-Verwendungen erstellt wurden, können zugeordnet werden, während Ressourcen, die mit Standard- oder unveränderlichen Verwendungen erstellt wurden, nicht zugeordnet werden können.

Das Kopieren von Daten zwischen nicht zugeordneten Ressourcen ist sehr schnell, da dies der häufigste Fall ist und für eine gute Leistung optimiert wurde. Da diese Ressourcen nicht direkt von der CPU zugänglich sind, sind sie optimiert, damit die GPU sie schnell bearbeiten kann.

Das Kopieren von Daten zwischen zugeordneten Ressourcen ist problematischer, da die Leistung von der Verwendung abhängig ist, mit der die Ressource erstellt wurde. Beispielsweise kann die GPU eine dynamische Ressource relativ schnell lesen, aber nicht in sie schreiben, und die GPU kann nicht direkt in Stagingressourcen lesen oder schreiben.

Anwendungen, die Daten aus einer Ressource mit Standardverwendung in eine Ressource mit Stagingverwendung kopieren möchten (damit die CPU die Daten lesen kann – d. h. das GPU-Leseproblem) müssen dies mit Bedacht tun. Siehe "Zugreifen auf Ressourcendaten" weiter unten.

Zugreifen auf Ressourcendaten

Für den Zugriff auf eine Ressource ist die Zuordnung der Ressource erforderlich; Die Zuordnung bedeutet im Wesentlichen, dass die Anwendung versucht, der CPU Zugriff auf den Arbeitsspeicher zu gewähren. Der Prozess der Zuordnung einer Ressource, damit die CPU auf den zugrunde liegenden Speicher zugreifen kann, kann zu Leistungsengpässen führen. Aus diesem Grund müssen Sie sich darum kümmern, wie und wann diese Aufgabe ausgeführt werden soll.

Die Leistung kann angehalten werden, wenn die Anwendung versucht, eine Ressource zu einem falschen Zeitpunkt zuzuordnen. Wenn die Anwendung versucht, auf die Ergebnisse eines Vorgangs zuzugreifen, bevor dieser Vorgang abgeschlossen ist, tritt ein Pipeline-Stall auf.

Das Ausführen eines Kartenvorgangs zu einem falschen Zeitpunkt kann zu einem schwerwiegenden Leistungsverlust führen, indem die GPU und die CPU gezwungen werden, miteinander zu synchronisieren. Diese Synchronisierung tritt auf, wenn die Anwendung auf eine Ressource zugreifen möchte, bevor die GPU damit fertig ist, sie in eine Ressource zu kopieren, die die CPU zuordnen kann.

Leistungsüberlegungen

Es empfiehlt sich, einen PC als computer zu betrachten, der als parallele Architektur mit zwei Haupttypen von Prozessoren ausgeführt wird: eine oder mehrere CPU und eine oder mehrere GPUs. Wie bei jeder parallelen Architektur wird die beste Leistung erzielt, wenn jeder Prozessor mit genügend Aufgaben geplant wird, um zu verhindern, dass er im Leerlauf läuft und wenn die Arbeit eines Prozessors nicht auf die Arbeit eines anderen wartet.

Das szenario für GPU/CPU-Parallelität ist die Notwendigkeit, einen Prozessor zu zwingen, auf die Ergebnisse der arbeit von einem anderen zu warten. Direct3D entfernt diese Kosten durch asynchrone Kopiermethoden; die Kopie nicht unbedingt ausgeführt wird, wenn die Methode zurückgegeben wird.

Der Vorteil besteht darin, dass die Anwendung die Leistungskosten des tatsächlichen Kopierens der Daten erst dann zahlt, wenn die CPU auf die Daten zugreift. Dies ist der Fall, wenn Map aufgerufen wird. Wenn die Map-Methode aufgerufen wird, nachdem die Daten tatsächlich kopiert wurden, tritt kein Leistungsverlust auf. Wenn die Map-Methode dagegen aufgerufen wird, bevor die Daten kopiert wurden, tritt ein Pipelinestand auf.

Asynchrone Aufrufe in Direct3D (die die überwiegende Mehrheit der Methoden und insbesondere Renderaufrufe sind) werden in einem so genannten Befehlspuffer gespeichert. Dieser Puffer ist intern für den Grafiktreiber und wird verwendet, um Aufrufe der zugrunde liegenden Hardware zu stapeln, sodass der kostspielige Wechsel vom Benutzermodus zum Kernelmodus in Microsoft Windows so selten wie möglich erfolgt.

Der Befehlspuffer wird geleert, wodurch ein Benutzer-/Kernelmoduswechsel in einem von vier Situationen wie folgt verursacht wird.

  1. "Present" wird aufgerufen.
  2. Flush wird aufgerufen.
  3. Der Befehlspuffer ist voll; seine Größe ist dynamisch und wird vom Betriebssystem und dem Grafiktreiber gesteuert.
  4. Die CPU erfordert Zugriff auf die Ergebnisse eines Befehls, der auf die Ausführung im Befehlspuffer wartet.

Von den oben genannten vier Situationen ist Zahl 4 die wichtigste für die Leistung. Wenn die Anwendung einen Aufruf zum Kopieren einer Ressource oder Unterressource ausgibt, wird dieser Aufruf im Befehlspuffer in die Warteschlange gestellt.

Wenn die Anwendung dann versucht, die Stagingressource zuzuordnen, die das Ziel des Kopieraufrufs war, bevor der Befehlspuffer geleert wurde, tritt ein Pipelinestand auf, da nicht nur der Copy-Methodenaufruf ausgeführt werden muss, sondern auch alle anderen gepufferten Befehle im Befehlspuffer ausgeführt werden müssen. Dies führt dazu, dass die GPU und die CPU synchronisiert werden, da die CPU darauf wartet, auf die Stagingressource zuzugreifen, während die GPU den Befehlspuffer leert und schließlich die Ressource ausfüllt, die die CPU benötigt. Sobald die GPU die Kopie abgeschlossen hat, beginnt die CPU mit dem Zugriff auf die Stagingressource, während dieser Zeit befindet sich die GPU jedoch im Leerlauf.

Dies wird zur Laufzeit häufig beeinträchtigt. Aus diesem Grund sollte die Zuordnung von Ressourcen, die mit der Standardverwendung erstellt wurden, sorgfältig durchgeführt werden. Die Anwendung muss lange genug warten, bis der Befehlspuffer geleert wird und somit alle diese Befehle ausgeführt werden, bevor versucht wird, die entsprechende Stagingressource zuzuordnen.

Wie lange sollte die Anwendung warten? Mindestens zwei Frames, da dadurch Parallelität zwischen den CPU(n) und der GPU maximal genutzt werden kann. Die Art und Weise, wie die GPU funktioniert, besteht darin, dass die Anwendung Frame N verarbeitet, indem Aufrufe an den Befehlspuffer übermittelt werden, die GPU die Aufrufe aus dem vorherigen Frame N-1 ausführt.

Wenn eine Anwendung also eine Ressource zuordnen möchte, die aus dem Videospeicher stammt und eine Ressource bei Frame N kopiert, beginnt dieser Aufruf tatsächlich mit der Ausführung bei Frame N+1, wenn die Anwendung Aufrufe für den nächsten Frame sendet. Die Kopie sollte abgeschlossen sein, wenn die Anwendung frame N+2 verarbeitet.

Frame GPU/CPU-Status
N
  • CPU-Probleme rendern Aufrufe für den aktuellen Frame.
N+1
  • GPU führt Aufrufe aus, die während des Frame-N von der CPU gesendet wurden.
  • CPU-Probleme rendern Aufrufe für den aktuellen Frame.
N+2
  • Die GPU hat die Ausführung von Anrufen beendet, die während des Frame-N von der CPU gesendet wurden. Ergebnisse sind bereit.
  • GPU führt Aufrufe aus, die während des Frames N+1 von der CPU gesendet werden.
  • CPU-Probleme rendern Aufrufe für den aktuellen Frame.
N+3
  • DIE GPU hat die Ausführung von Anrufen beendet, die während des Frames N+1 von der CPU gesendet wurden. Ergebnisse bereit.
  • GPU führt Aufrufe aus, die während des Frames N+2 von der CPU gesendet werden.
  • CPU-Probleme rendern Aufrufe für den aktuellen Frame.
N+4 ...

 

Ressourcen