Rendergeschwindigkeit optimieren

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Benutzeravatar
Zudomon
Establishment
Beiträge: 2253
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: Rendergeschwindigkeit optimieren

Beitrag von Zudomon »

Ich habe auf dem Laptop mit der "Intel HD Graphics 3000" beim testen auf Low festgestellt, dass die Baumstämme der kleinen Bäume etwa 1/6 der Rechenzeit brauchen, wie die Pilze. Und ich finde den Grund dafür nicht.

Hier die beiden Diagramme:
20170122_1.jpg
20170122_2.jpg
Bei beiden ist die Dreieckszahl etwa gleich... selbst wenn ich nur 512 Dreiecke von beiden zeichnen lasse, habe ich diese Zeitdifferenz, allerdings proportional. Das Inputlayout ist das gleiche, die Shader ebenso. Wenn ich mich nicht vertue, dann ist der einzige Unterschied wirklich die Form. Wenn ich kurz vorm Rendern das Mushroom Modell durch den Baumstamm tausche, habe ich keine Geschwindigkeitsdifferenz. Man sieht auch im Diagramm die davor und dahinterliegenden Calls sind alle gleich schnell.
Das einzige, was mir nun noch einfällt, dass vielleicht die Vertexanordnung bei dem Baumstamm besser ist und der dort besser auf den VertexCache zugreifen kann. Aber ist der Geschwindigkeitsvorteil so groß?! Oder übersehe ich noch etwas? Der Overdraw kann es auch schlecht sein, da die Objekte ja in verschiedenen größen auf dem Bildschirm landen, trotzdem alle die gleiche Renderzeit brauchen. Außerdem deckt der Pilz prinzipiell eine kleine Fläche ab.
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: Rendergeschwindigkeit optimieren

Beitrag von dot »

Beide Modelle scheinen mir aufgrund winziger Dreiecke auf die Entfernung extrem ineffizient zu rendern (aufgrund der Art und Weise wie die GPU rendert – Stichwort Quad Shading – sind Dreiecke kleiner als 2×2 Pixel extrem suboptimal). Auf wie viele Pixel pro Dreieck kommst du denn beim Baum vs beim Pilz? Die Lösung heißt vermutlich LoD, würde vermutlich auch dem Aliasing gut tun, das man da so sieht...

Btw: Verwendest du wirklich für jeden einzelnen Pilz einen separaten Drawcall?
Benutzeravatar
Zudomon
Establishment
Beiträge: 2253
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: Rendergeschwindigkeit optimieren

Beitrag von Zudomon »

dot hat geschrieben:Btw: Verwendest du wirklich für jeden einzelnen Pilz einen separaten Drawcall?
Ja, momentan werden alle Weltobjekte per seperatem Call gerendert... das wird aber nicht so bleiben.

Was die 2x2 Quads angeht, dachte ich auch schon dran. Allerdings sollten ja die langen dünnen Dreiecke des Baumstamms da schlechter abschneiden. Auch glaube ich nicht, dass das da eine Rolle stellt, weil jeder Drawcall der Objekte ja gleich lange braucht, egal wie groß das Objekt am Ende auf dem Bildschirm ist.
Ich habe nun mal die Model Matrix für die Baumstämme und Pilze auf Identiy gesetzt, die werden also nicht gecullt, landen aber auch nicht mehr auf dem Bildschirm. Drawcall Rendergeschwindigkeit ist dabei gleich geblieben. Ich denke, damit kann man diverse Füllratendinge ausschließen.
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Rendergeschwindigkeit optimieren

Beitrag von Krishty »

Interessant!

Hast du die Messung bestätigt, indem du die Pilze abschaltest, und dann tatsächlich so viel mehr fps hast, wie deine Messungen vermuten lassen? Das gleiche für Baumstämme?
Hast du mal die Vertex & Index Buffers der beiden vertauscht?
Die Reihenfolge vertauscht, so dass erst die Pilze gezeichnet werden, dann die Bäume?
Die Pilze auf 1×10×1 m hochskaliert (damit die Form ähnlich der Bäume ist)?
Setzt du auch die States vor jedem Pilz, und dabei vielleicht andere als für die Bäume?
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Zudomon
Establishment
Beiträge: 2253
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: Rendergeschwindigkeit optimieren

