Updateperformance bei komplexen 3D Animationen
-
versuch triangles statt quads, graphickarten koennen eigentlich keine quads. es wird jedesmal zu dreiecken konvertiert.
wenn du glclear testen willst, mach das clear sofort nach dem swapbuffers und falls du einen stencilbuffer angibst, dann clear den auch.
char color, sowas gibt es hardwaremaessig nicht. und deine struct sollte 16byte alligned sein.
um sagen zu koennen weshalb dein vbo so lange bem update braucht, muesste man sehen was du machst, da laeuft eindeutig etwas schief.wobei ich mir bei einer 9250 auch nicht so sicher bin was die kann, war das nicht nur eine onboard karte?
-
rapso schrieb:
versuch triangles statt quads, graphickarten koennen eigentlich keine quads. es wird jedesmal zu dreiecken konvertiert.
Quads haben einen entscheidenen Vorteil: sie können sich krümmen, was bei korrekten Vertex-Normalen saubere Übergänge schafft.
Ausserdem halbiert es die Anzahl der Objekte, die Indices werden um 1/3 reduziert.
Habe trotzdem mal Triangles probiert.
"glDrawElements mit VBOs, ohne glClear" ging mit Triangles statt Quads von 73 auf 74 fps hoch
rapso schrieb:
wenn du glclear testen willst, mach das clear sofort nach dem swapbuffers und falls du einen stencilbuffer angibst, dann clear den auch.
Stencil nutze ich für den Test noch nicht.
Das glClear hatte ich ja schon rausgenommen, aber danke für den Tip!rapso schrieb:
char color, sowas gibt es hardwaremaessig nicht. und deine struct sollte 16byte alligned sein.
Der Witz ist, dass es bis 40000 Indizes keine Probleme gibt.
Dachte auch, das wäre genau der Sinn von Interleaved Arrays...
Somit sollte es der GPU doch egal sein, oder?rapso schrieb:
um sagen zu koennen weshalb dein vbo so lange bem update braucht, muesste man sehen was du machst, da laeuft eindeutig etwas schief.
Ist eigentlich nix aussergewöhnliches, hier mal eine kurze Zusammenfassung:
struct { float nv[3]; float p[3]; } vertice; // ... // Mesh Vertices extern berechnen // ... // Function Pointer holen glBindBufferARB = (PFNGLBINDBUFFERARBPROC)wglGetProcAddress("glBindBufferARB"); glGenBuffersARB = (PFNGLGENBUFFERSARBPROC)wglGetProcAddress("glGenBuffersARB"); glBufferDataARB = (PFNGLBUFFERDATAARBPROC)wglGetProcAddress("glBufferDataARB"); glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)wglGetProcAddress("glDrawRangeElements"); glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC) wglGetProcAddress("glDeleteBuffersARB"); // Indices erzeugen indices = new unsigned short[ (mesh.nCountX-1)*(mesh.nCountY-1)*6 ]; int ii=0; for( int x=0; x<(mesh.nCountX-1); x++) { for( int y=0; y<(mesh.nCountY-1); y++) { indices[ii] = x*mesh.nCountY + y; indices[ii+1] = x*mesh.nCountY + y + 1; indices[ii+2] = (x+1)*mesh.nCountY + y + 1; indices[ii+3] = (x+1)*mesh.nCountY + y + 1; indices[ii+4] = (x+1)*mesh.nCountY + y; indices[ii+5] = x*mesh.nCountY + y; ii += 6; } } // VBOs erzeugen und Daten kopieren glGenBuffersARB(1, &vboId); glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboId); glBufferDataARB(GL_ARRAY_BUFFER_ARB, (mesh.nCountX)*(mesh.nCountY)*sizeof(vertice), vertices, GL_STATIC_DRAW_ARB); glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); glGenBuffersARB(1, &eboId); glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, eboId); glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, (mesh.nCountX-1)*(mesh.nCountY-1)*6*sizeof(unsigned short), indices, GL_STATIC_DRAW_ARB); glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); //später zeichnen glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboId); glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, eboId); glInterleavedArrays(GL_N3F_V3F, 0, 0); glDrawElements(GL_TRIANGLES, (mesh.nCountX-1)*(mesh.nCountY-1)*6, GL_UNSIGNED_SHORT, 0); glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);rapso schrieb:
wobei ich mir bei einer 9250 auch nicht so sicher bin was die kann, war das nicht nur eine onboard karte?
Nein, die Radeon 9250 ist eine 128MB AGP Karte mit recht guter 3D Performance.
Bei einer Quadro 3500 lief es ähnlich...Übrigens:
den Performance-Einbruch habe ich auch ohne Licht, also bei folgender Konfig:glDisable(GL_LIGHTING); glPolygonMode( GL_FRONT_AND_BACK, GL_LINE);Mit Licht passiert das nicht:
glEnable(GL_LIGHTING); glPolygonMode( GL_FRONT_AND_BACK, GL_FILL);Tappe hier momentan etwas im Dunkeln

