[D3D10] Terrain-Patch mit einem Draw-Aufruf

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
Unknown GER
Beiträge: 49
Registriert: 09.01.2003, 13:04

[D3D10] Terrain-Patch mit einem Draw-Aufruf

Beitrag von Unknown GER »

Hallo! :)

ich frage mich gerade, wie man ein typisches Terrain-Patch - bestehend aus n * n Vertices - am geschicktesten organisieren würde, so dass es mit nur einem Draw-Aufruf gerendert werden kann. Eine Triangle List wäre wohl die nicht so tolle Brute-Force-Methode. Mit Triangle Strips wären es ohne Tricks jedoch n - 1 Draw-Aufrufe. Mit "Trick" meine ich das hier:

Bild

Indem man an die ursprünglichen Triangle Strips jeweils ein künstliches Dreieck mit Null Fläche hängt, bekommt man das ganze Patch mit nur einem DrawIndexed-Aufruf hin. Dafür wird der Index Buffer größer, was jedoch kein Problem sein sollte, wenn die Patches nicht zu groß werden.

Wie sieht es aber mit Instancing aus? Man hätte nur ein Triangle Strip, der eine Reihe des Patches ausmacht und den entsprechenden Index Buffer dazu. Zusätzlich allerdings noch einen Instance Buffer, in dem für jede Reihe ein Positionsoffset steht. Das ginge dann ja mit nur einem DrawIndexedInstanced-Aufruf, und es gäbe keine künstlichen Nullflächen-Dreiecke. Hat damit jemand schon Erfahrungen sammeln können, ob das auch wirklich Vorteile anstatt Nachteile bzgl. der Performanz gibt?

Oder macht man das ganz anders mit den Patches und ich komm nur nicht drauf? ;)
Benutzeravatar
Aramis
Moderator
Beiträge: 1458
Registriert: 25.02.2009, 19:50
Echter Name: Alexander Gessler
Wohnort: 2016
Kontaktdaten:

Re: [D3D10] Terrain-Patch mit einem Draw-Aufruf

Beitrag von Aramis »

Ich würde ganz einfach eine Triangle-List rendern, diese aber auf Cache-Lokalität optimieren. Das Ergebnis ist genauso schnell wie ein gleich langer Triangle-Strip, und vermutlich schneller wie ein Triangle-Strip mit Dummy-Dreiecken.

Ich hab meine Patches in 2x2-Gruppen indiziert (8 Dreiecke und 9 einzigartige Indices), was eine allgemein ganz gute Faustregel für die Größe des Post Transform Vertex Caches ist und die Zahl der Cache-Misses recht klein hält (auch wenn ich mir nie die Mühe gemacht habe es sonderlich detailliert nachzumessen …).
Benutzeravatar
Krishty
Establishment
Beiträge: 8261
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [D3D10] Terrain-Patch mit einem Draw-Aufruf

Beitrag von Krishty »

Ist keine Antwort auf die Frage an sich, aber ein nützlicher Tipp: Die Vertices sind bei Patches ausgesprochen regelmäßig und werden üblicherweise auch regelmäßig in einen Puffer geschrieben. Das bedeutet, dass man – da ja in Shadern Integerarithmetik zur Verfügung steht – aus einem Index zurückrechnen kann, welche Vertex(-XZ-)position damit gemeint ist.

Das bedeutet weiterhin, dass X- und Z-Position aus dem Vertex-Buffer fallen, da sie im Shader rekonstruiert werden können. Weiter: liegt die Terrainhöhe in einer Textur vor, kann man die Y-Koordinate im Vertex-Shader aus der Textur laden. Da Texturen – im Gegensatz zu Vertex-Buffern – Zugriff auf mehr als ein Element bieten, kann man auch die Höhen der umgebenden Texel laden und daraus die Normale rekonstruieren.

Am Ende der Kette steht: Man braucht ab D3D10 für sowas keinen Vertex-Buffer mehr und spart drei Viertel der Bandbreite. Benutzt man für die Patches den Geometry-Shader, braucht man auch keinen Index-Buffer mehr und erzeugt alles prozedural aus der Textur. Kostet dafür Renderleistung (man verzichtet auf die Vertex-Caches), aber wahrscheinlich wird das langfristig durch geringeren CPU-Bedarf wettgemacht.

Gruß, Ky
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Schrompf
Moderator
Beiträge: 4867
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: [D3D10] Terrain-Patch mit einem Draw-Aufruf

