Interleaved - Alle Scheitelpunktdaten (Position, Normal, Texkoord ...) werden in 1 Scheitelpunktpuffer getrennt gespeichert. Jedes Scheitelpunktattribut wird in einem separaten Scheitelpunktpuffer gespeichert (1 für Positionen, 1 für Normalen ...).
Ich weiß, dass diese Frage oft gestellt wurde und ich weiß auch, dass es (leider) keine richtige Antwort gibt. Aber ich möchte versuchen, die wichtigsten Vor- und Nachteile von beiden aufzulisten. Oder vielleicht haben Sie einige allgemeine Faustregeln, wann Sie sie verwenden sollen.
Vorteile von Interleaved:
- schneller? (Alle Daten für 1 Scheitelpunkt werden auf einmal abgerufen? etw über den Cache, der besser funktioniert)?
- weniger API-Aufrufe (zum Erstellen und Festlegen von Puffern, aber das ist wahrscheinlich ein sehr kleiner Unterschied)
Vorteile der getrennten:
- Wenn verschiedene Shader unterschiedliche Scheitelpunktattribute benötigen (z. B. ein Shader benötigt nur Position und ein anderer Position, Normal und Texcoord), kann jedem Shader nur die Daten bereitgestellt werden, die er benötigt, und es gibt keine Datenverdoppelung
- Wenn nur die Position von Scheitelpunkten aktualisiert wird, müssen die anderen Attributdaten (z. B. Normalen und Texkoordinaten) nicht erneut gesendet werden.
Wenn Sie weitere Unterschiede feststellen, schreiben Sie bitte. Von oben sieht es im Allgemeinen wie ein Kampf zwischen Speicher und Leistungsoptimierung aus. Aber vielleicht irre ich mich? Vielleicht ist man in den meisten Fällen besser / schlechter?
Bearbeiten: Noch ein Problem - mit verschachtelten Puffern könnte ich unnötige Daten an die GPU senden, und die Datenbandbreite ist ein großer Engpass bei den heutigen Karten. Sollte ich mir darüber Sorgen machen?
Antworten:
Ich habe kürzlich beide Versionen in OpenGL (4.3) implementiert und unter Verwendung der (Crytek) Sponza-Szene als Test-Rendering-Szene Shader verwendet, die entweder nur eine Teilmenge oder die vollständige Menge aller definierten Scheitelpunktattribute verwendeten.
Es gab einen Unterschied zu Ihrem Setup: Im nicht verschachtelten Fall befanden sich die Attribute auch im selben Scheitelpunktpuffer. Mit OpenGL ist dies ganz einfach. Sie können Byte-Offsets einfach mit glVertexAttribPointer (...) mit dem letzten Parameter an ein bestimmtes Attribut binden. Eine entsprechende Option gibt es wahrscheinlich für DirectX.
Insbesondere beim Rendern einer Schattenkarte, für die nur Scheitelpunktpositionen erforderlich sind (in meinem Fall), wurden bei Verwendung nicht verschachtelter Puffer ~ 210 bis ~ 220 FPS verwendet, was einem Unterschied von etwa 0,2 ms entspricht. Mit anderen Worten, Sie könnten mit dieser Beschleunigung nicht einmal von 60 FPS auf 61 FPS wechseln.
Beim Rendern der Szene aus der Perspektive des Schattenlichts, jedoch unter Verwendung aller Attribute (in meinem Fall eines verzögerten Durchlaufs der Schattengeometrie) hat sich die Leistung zwischen den beiden Versionen überhaupt nicht geändert.
Ich kann nur raten, aber ich denke, der Grund, warum sich das Rendern der Schattenkarte verbessert hat, ist, dass GPUs (wie CPUs) wahrscheinlich nicht nur einzelne Bytes, Wörter oder Wörter mit einem Speicherzugriff aus dem Speicher ziehen, sondern stattdessen mehr Bytes (auf den meisten modernen CPUs) Dies wären 64 Bytes pro Zugriff) und würde es irgendwo zwischenspeichern. Wenn Daten verschachtelt sind, zieht die GPU möglicherweise einen Satz Position / Normal / Texcoord / was auch immer pro Speicherzugriff auf einmal, von denen alle außer der Position Speicherbandbreite verschwenden, wenn Sie nur Position verwenden.
Eine Einschränkung: In meinem Testfall war die Speicherbandbreite nicht gebunden. Wenn also der Speicherdurchsatz Ihr Engpass ist, werden die Messungen möglicherweise anders ausgeführt.
Insgesamt würde ich vorschlagen, dass Sie es so belassen, wie Sie es jetzt haben, und es später ändern, sobald Sie feststellen, dass eine Optimierung erforderlich ist. Das Ändern dauert nicht lange. Sie müssen lediglich ändern, wie die Daten an den GPU-Speicher übergeben werden, und ändern, wie Attribute mithilfe Ihrer Grafik-API gebunden werden.
quelle
verschachtelt : Wenn es einfacher ist, Speicher und Code zu verstehen und zu verwalten. Anstatt 4 Puffer zu haben, haben Sie nur einen und das wars.
trennen : Es gibt keinen praktischen Vorteil beim Teilen von Ressourcen. Das Verwalten von 3D-Inhalten ist schwierig, und wenn die separaten Streams gemeinsam genutzt werden, entsteht nur ein Albtraum. Sie könnten dadurch etwas Gedächtnis gewinnen, aber es lohnt sich nicht.
Bei der Leistung kann es einen Unterschied geben, zumindest bei einigen Android-GPUs weiß ich, dass Sie unterschiedliche Ergebnisse erzielen werden.
quelle
[position, normal]
und der andere mit[position, normal, texcoord]
) und jeder für seinen jeweiligen Shader oder nur 1 Vertex-Puffer (letzterer) und für beide Shader?