Wie verwende ich UpdateSubresource und Map / Unmap?

8

Nach meinem Verständnis (beim Lesen verschiedener Seiten) gibt es zwei Möglichkeiten, einen Puffer zu aktualisieren:

  1. UpdateSubresource()(wenn Puffer mit DEFAULTVerwendung erstellt wird)
  2. Map()Kopieren Sie die neuen Daten Unmap()(wenn der Puffer mit der DYNAMICVerwendung erstellt wird).

Rufe ich im ersten Fall nur diese eine Funktion auf (nichts weiter)? Weil ich gesehen habe, wie Leute sagten, sie ordnen den Puffer zu und aktualisieren dann die Unterressource, oder vielleicht habe ich sie falsch verstanden.

Gibt es auch einen anderen Weg (bezweifle es: P)? Verstehe ich die Dinge richtig?

NPS
quelle

Antworten:

11

Dazu gibt es eine gute Präsentation: Wirf nicht alles weg: Effizientes Puffermanagement von John McDonald bei NVIDIA. Es umfasst verschiedene Themen, aber auf dem Thema Ihrer Frage, die allgemeine Beratung ist Puffer mit dynamischer Nutzung und Verwendung erstellen Map()mit D3D11_MAP_WRITE_DISCARD, wenn die Daten häufig aktualisiert werden muss (wie jeder Rahmen oder mehrmals pro Frame). Dies würde für konstante Puffer, Scheitelpunktpuffer für Partikelsysteme und dergleichen verwendet.

Gemäß der Präsentation UpdateSubresource()verursacht die Standardnutzung / mehr CPU-Overhead als die dynamische Nutzung / Map(). Er empfiehlt jedoch die Standardverwendung / UpdateSubresource()für Daten, die nur gelegentlich aktualisiert werden müssen, z. B. Daten, die in einem Open-World-Spiel von der Festplatte gestreamt werden.

Und ja, in dem Fall, in dem Sie es verwenden UpdateSubresource(), würden Sie es selbst verwenden, nicht in Kombination mit Map().

Nathan Reed
quelle
2
Unheimlich, Sie haben beide in derselben Minute geantwortet und denselben Link gepostet.
NPS
In einem anderen Thread haben Sie geschrieben: "Sie müssen den Puffer nicht binden, um ihn mit UpdateSubresource zu aktualisieren. Tatsächlich sollte er beim Aktualisieren nicht gebunden werden." Bedeutet dies, dass ich immer alle Puffer aufheben sollte, bevor ich sie aktualisiere? Wenn ja, wie binde ich einen Puffer auf?
NPS
1
@NPS Zunächst einmal ist es implizit ungebunden, wenn Sie bereits etwas anderes an seine Stelle gebunden haben. Andernfalls können Sie NULL explizit binden, um die Bindung eines Puffers aufzuheben. Zum Beispiel können Sie ID3D11ShaderResourceView * nullsrv = NULL; pCtx->PSSetShaderResources(0, 1, &nullsrv);eine Textur von Steckplatz 0 lösen.
Nathan Reed
Ich wusste von dem impliziten, brauchte aber das explizite, danke. Aber Sie haben meine erste Frage nicht beantwortet - muss ich dies immer für alle Puffer tun, die ich aktualisieren wollte?
NPS
1
@NPS Idealerweise sollte der Puffer zum Zeitpunkt der Aktualisierung auf der CPU nicht von der GPU verwendet werden. Die GPU und die CPU werden jedoch asynchron ausgeführt, sodass dies nicht einfach sicherzustellen ist. Ich würde sagen, mach dir keine Sorgen, es sei denn, du findest, dass es sich um ein tatsächliches Leistungsproblem handelt.
Nathan Reed
2

Sie haben sich möglicherweise auf den tatsächlichen Vorgang des Aktualisierens einer Ressource und nicht auf den tatsächlichen Funktionsaufruf bezogen. Im Allgemeinen sollte UpdateSubResource für Standardressourcen verwendet werden, die nicht häufig aktualisiert werden (dh nicht für jeden Frame. In diesem Fall ist es wahrscheinlicher, dass der Puffer in einen temporären Puffer kopiert wird, auf den über den Befehlspuffer zugegriffen werden kann ( auf Grund der Rasse Bedingungen zum Beispiel). Es wird Ihnen auch die Update erlaubt Sub - Ressourcen (in Texturen, zum Beispiel).

Map / Unmap sollte verwendet werden, wenn eine Ressource sehr häufig aktualisiert werden soll (dh jeder Frame), z. B. einige konstante Puffer. Der häufigste Fall ist, wenn Sie den gesamten Puffer mit WriteDiscard überschreiben. Es gibt eine nVidia-Präsentation, in der sie diese Praxis empfehlen.

Der Wanderer
quelle