-
rapso schrieb:
mach das clear sofort nach dem swapbuffers.
...
und deine struct sollte 16byte alligned sein.Hi Rapso,
habe beides nochmal explizit ausgetestet.
Hatte mich bislang daran orientiert, Berechnungen direkt nach dem Swappen auszuführen, da ich dies schon öfters gelesen hatte.Die Struktur habe ich jetzt mit
VERTICE __declspec(align(16)) vertice;deklariert, siehe auch http://msdn2.microsoft.com/en-us/library/83ythb65.aspx
Das glClear führe ich nun direkt nach dem Swappen aus.
Beides hat leider nicht die geringste Auswirkung.Mal abgesehen davon, dass die finale FPS mich nicht umhaut, so wundere ich mich immer noch sehr über die drastischen Einbrüche bei Verwendung der VBOs unter den vorher beschriebenen Bedingungen (mehr als 40000 Elemente für glDrawElements und im Wire-Modus).
Gruß,
Modes
-
Vielleicht reicht über der Anzahl von 40000 VBO's die Kapaizität der Grafikkarte nicht mehr und es muss auf festplatte doer andere Speichermedien ausgelagert werden. Schon mit dem RAM wäre es dann wesentlich langsamer als über den Grafikkarten internen Speicher.
Oder ich steh schon wieder auf dem Schlacuh und verwechsel etwas.
-
modestia schrieb:
rapso schrieb:
versuch triangles statt quads, graphickarten koennen eigentlich keine quads. es wird jedesmal zu dreiecken konvertiert.
Quads haben einen entscheidenen Vorteil: sie können sich krümmen, was bei korrekten Vertex-Normalen saubere Übergänge schafft.
eigentlich triangulieren das die graphikkarten nur bzw der treiber, du hast also eigentlich garkeine vorteile davon.
Ausserdem halbiert es die Anzahl der Objekte, die Indices werden um 1/3 reduziert.
Habe trotzdem mal Triangles probiert.
"glDrawElements mit VBOs, ohne glClear" ging mit Triangles statt Quads von 73 auf 74 fps hoch
ich koennte vermuten dass das problem woanders liegt wenn die framerate so ist. 74fps bei 40000 indices? also 60 000 wenn es dreiecke waeren? zufaellig *hehe*
was ist denn der maximale wert deiner 9250? 5Mio/s klingt nicht so gut, meine psp uebertrifft das (ohne licht etc.)rapso schrieb:
wenn du glclear testen willst, mach das clear sofort nach dem swapbuffers und falls du einen stencilbuffer angibst, dann clear den auch.
Stencil nutze ich für den Test noch nicht.
Das glClear hatte ich ja schon rausgenommen, aber danke für den Tip!wenn du einen stencilbuffer setzt, selbst wenn du den nicht benutzt, musst du den beim clear vom zbuffer mit clearen wenn es schnell gehen soll.
rapso schrieb:
char color, sowas gibt es hardwaremaessig nicht. und deine struct sollte 16byte alligned sein.
Der Witz ist, dass es bis 40000 Indizes keine Probleme gibt.
Dachte auch, das wäre genau der Sinn von Interleaved Arrays...
Somit sollte es der GPU doch egal sein, oder?und ab 40 000 indices fuer quads, also 60 000 bei triangles bricht es ein, und das nur wenn das char mit drinnen ist?
rapso schrieb:
um sagen zu koennen weshalb dein vbo so lange bem update braucht, muesste man sehen was du machst, da laeuft eindeutig etwas schief.
Ist eigentlich nix aussergewöhnliches, hier mal eine kurze Zusammenfassung:
...glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, (mesh.nCountX-1)*(mesh.nCountY-1)*6*sizeof(unsigned short), indices, GL_STATIC_DRAW_ARB); ...ich glaube zum updaten sollte man GL_DYNAMIC_DRAW benutzen
Übrigens:
den Performance-Einbruch habe ich auch ohne Licht, also bei folgender Konfig:glDisable(GL_LIGHTING); glPolygonMode( GL_FRONT_AND_BACK, GL_LINE);Mit Licht passiert das nicht:
glEnable(GL_LIGHTING); glPolygonMode( GL_FRONT_AND_BACK, GL_FILL);Tappe hier momentan etwas im Dunkeln