Beitrag von Zudomon »

So viele Fragen :D
Krishty hat geschrieben:Hast du die Messung bestätigt, indem du die Pilze abschaltest, und dann tatsächlich so viel mehr fps hast, wie deine Messungen vermuten lassen? Das gleiche für Baumstämme?
Muss ich noch testen... im Moment ist der Laptop in beschlag. ;)
Krishty hat geschrieben:Hast du mal die Vertex & Index Buffers der beiden vertauscht?
Die Reihenfolge vertauscht, so dass erst die Pilze gezeichnet werden, dann die Bäume?
Die Pilze auf 1×10×1 m hochskaliert (damit die Form ähnlich der Bäume ist)?
Was ich jetzt mal probiert haben, wenn Baumstamm gerendert werden soll, Pilz zu rendern, und umgekehrt. Die Model Matrix bleibt. Dadurch wird auch die Reihenfolge geändert. Das Ergebnis:
20170122_3.jpg
20170122_4.jpg
Die Rendergeschwindigkeit ist fast genauso, wie vorher. Ich schiebe die etwas längere Zeichendauer mal direkt auf die Pilzgröße wegen der Pixelfüllrate.
Krishty hat geschrieben:Setzt du auch die States vor jedem Pilz, und dabei vielleicht andere als für die Bäume?
Es werden redundatente States gefiltert, bevor sie nach DX geschickt werden. Also zwischen den Drawcalls werden faktisch nur die Shaderkonstanten gesetzt, die auf den Bildern zu sehen sind, CF_... CM... usw.
Da nach Texturen/Shader sortiert ist, werden ansonsten keine States geändert.
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Rendergeschwindigkeit optimieren

Beitrag von Krishty »

Spannend; es scheint also echt am Pilzmodell zu liegen …

Kannst du das Modell mal exportieren und verifizieren, dass alle Indizes gültig sind? Bei mir auf Nvidia bricht die Frame-Rate bei einigen Sonderfällen ein, z.B. bei Draw Calls mit 0 Dreiecken oder bei beschädigten Indizes [ohne Meldungen der Debug Runtime, wohlgemerkt] …
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Zudomon
Establishment
Beiträge: 2253
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: Rendergeschwindigkeit optimieren

Beitrag von Zudomon »

Krishty hat geschrieben:Draw Calls mit 0 Dreiecken
Du meinst damit, wenn der Flächeninhalt 0 ist, oder?

Also da muss ich nachher mal genaue Checks einbauen.
Aber da eine Linie rund extruded wird für die Pilzform, und diese an den Enden Dreiecke, statt Vierecke erzeugt, kann ich schon mal vorweg nehmen, dass demnach sowohl 0 Dreiecke und doppelte Indizies vorhanden sein könnten.
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Rendergeschwindigkeit optimieren

Beitrag von Krishty »

Nein, ich meine Draw Calls mit Null Dreiecken. Leere Draw Calls. Die lösen hier um die 10 ms Lag aus. Man testet halt selten, was passiert, wenn ein User eine leere Datei importiert ;)

Geht eben darum, dass Treiber langsame Sonderfälle haben; ich will ausschließen, dass wir es hier mit sowas zu tun haben. Die unterscheiden sich unter den Herstellern und Treiberversionen, darum muss man da ein Bisschen im Dunkeln stochern. Vertex- und Index Buffers verifizieren ist aber immer ein guter Anfang.

Sind die Shader für Pilze und Baumstämme unterschiedlich? Vielleicht limitiert dieses Mal tatsächlich die Rechenleistung …
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Zudomon
Establishment
Beiträge: 2253
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: Rendergeschwindigkeit optimieren

Beitrag von Zudomon »

