[D3D 11] Wie viele Constant Buffers?

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.

[D3D 11] Wie viele Constant Buffers?

Beitragvon Krishty » 24.05.2017, 00:44

Man soll Constant Buffers nach Änderungshäufigkeit sortieren. Okay.

Ich habe hier eine Szene mit 100.000 Objekten und 10.000 verschiedenen Materialien (Ambient, Diffuse, …). Die Transformationsmatrizen ändern sich fast nie. Die Materialien ändern sich noch viel seltener. Wir können also erstmal übereinkommen, dass Transformationsmatrizen und Materialdaten in getrennte Constant Buffers gehen.

Soll ich jetzt 100.000 Constant Buffers mit Transformationsmatrizen anlegen? Oder nur einen, und den in jedem Frame 100.000 Mal überschreiben? Soll ich 10.000 Constant Buffers mit Materialdaten anlegen? Oder nur einen, den ich in jedem Frame 10.000 Mal überschreibe?

Dauerndes Überschreiben geht irgendwie dem Sinn von Buffern zuwider. (Es soll ja auf der GPU gepuffert bleiben, so lange es sich nicht ändert. Der große Unterschied zu D3D 9, wo man jeden Frame alle Konstanten neu zur GPU geschickt hat.) Andererseits erscheint mir das exzessive Erzeugen von Constant Buffers bedenklich. Dann wiederum finde ich aber keinen Hinweis in den Resource Limits, dass das irgendwie nach oben begrenzt wäre.

Ich habe jetzt testweise 10.000 Constant Buffers für die Materialien erzeugt, und das läuft richtig gut. (Zig Megabyte weniger Working Set pro Frame!) Mache ich alles richtig, oder wirft gerade jemand die Hände über dem Kopf zusammen?
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
 
Beiträge: 5690
Registriert: 26.02.2009, 12:18
Benutzertext: state is the enemy

Re: [D3D 11] Wie viele Constant Buffers?

Beitragvon kimmi » 24.05.2017, 10:58

In einem Talk eines Unreal-Engine-Engineers habe ich zu dem Thema mal die folgende Antwort bekommen: "Strongly depends on you current situation and environment."
Wenn du trotz der Switches zwischen den Constant-Buffern keinen signifikanten Performance-Bottlenecks findest, hat es für dein Szenario hin. Ansonsten könntest du die jeweiligen Buffer vermutlich noch etwas in Cluster unterteilen, um zusammen gehörende Gruppen besser andressieren zu können.
Aber wenn es läuft: warum nicht :).

Gruß Kimmi
Benutzeravatar
kimmi
Kim Kulling
Moderator
 
Beiträge: 1331
Registriert: 26.02.2009, 10:42
Wohnort: Luebeck

Re: [D3D 11] Wie viele Constant Buffers?

Beitragvon Krishty » 24.05.2017, 11:59

Hmmm; okay. Nvidia sagt (https://developer.nvidia.com/content/co ... ant-pain-0 ), dass man mit XXSetConstantBuffers() + DrawIndexed() doppelt so viel gerendert kriegt wie mit Map(DISCARD) + Unmap() + DrawIndexed() + cache miss (Kopieraufwand noch nicht einberechnet), und bisher deckt sich das mit meiner Leistung.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
 
Beiträge: 5690
Registriert: 26.02.2009, 12:18
Benutzertext: state is the enemy

Re: [D3D 11] Wie viele Constant Buffers?

Beitragvon Schrompf » 24.05.2017, 13:05

Ich hatte Constant Buffers so verstanden, dass es nur kleine kontinuierliche Blöcke GPU-Speicher sind, und in einem Descriptor Block (oder wie der hieß) liegt ein Zeiger darauf. Und da in Vulkan und DX12 ja jeder DrawCall nur noch ein Gesamt-Satz an solchen Zeigern ist, *müsste* es völlig ok sein, hundertausende winzige Constant Buffers rumliegen zu haben.

Der alte C++-Bastler in mir will einen Custom Allocator dafür schreiben, aber ich glaube, wir haben immer noch keinen Direktzugriff auf die Speicher und Zeiger der GPU.
Häuptling von Dreamworlds. Baut an was Neuem. Hilft nebenbei nur höchst selten an der Open Asset Import Library mit.
Benutzeravatar
Schrompf
Thomas Ziegenhagen
Moderator
 
Beiträge: 3537
Registriert: 26.02.2009, 00:44
Wohnort: Dresden
Benutzertext: Lernt nur selten dazu

Re: [D3D 11] Wie viele Constant Buffers?

Beitragvon kimmi » 24.05.2017, 15:11

Mit Vulkan sollte das gehen :). DX11? Ich weiß ja nicht ...
Benutzeravatar
kimmi
Kim Kulling
Moderator
 