vielleicht bist du ja auch nicht von den vertices her limitiert. zum benchmarken von vertices solltest du das objekt so klein wie moeglich auf dem screen haben. des weiteren lohnen sich garkeine benchmarks wenn du im window mode bist, vor allem clear ist dannn vermutlich viel langsammer.
zudem solltest du checken ob du nicht mit VSync testest, denn wenn dein monitor nur 75hz darstellst, wirst du nie ueber diese fps kommen.
-
modestia schrieb:
rapso schrieb:
mach das clear sofort nach dem swapbuffers.
...
und deine struct sollte 16byte alligned sein.Hi Rapso,
habe beides nochmal explizit ausgetestet.
Hatte mich bislang daran orientiert, Berechnungen direkt nach dem Swappen auszuführen, da ich dies schon öfters gelesen hatte.welche berechnungen?
gut ist
logic zeichnen zwap clear logic zeichnen swap clear ...viele neigen zu
logic clear zeichnen swap ..zudem, wie gesagt, in fullscreen testen ;).
desweiteren, color cleart wohl kein spiel. man ueberzeichnet eh alles, und fuer den z+stencilbuffer gibtb es meist einen 'zero cycle clear', also quasi umsonst.Die Struktur habe ich jetzt mit
VERTICE __declspec(align(16)) vertice;deklariert, siehe auch http://msdn2.microsoft.com/en-us/library/83ythb65.aspx
Das glClear führe ich nun direkt nach dem Swappen aus.
Beides hat leider nicht die geringste Auswirkung.nein, darum geht es nicht

es geht darum dass in einem array die vertices immer 16byte (oder zumindestens 8byte) alligned sind.
wenn also sizeof(Vertex) 16, 32, 48... ist, gibst du der graphikkarte optimales futter. wenn du einen char einbaust, also dann ganz krumme werte hast bei den addressen der vertices, kommt eine gpu damit absolut nicht klar.
Ist wie SSE bei CPUs, alligned load ist sehr viel schneller als unalligned.Mal abgesehen davon, dass die finale FPS mich nicht umhaut, so wundere ich mich immer noch sehr über die drastischen Einbrüche bei Verwendung der VBOs unter den vorher beschriebenen Bedingungen (mehr als 40000 Elemente für glDrawElements und im Wire-Modus).
wiremodus kann durchaus langsammer als fillmodus sein ;). skalier das objekt einfach ganz klein zum testen. und wie gesagt, vsync aus und fullscreen

-
rapso schrieb:
welche berechnungen?
z.B. die Berechnungen, die das Mesh bzw. einzelne Vertices dynamisch aktualisieren und die beweglichen Objekte neu positionieren.
rapso schrieb:
viele neigen zu
logic clear zeichnen swap ..Ähem...an diesem Gerücht ist bestimmt was dran

rapso schrieb:
zudem, wie gesagt, in fullscreen testen ;).
DAS bringt in der Tat was, bin ohne glClear auf 106 fps gekommen

Ähnliche Raten bekomme ich (nun logischerweise) auch, wenn ich das Windowsfenster auf ca. 600x400 Pixel setze.
Denke, hier bin ich einfach zu gierig nach Pixeln
rapso schrieb:
desweiteren, color cleart wohl kein spiel. man ueberzeichnet eh alles, und fuer den z+stencilbuffer gibtb es meist einen 'zero cycle clear', also quasi umsonst.
Aha, also lieber einen blauen Himmel als Hintergrund zeichnen als "clearen"?
Beim Stencil bin ich noch nicht, werde ich aber mal testen...rapso schrieb:
nein, darum geht es nicht

es geht darum dass in einem array die vertices immer 16byte (oder zumindestens 8byte) alligned sind.Dachte, genau das soll ja die "align" Methode vorgaukeln.
Hatte aber das CHAR aus dem Struct schon rausgenommen, so dass es hier kein Unterschied mehr machte.Komme jetzt der Sache schon näher, danke schonmal!
-
glFlush() vor dem swappen kann in einigen fällen und treiberabhängig einen großen geschwindigkeitsvorteil bringen

edit: SwapBuffers() impliziert eigentlich glFlush(), nichtsdestotrotz hat es aus irgendeinem mir unerfindlichem grund ein steigerung der framerate eines projektes von mir um 250% gebracht. vielleicht ist der treiber verbuggt :S