[D3D9] Last auf Input Assembler reduzieren

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
Benutzeravatar
Schrompf
Moderator
Beiträge: 5161
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas
Wohnort: Dresden
Kontaktdaten:

[D3D9] Last auf Input Assembler reduzieren

Beitrag von Schrompf »

Guten Tag, verehrte Expertinnen und Experten.

Wie schon im Jammer-Thread angedeutet habe ich aktuell ein Problem mit vielen vielen kleinen Flächen, die ich effizient rendern möchte. NVidia NSight ist zwar nur ein unvollkommenes Werkzeug, aber der Grundaussage der Profiler-Läufe kann ich wohl trauen: die GPU verbringt drei Viertel der Zeit im Input Assembler. Was kann ich dagegen tun?

Ich dachte mir, das Verkleinern der Eingabestrukturen könnte helfen. Das habe ich wie folgt ausprobiert:

Code: Alles auswählen

struct VoxelVertex 
{ 
  float3 vpos; 
  ubyte4 vtex; 
};
struct InstanzVertex 
{
  float3 ipos; 
  ubyte4 inorm; 
  ubyte4 igr_und_tex; 
  ubyte4 ifarbe;
};

VertexAusgabe main( const VertexEingabe rein)
{
  // Ausgabestruktur
  VertexAusgabe raus;

  // Instanz in Kamerakoordinaten transformieren
  float4 pos = float4( rein.ipos * gVoxelGroesse, 1.0f);
  float3 norm = mul( (float3x3) gObjektMatrix, rein.inorm * (2.0f / 255.0f) - float3( 1.0f, 1.0f, 1.0f));
  float4 weltPos = mul( gObjektMatrix, pos);
  float4 kamPos = mul( gWeltMatrix, pos);

  // dort zu Quadrat entfalten
  float igr = rein.igr_und_tex.x * (1.0f / 255.0f) + rein.igr_und_tex.y;
  kamPos.xyz += rein.vpos * gVoxelGroesse * igr;
  // und ausgeben
  raus.mPosition = mul( gProjMatrix, kamPos);

  // Texturkoordinaten erstellen
  float texgr = 32.0f / 2048.0f;
  float2 texpos = (rein.igr_und_tex.zw * 40.0f + 4.0f) * (1.0f / 2048.0f);
  raus.mTexKoords = texpos + rein.vtex * texgr;
                        
  return raus;
}
Erklärung: Ein Voxel ist ein Billboard besteht aus zwei Dreiecken, die ich dann per Instancing in Rudeln zeichne. Das hier ist eine vereinfachte Form, bei der ich mal alle relevanten Sachen zusammenkopiert habe. Ich könnte die Vertex-Strukturen noch ein bisschen weiter eindampfen, aber ich bezweifle, ob das noch irgendwas bringt. Der Mesh-Vertex ist jetzt noch 16 Byte groß und der InstanzVertex noch 24 Byte - gegenüber vorher 28 Byte und 56Byte habe ich gerade mal 30% Performance gewonnen. Es liegt also anscheinend nicht am Speicherdurchsatz, sondern der Input Assembler ist irgendwie anderweitig überlastet. Hat jemand noch eine Idee, was ich hier tun könnte?

Eine Idee wäre noch, das Instancing sein zu lassen, und mit DX10 und einem GeometrieShader Point Sprites zu pinseln. Das würde evtl. den Input Assembler entlasten, weil der dann kein Instancing mehr zusammensuchen muss und der VertexShader nur noch pro Voxel einmal läuft. Dazu müsste ich aber auf DX10 wechseln, was ich bisher eigentlich nicht wollte.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: [D3D9] Last auf Input Assembler reduzieren

Beitrag von CodingCat »

Stimmt die Vertex Declaration bzgl. Reihenfolge und Offsets (auch Stream-übergreifend) exakt mit der Shader-Input-Signatur überein? Wenn ja, dann sieht es tatsächlich düster aus. Du könntest allenfalls noch Mini-Vertices probieren, in denen du VoxelVertex durch ein einziges Byte oder Uint mit ID zwischen 0 und 3 ersetzt. Wenn auch das nicht hilft, fällt mir höchstens noch Texture-Lookup statt Instancing-Stream ein, um die gesamte Multi-Stream-Assembly loszuwerden. Ob das dann aber tatsächlich schneller als der Input Assembler ist, kann ich nicht voraussagen.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
Schrompf
Moderator
Beiträge: 5161
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas
Wohnort: Dresden
Kontaktdaten:

Re: [D3D9] Last auf Input Assembler reduzieren

Beitrag von Schrompf »

Danke. Der Gedanke, den MeshVertex auf 4Byte zu reduzieren, kam mir auch schon während des Schreibens. Aber ich bezweifle, dass da noch viel rauszuholen ist - das Assembling aus zwei Streams scheint das Problem zu sein.

Ich habe gerade mal nachgeschaut: die detail-dichteste Szene hat etwa 1000 Buffer mit insgesamt 42MB Größe. Ich könnte also schlimmstenfalls das Instancing sein lassen und wieder vier Vertices pro Voxel schreiben. Die Instanz-Positionen sind ganze Zahlen, also könnte 3x16Bit Position reichen und die Ecke-ID pack ich in den vierten 16Bit-Wert. Damit wären wir dann bei 20Byte pro Vertex und damit 80Byte pro Voxel. Werde ich mal ausprobieren.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
Schrompf
Moderator
Beiträge: 5161
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas
Wohnort: Dresden
Kontaktdaten:

Re: [D3D9] Last auf Input Assembler reduzieren

Beitrag von Schrompf »

Und das ist das Ergebnis:

Instancing von 56Byte VertexStruktur auf 24Byte-VertexStruktur geschrumpft: 14 -> 18 fps
Instancing ausgebaut und stattdessen manuell 4 Vertizes pro Voxel geschrieben: 18fps -> 50 fps

Dafür bin ich jetzt bei 200MB VideoRAM anstatt vorher 42MB für die Buffer. Nuja... etwas Platz zum Optimieren ist noch, das war erstmal nur ein QuickHack zum Ausprobieren.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Jörg
Establishment
Beiträge: 296
Registriert: 03.12.2005, 13:06
Wohnort: Trondheim
Kontaktdaten:

Re: [D3D9] Last auf Input Assembler reduzieren

Beitrag von Jörg »

Kannst Du nicht alles aus der VertexID ableiten und ganz auf Voxelvertex verzichten?
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: [D3D9] Last auf Input Assembler reduzieren

Beitrag von CodingCat »

Das wäre mit Sicherheit der beste Weg, aber iirc erfordert das mindestens DX10. Lässt sich aber sehr leicht herausfinden, einfach mal SV_VertexID zum Input des VS hinzufügen. :|
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
Schrompf
Moderator
Beiträge: 5161
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas
Wohnort: Dresden
Kontaktdaten:

Re: [D3D9] Last auf Input Assembler reduzieren

Beitrag von Schrompf »

Braucht nach meinem Wissen mindestens DX10. Die ganzen SV_Defs heißen vorher ja noch POSITION0, TEXCOORD0 und so.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Antworten