Beiträge: 1331
Registriert: 26.02.2009, 10:42
Wohnort: Luebeck

Re: [D3D 11] Wie viele Constant Buffers?

Beitragvon David_pb » 24.05.2017, 22:28

Hi,

du musst bedenken was im Hintergrund passiert wenn du einem Puffer überschreibst: Der Speicher kann in diesem Fall ja nicht wirklich überschrieben werden, weil die GPU den Inhalt (i.A.) noch gar nicht verarbeiten konnte. Würde der Speicher überschrieben werden dann hätte man ein Szenario, wo unterschiedliche Objekte mit den selben Konstanten gerendert werden würden. Aus diesem Grund wird der Puffer "umbenannt", der Treiber alloziert also einen neuen Speicherbereich und packt diesen hinter den Handle des Puffers. Das Update geht dann also in den neuen Speicherbereich, so das vorher abgesetzte Drawcalls/Dispatches ihre eigene Version des CBuffers behalten. Im Endeffekt ist der Speicherfootprint also ähnlich, hat aber einen gewissen Managementoverhead auf Treiberseite. Dort wird nämlich häufig versucht den Prozess zu optimieren, z.B. indem der Treiber bereits im Vorfeld einen größeren Speicherblock reserviert und dann solang einen Offset verschiebt bis der Block aufgebraucht ist. Im Idealfall sind beim nächsten Discard die ersten Bereiche bereits von der GPU konsumiert, so das eine Anfrage beim Speichermgmnt effektiv verhindert wird (unwahrscheinlich bei deinem Szenario). Das Pattern kennt man z.B. auch bei Streamingbuffern, wenn beispielsweise Instanzdaten gesammelt, oder Partikeldaten von der CPU geschrieben werden. In diesem Fall würde man einen Puffer reservieren der WorstCaseGröße * MaximaleLatenz groß ist und jeweils mit NO_OVERWRITE mappen + offsetten bis ein Überlauf entsteht, ansonsten mit DISCARD um den Puffer zu resetten. Im Idealfall würde der Puffer also nie wirklich 'renamed' werden.

Ein weiteres potentielles Problem sind Cacheflushes/Pipelinesyncs die ggf notwendig sind, bevor die Daten von der GPU gelesen werden können.

Im Falle von sehr häufigen Updates kann der Overhead groß werden, so das du Puffer nicht sharen solltest (manche APIs bieten die Möglichkeit solche Konstanten direkt in den Commandbuffer zu schreiben, z.B. über Rootkonstanten in DX12). Für Puffer mit weniger hohen Update-Frequenz ist der Overhead häufig vertretbar. In vielen Fällen sind die Konstanten aber tatsächlich unveränderlich (z.B. häufig bei Materialparametern o.Ä.). In diesen Fällen kann es Sinn machen die Daten offline in einzelne Puffer zu backen und einfach zu binden. Das gibt den Treiber auch die Möglichkeit die Daten in GPU 'nahmen' Speicher (z.B. VRAM) zu lagern, weil kein CPU Zugriff notwendig ist.

Ein Allokationsschema für CBuffer mit DX11 ist schwierig, weil 'partial' Updates nicht möglich sind (DX11.1 bietet das an). Ein CBuffer-Pool ist allerdings eine Möglichkeit die ggf am nächsten an die Idee eines Sperichermanagement ran kommt. DX12/Vulkan sind da etwas flexibler, Zugriff auf Speicheradressen hat man zwar auch dort nicht, ist aber für einen Allokator auch nicht notwendig. Ich hatte in einem Spiel mal gesehen, das statt CBuffern sämtliche Konstanten über TBuffer an die GPU gefüttert wurden um eine art Speicherverwaltung zu ermöglichen. Ist sicher auch eine Möglichkeit. :-)
David_pb
 
Beiträge: 18
Registriert: 23.07.2014, 20:50

Re: [D3D 11] Wie viele Constant Buffers?

Beitragvon Krishty » 24.05.2017, 23:47

Danke!
(manche APIs bieten die Möglichkeit solche Konstanten direkt in den Commandbuffer zu schreiben, z.B. über Rootkonstanten in DX12)
Das kann ich klägen: Der oben verlinkte Nvidia-Artikel sagt, dass auch unter D3D 11 alle Constant Buffer Updates direkt in den Command Buffer kopiert werden, und der ist auf 128 MiB limitiert (danach Flush & Stall). Eine API-Garantie ist das aber natürlich nicht.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
 
Beiträge: 5690
Registriert: 26.02.2009, 12:18
Benutzertext: state is the enemy


Zurück zu Grafikprogrammierung

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 2 Gäste