Krishty hat geschrieben:Sind die Shader für Pilze und Baumstämme unterschiedlich?
Gleiche Shader. Sind wirklich nur die VB und IB Daten anders. Leere Drawcalls hab ich nicht. Zumal ja auch etliche Baumstamm und Pilzmodelle gerendert werden und alle jedesmal die gleiche Zeit brauchen.
Ich weiß nicht, ob ich heute noch zu den Checks komme. Also die Checks Dreiecke mit mit 0 Ausdehnung zu filtern und Indexlisten entsprechend zu bereinigen. Momentan sehe ich da momentan am ehesten die Chance, also dass es daran liegt.
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Rendergeschwindigkeit optimieren

Beitrag von Krishty »

Dreiecke mit Nullausdehnung sollten keine Probleme machen (außer, dass sie ein Bisschen Leistung verschwenden, aber nicht in dem Maße).

Gleiches für Dreiecke mit zwei identischen Indizes, denn die setzt man ständig ein um Triangle Strips zu schneiden. (Obwohl es da seit D3D 10 bessere Wege gibt.)

Aber ungültige Indizes oder NaN/INF in Vertices könnten schon Probleme verursachen. Gerade auf Intel-Karten würde ich mal Denormalized/NAN/INF prüfen.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Zudomon
Establishment
Beiträge: 2253
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: Rendergeschwindigkeit optimieren

Beitrag von Zudomon »