Beitrag von Schrompf »

Der Post Vertex Cache von GPUs ist so im Bereich 16 bis 32 Vertices, wenn ich mich recht erinnere. Ein 3x3-Patch müsste also auch noch gut funktionieren.

Triangle Strips und degenerierte Flächen für die Übergange sind jedenfalls sooooooo 1999. Und zwar wortwörtlich, denn seit der ATI Radeon 8000-Serie sind indizierte Primitives der effektivste Weg. Und die Grafikkarten-Generation ist ja nun schon ne Weile her.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Unknown GER
Beiträge: 49
Registriert: 09.01.2003, 13:04

Re: [D3D10] Terrain-Patch mit einem Draw-Aufruf

Beitrag von Unknown GER »

Danke für die informativen Antworten. :) Gibt es genauere Spezifikationen bzgl. der Cachegrößen für bestimmte Grafikkarten? Wie würde man ein Patch der Größe 64x64 Cache-optimiert organisieren? Wäre da überhaupt was zu machen? An der Patchgröße kann ich bedingt durch das Verfahren, das ich gerade implementiere, nichts ändern. Gibt es auch Richtwerte für optimale Größen von Vertex und Index Buffern bzw. lohnt es sich noch andere Vertices und Indices mit in die Patch Buffer zu hängen, so dass ich nicht die Buffer in einem Renderdurchgang wechseln muss, sondern lediglich Offset-Angaben bei den Draw-Aufrufen mache?

Das mit dem Ansatz komplett ohne Vertex Buffer hab ich vor ein paar Tagen schonmal gelesen und werd das wohl auch mal ausprobieren, ob und wieviel das bringt.
Benutzeravatar
Schrompf
Moderator
Beiträge: 4867
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: [D3D10] Terrain-Patch mit einem Draw-Aufruf

Beitrag von Schrompf »

Jetzt render doch einfach erstmal. Egal, was Du an Indizes optimieren kannst, es wird bestenfalls eine Wirkung im niedrigen einstelligen Prozentbereich haben. Wahrscheinlich aber eher 0% Gewinn, weil in den meisten Fällen nunmal das Fragment Processing der entscheidende Faktor ist. Faktor 10 bis 100 aufwändiger als das Vertex Processing. Hau jeweils einen 64x64-Patch in einen VertexBuffer, benutze einen Index-Buffer für alle, und render die. Der nächste Schritt sollte die Detailreduktion sein.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Unknown GER
Beiträge: 49
Registriert: 09.01.2003, 13:04

Re: [D3D10] Terrain-Patch mit einem Draw-Aufruf

Beitrag von Unknown GER »

Wird ein Vertex Shader eigentlich einmal pro Vertex im Vertex Buffer ausgeführt unabhängig wie oft er indiziert wird, oder einmal für jeden Index auf ihn im Index Buffer?
Benutzeravatar
Aramis
Moderator
Beiträge: 1458
Registriert: 25.02.2009, 19:50
Echter Name: Alexander Gessler
Wohnort: 2016
Kontaktdaten:

Re: [D3D10] Terrain-Patch mit einem Draw-Aufruf

Beitrag von Aramis »

Theoretisch einmal pro Eintrag im Indexbuffer. Praktisch kommt genau *hier* der besagte PostTransform-Cache in's Spiel. Er cached die vortransformierten Vertices für die letzten n Indices, wobei sich n aus der Göße des Caches und der Größe eines einzelnen Vertex ergibt.
Unknown GER
Beiträge: 49
Registriert: 09.01.2003, 13:04

Re: [D3D10] Terrain-Patch mit einem Draw-Aufruf

Beitrag von Unknown GER »

Nochmals danke für die ganzen Infos, vor allem bzgl. dem Cache für Vertices aus dem Vertex Shader. :)

Ich mache das ganze nun ohne Vertex Buffer (nur mit einem Index Buffer). Die Positionen der Vertices berechne ich aus dem Index, an den ich über SV_VertexID im Vertex Shader komme. Gezeichnet wird mit einem einzigen DrawIndexed()-Aufruf als Triangle Strip(s). Das geht mit Hilfe von Cut Indices (0xFFFF) komplett ohne Nullflächen-Dreiecke. Mit welcher Länge der Triangle Strips ich bzgl. des Caches am besten fahren werde, lote ich dann aus, wenn genug auf dem Bildschirm zu sehen sein wird, so dass ich das unmittelbar an den FPS bzw. T/s erkennen können sollte.
Antworten