Krishty hat geschrieben:Aber ungültige Indizes oder NaN/INF in Vertices könnten schon Probleme verursachen. Gerade auf Intel-Karten würde ich mal Denormalized/NAN/INF prüfen.
Ich weiß gar nicht, wie man das vernünftig überprüfen kann :(
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Rendergeschwindigkeit optimieren

Beitrag von Krishty »

Zudomon hat geschrieben:
Krishty hat geschrieben:Aber ungültige Indizes oder NaN/INF in Vertices könnten schon Probleme verursachen. Gerade auf Intel-Karten würde ich mal Denormalized/NAN/INF prüfen.
Ich weiß gar nicht, wie man das vernünftig überprüfen kann :(
  bool isFine(float x) {
    auto absX = abs(x);
    return 1.17549e-38f < absX && absX <= 3.4028234e38f;
  }


Alle NaN-Vergleiche ergeben false, also ergibt der Ausdruck ebenfalls false, falls eine NaN reinrutscht. Delphi müsste sich ebenfalls an IEEE 754 halten, und ihr abs() müsste für NaNs ebenfalls NaN zurückgeben, also brauchst du es nur übersetzen.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Zudomon
Establishment
Beiträge: 2253
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: Rendergeschwindigkeit optimieren

Beitrag von Zudomon »

Hab nun erstmal die Dreiecke mit 0 Ausdehnung gefiltert. Ein paar Dreiecke konnten dadurch eingespart werden, was sich proportional auf die Geschwindigkeit ausgewirkt hat. Allerdings bleibt es bei den Pilzen immer noch entsprechend langsamer.

Als nächstes erstmal deine Funktion übersetzt und über den VB drüber gejagt. Hab das dann noch etwas umgeschrieben. Delphi bietet eine Funktion um auf nan zu testen. Außerdem hab ich eingebaut, dass kleine Werte auf 0 gesnappt werden:

Code: Alles auswählen

function MakeCorrect(_x: Single): Single;
begin
  Result:=_x;
  if IsNaN(Result) then Result:=0;
  if (Result>-0.00001) and (Result<0.00001) then Result:=0;
end;
Letztendlich hat das aber auch nichts gebracht.

Nun bleibt mir vorerst nur noch die Indizeprüfung. Das mach ich aber erst morgen...

EDIT:
Krishty hat geschrieben:Aber ungültige Indizes
Damit meinst du doch, dass die Indizes nicht den VB überschreiten oder < 0 sind. Wenn ja, das kommt auch nicht vor.

EDIT2:
Was mir jetzt noch einfällt, ich schau mir morgen noch den VS an... vielleicht erzeugen ja die übergebenen Vertex-Werte dort ein NaN. Es scheint ja definitiv mit der Dreiecksanzahl zu skalieren.
Benutzeravatar
Zudomon
Establishment
Beiträge: 2253
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: Rendergeschwindigkeit optimieren

Beitrag von Zudomon »

So, nun hab ich es nochmal mit einem simplen Vertex- und PixelShader probiert... und siehe da :D ... immer noch ist das Pilz Modell um etwa das 5 fache langsamer! :(
Also jedes Objekt hat seinen eigenen VB und IB. Und da sollten die IB's als Word drin stehen, solange es von der Dreiecksanzahl möglich ist.
Ich meine, gut, wenn ich das Problem nicht finden kann, dann ist es nun mal so... hab eh gesehen, dass das LOD Objekt für die Pilze auch ohne Subdivide auskäme und schon wären die Dreiecke statt momentan noch 1700 auf 70 runter... damit wäre das Problem indirekt dann eh gelöst. Aber es reizt mich schon ein wenig die Neugierde, was da wirklich anders läuft. Vielleicht muss ich mich mal ein bisschen mit Try&Error da durch wurschteln. Im Extremfall könnte man ja wirklich mal Mushroom und Baumstamm generieren und dann tatsächlich einfach die anderen Positionen übernehmen. An irgendwas muss das ja liegen.
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Rendergeschwindigkeit optimieren

Beitrag von Krishty »

Gemäß deines Beitrags gestern um 18:55 kann es jedenfalls kein Zufall sein. Mich interessiert durchaus, was da schiefgeht – aber konkrete Vorschläge zum Debugging habe ich auch nicht mehr …
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Zudomon
Establishment
Beiträge: 2253
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: Rendergeschwindigkeit optimieren

Beitrag von Zudomon »

Krishty hat geschrieben:Gemäß deines Beitrags gestern um 18:55 kann es jedenfalls kein Zufall sein.
Meinst du deinen Beitrag? :D

Hab mir nun nochmal anzeigen lassen, ob wirklich beide Modelle das selbe Indexformat benutzen. - Ja, 16 Bit.
Und mir nochmal die Doku zu DrawIndexedPrimitive durchgelesen, ob ich da vielleicht die Werte falsch benutze. Ist aber auch nicht der Fall.

Es könnte sein, dass es vielleicht am VertexCache liegt. Ich bin mir nicht sicher, ob beide Objekte von DX daraufhin optimiert werden. Ich benutze da ja die D3DXOptimizeFaces und D3DXOptimizeVertices.
Wenn es das nicht ist, dann weiß ich auch nicht mehr :D

EDIT: Beide Modelle werden optimiert.
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Rendergeschwindigkeit optimieren

Beitrag von Krishty »

Krishty hat geschrieben:Gemäß deines Beitrags gestern um 18:55 kann es jedenfalls kein Zufall sein.
Meinst du deinen Beitrag? :D
Nein, den mit den vertauschten Meshes, bei dem die Pilze trotzdem deutlich langsamer sind: https://zfx.info/viewtopic.php?f=5&t=40 ... =30#p53934
Hab mir nun nochmal anzeigen lassen, ob wirklich beide Modelle das selbe Indexformat benutzen. - Ja, 16 Bit.
Und mir nochmal die Doku zu DrawIndexedPrimitive durchgelesen, ob ich da vielleicht die Werte falsch benutze. Ist aber auch nicht der Fall.

Es könnte sein, dass es vielleicht am VertexCache liegt. Ich bin mir nicht sicher, ob beide Objekte von DX daraufhin optimiert werden. Ich benutze da ja die D3DXOptimizeFaces und D3DXOptimizeVertices.
Wenn es das nicht ist, dann weiß ich auch nicht mehr :D
Der Vertex Cache sollte höchstens 10 % bringen – in deinem Fall viel weniger, weil die Dreiecke so winzig sind.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Antworten