Performance-Frage [weiteres Problem!]
-
Ein DrawPrimitive-Call lohnt sich fuer 12 Triangles nicht.
Steck alle Objekte die zusammen transformiert werden sollen in einen Vertexbuffer.
-
hellihjb schrieb:
Ein DrawPrimitive-Call lohnt sich fuer 12 Triangles nicht.
Steck alle Objekte die zusammen transformiert werden sollen in einen Vertexbuffer.Jeder einzelne Geschützturm hat eine andere ausrichtung...also eine andere Worldmatrix....
und die haben alle den gleichen vertexbuffer nur verschiebe ich dann eben an einen bestimmten punkt, rotiere das ganze und stelle es dar...dann zum nächsten punkt wo eingeschütz stehen soll usw.Ich muss doch für jeden Würfel vor dem darstellen
die rotation und position an eine WorldMatrix angeben oder nicht?
und dann rufe ich
[QUOTE] Device->SetTransform( D3DTS_WORLD, &Objects[q]->WorldMatrix);[/cpp]
auf um mitzuteilen dass das objekt so positioniert und rotiert werden soll
da kann ich doch gar nicht alle gleichen objekte in den gleichen drawprimitiv aufruf packen oder? weil ich ja dazwischen andere matrizen (weil andere rotationen) angeben muss....
Sind zwar die gleichen Türme aber alle nach einem anderen winkel ausgerichtet.
oder seh ich das falsch...??ich hab das so aus den kleinen beispielen aus den büchern die ich hier hab rausgenommen...da steht ja leider nie drin wie das bei vielen objekten am besten machbar ist....

Hier ein Bild damit ihr wisst wie es aussieht:
http://i191.photobucket.com/albums/z231/kuldren/10sept08-1.jpgÜbrigens besteht immer noch das Problem dass die Framerate um ca 10-15 fällt sobald man so nahe heranzoomt (einfach die kamera bewegt) dass man ca 5x5 Geschütze im Bild hat...
-
Dann multiplizierst Du die Vektoren eines Wuerfels eben erst mit der entsprechenden Matrix bevor Du sie in den Vertex-Buffer schreibst.
-
hellihjb schrieb:
Dann multiplizierst Du die Vektoren eines Wuerfels eben erst mit der entsprechenden Matrix bevor Du sie in den Vertex-Buffer schreibst.
Hm
Bisher fülle ich den Buffer so
CUSTOMVERTEX cbuf[]={ { - Objects[q]->Size.x/2, - Objects[q]->Size.y/2, - Objects[q]->Size.z/2, Objects[q]->Color, 0, 1}, // Vorne { - Objects[q]->Size.x/2, + Objects[q]->Size.y/2, - Objects[q]->Size.z/2, Objects[q]->Color, 0, 0}, { + Objects[q]->Size.x/2, + Objects[q]->Size.y/2, - Objects[q]->Size.z/2, Objects[q]->Color, 1, 0}, { + Objects[q]->Size.x/2, + Objects[q]->Size.y/2, - Objects[q]->Size.z/2, Objects[q]->Color, 1, 0}, { + Objects[q]->Size.x/2, - Objects[q]->Size.y/2, - Objects[q]->Size.z/2, Objects[q]->Color, 1, 1}, { - Objects[q]->Size.x/2, - Objects[q]->Size.y/2, - Objects[q]->Size.z/2, Objects[q]->Color, 0, 1}, //usw }; BYTE* VertexBufferStart; Device->CreateVertexBuffer(sizeof(cbuf), D3DUSAGE_WRITEONLY, D3D_CUSTOMVERTEX, D3DPOOL_MANAGED, &Objects[q]->VB, NULL); Objects[q]->VB->Lock(0,0,(void**)&VertexBufferStart,0); memcpy(VertexBufferStart,cbuf,sizeof(cbuf)); //VertSize=sizeof(cbuf); Objects[q]->VB->Unlock(); Device->SetFVF(D3D_CUSTOMVERTEX);Und zeichnen erfolgt so:
Device->SetTransform( D3DTS_WORLD, &Objects[q]->WorldMatrix); Device->SetStreamSource(0,VB,0,sizeof(CUSTOMVERTEX)); Device->SetTexture(0,NULL); Device->DrawPrimitive(D3DPT_TRIANGLELIST,0,12);ich dachte setTransform(D3DTS_WORLD....); legt fest dass alles was als nächstes gezeichnet wird so rotiert wird ?
Wenn ich vor dem Füllen des Buffers die vektoren multipliziere (wie auch immer dass dann geht -> ? ) müsste ich das ja bei jedem draw vorgang für alle objekte machen....kostet das nicht zu viel zeit?
-
ja, beides ist eine suboptimale loesung, da du beim immer neu befuellen von buffern sehr drauf angewiesen bist, dass der treiber dir die buffer ohne stalls gibt. wenn du zuviel fuellen willst, oder zuviele buffer hast, oder... muss der treiber im zweifelsfall warten bis der vorherige aus der pipeline ist (und das koennen manchmal ein paar frames sein). so wenige polys wie du zeichnest koennte aber hellis idee durchaus funktionieren.
eine weitere moeglichkeit waere: vertexshader. du koenntest dann einmal zum start z.b. 32mal den turm in den buffer schreiben, dabei vergibst du jedem dieser tuerme eine andere ID (die du irgendwie mit in den buffer schreibst, also als vertex attribut). dann uebergibst du 32 Worldmatrizen als vertexshader-constants die du mittels der ID pro vertex indizieren kannst.
natuerlich ist das ein overhead 32mal das selbe objekt reinzuschreiben, aber so extrem lowpoly wie das ist, bist du einfach nur drawcall limitiert. mehr als 2000 drawcalls pro frame kann man kaum fluessig darstellen (wenn man texture+statechanges miteinbezieht).
-
Da habt Ihr mich wohl missverstanden.
Dieser Geschuetzturm besteht ja aus 13 einzelnen Wuerfeln die jeweils per Matrix an eben die Stelle gebracht werden wo sie hin sollen - es sind also 13 Render-Calls noetig.
Das Objekt besteht aber nur aus zwei "logischen" Teilen: ein statischer Sockel und ein bewegliche Geschuetz.
Mein Vorschlag war darum, fuer jedes dieser zwei Teilobjekte *einmal* einen Vertexbuffer anzulegen in dem die zugehoerigen Wuerfel bereits transformiert abgelegt sind - somit sind nur noch zwei Render-Calls notwendig und das Geschuetz bleibt beweglich.
-
Kann ich nicht einfach mehrere Streamsources angeben?
Hab mal ein bissl Google bemüht aber kein richtiges Beispiel gefunden...Allerdings wird erwähnt dass es möglich ist mehrere Sources anzugeben (sonst hätte der erste Parameter von setstreamsource auch wenig sinn)EDIT:
Ich werde das ganze jetzt so machen wie von euch vorgeschlagen...direkt die einzelteile zusammen im Buffer Speichern...
Gibt es da eine Möglichkeit mehrere Buffer zu einem zu verschmelzen?
Wenn ich das ganze mit einem vector anstelle funktioniert das erstellen und füllen des buffer leider nicht. Nur mit einem arrayEDIT2:
So hab es jetzt genauso gemacht und es funktioniert auch recht gut. Das darstellen funktioniert bei 100 geschützen bei 60 fps ohne probleme...Allerdings sinken die FPS sobald ich beginne zu feuern (sind ja wieder 10 schuss pro Geschütz und 100 geschütze also 1000 Kugeln und somit 1000 drawcalls)
Gibts dafür ne gute Möglichkeit das ganze effizienter zu machen?
Nebenfrage: Ist es normal dass die FPS um ganze 30 fallen sobald man näher mit der Kamera heranfährt? Wenn ich nache rangehe...dass ich ca 5x5 Geschütze im Sichtfeld habe fallen die fps auf 30

Aber von weitem oder ganz nahe sinds wieder 60....
Es ist sogar so dass sie kontinuierlich fallen je näher ich rangehe....und ganz nah springen sie plötzlich wieder auf 60 ...total seltsam
-
Kuldren schrieb:
Allerdings sinken die FPS sobald ich beginne zu feuern (sind ja wieder 10 schuss pro Geschütz und 100 geschütze also 1000 Kugeln und somit 1000 drawcalls)
Gibts dafür ne gute Möglichkeit das ganze effizienter zu machen?
du weisst doch dass du drawcall limitiert bist und wieder machst du diese mini drawcalls. pack alle particle in einen vertexbuffer und zeichne sie mit einem rutsch (drawcall)
Nebenfrage: Ist es normal dass die FPS um ganze 30 fallen sobald man näher mit der Kamera heranfährt? Wenn ich nache rangehe...dass ich ca 5x5 Geschütze im Sichtfeld habe fallen die fps auf 30

ja, dein stichwort ist vsync.
-
rapso schrieb:
du weisst doch dass du drawcall limitiert bist und wieder machst du diese mini drawcalls. pack alle particle in einen vertexbuffer und zeichne sie mit einem rutsch (drawcall)
Darauf wollte ich hinaus, aber ich müsste Position (das ist ja noch einfach) und Rotation der Schüsse transformieren bevor ich die Vertices in den Buffer schreibe. Da steh ich leider an, weil ich ja bisher einfach die WorldMatrix mit
Device->SetTransform( D3DTS_WORLD, &Objects[q]->WorldMatrix);dazu verwendet habe. Aber wie mache ich das ohne danach direkt den Drawcall zu starten

rapso schrieb:
ja, dein stichwort ist vsync.
Das hab ich schon in einem anderen Thread gelesen. Kann aber nicht wirklich was damit anfangen. Soll ich VSync abschalten? Wär das nicht Kontraproduktiv (Obwohls dann trotzdem mehr Frames wären?
-
Kuldren schrieb:
rapso schrieb:
du weisst doch dass du drawcall limitiert bist und wieder machst du diese mini drawcalls. pack alle particle in einen vertexbuffer und zeichne sie mit einem rutsch (drawcall)
Darauf wollte ich hinaus, aber ich müsste Position (das ist ja noch einfach) und Rotation der Schüsse transformieren bevor ich die Vertices in den Buffer schreibe. Da steh ich leider an, weil ich ja bisher einfach die WorldMatrix mit
Device->SetTransform( D3DTS_WORLD, &Objects[q]->WorldMatrix);dazu verwendet habe. Aber wie mache ich das ohne danach direkt den Drawcall zu starten

ja genau, du machst das, nicht D3d, du per hand in deinem code, in d3d setzt du identity.
rapso schrieb:
ja, dein stichwort ist vsync.
Das hab ich schon in einem anderen Thread gelesen. Kann aber nicht wirklich was damit anfangen. Soll ich VSync abschalten? Wär das nicht Kontraproduktiv (Obwohls dann trotzdem mehr Frames wären?
bitte informier dich doch darueber. wenn du weisst was das ist und wozu, wirst du all deine fragen beantworten koennen. that's no rocked science.
-
rapso schrieb:
bitte informier dich doch darueber. wenn du weisst was das ist und wozu, wirst du all deine fragen beantworten koennen. that's no rocked science.
Ok...werde mich später damit auseinandersetzen
rapso schrieb:
ja genau, du machst das, nicht D3d, du per hand in deinem code, in d3d setzt du identity.
Ok ... ich stelle jeden Schuss mit nur einem Dreieck dar und dieses Dreieck muss ich um einen bestimmten Winkel rotieren.
Dazu verwende ich prinzipiell die Formeln:
x'=x*cos(phi)-y*sin(phi) y'=x*sin(phi)+y*cos(phi)(x und y sind ja nur die Größe der Schüsse in x und y durch 2 - dabei beachte ich auch die vorzeichen)
Allerdings gelten die ja nur für das drehen um den Winkel (phi) und nicht das ausrichten nach phi.
Den Winkel hole ich mir übrigens so:
xBuf=(targetAimed->x-Position.x); yBuf=(targetAimed->z-Position.z); gFAngle=atan2f(xBuf,yBuf);Wenn ich aber die obigen Formeln verwenden will müsste ich für jeden der 3 Punkte eine andere Winkeldifferenz ausrechnen (also den Winkel des Punkts und dann vom Auszurichtenden Winkel abziehen) UND anschließend dann mit den obigen Formeln um diese Winkeldifferenz rotieren- Allerdings erscheint mir das sehr kompliziert bzw. aufwändig- gibts da keine einfachere Möglichkeit?
Noch eine Frage:
Kann es sein dass der Teil mit dem ich den Vertexbuffer fülle:BYTE* VertexBufferStart=NULL; Device->CreateVertexBuffer(sizeof(cbuf), D3DUSAGE_WRITEONLY, D3D_CUSTOMVERTEX, D3DPOOL_MANAGED, &VB, NULL); VB->Lock(0,0,(void**)&VertexBufferStart,0); memcpy(VertexBufferStart,cbuf,sizeof(cbuf)); VB->Unlock(); Device->SetFVF(D3D_CUSTOMVERTEX);Den Speicher frisst?
Denn nach einiger Zeit stockt das Programm bzw. der Rechner.
Muss ich da noch etwas freigeben? Obwohl der VB ein Member der Klasse und keine temporäre Variable ist?Bin für alle Tipps dankbar!
-
Kuldren schrieb:
Wenn ich aber die obigen Formeln verwenden will müsste ich für jeden der 3 Punkte eine andere Winkeldifferenz ausrechnen (also den Winkel des Punkts und dann vom Auszurichtenden Winkel abziehen) UND anschließend dann mit den obigen Formeln um diese Winkeldifferenz rotieren- Allerdings erscheint mir das sehr kompliziert bzw. aufwändig- gibts da keine einfachere Möglichkeit?
du hast doch gesagt dass du schon die matrix hast, weil du sie doch an D3D als world matrix uebergibst. multipliziere doch einfach die positionen der vertices mit dieser matrix, d3d hat schon alle funktionen die du dafuer brauchst, bzw die eine.
Noch eine Frage:
Kann es sein dass der Teil mit dem ich den Vertexbuffer fülle:
[cpp]BYTE* VertexBufferStart=NULL;
Device->CreateVertexBuffer(sizeof(cbuf), D3DUSAGE_WRITEONLY,
D3D_CUSTOMVERTEX, D3DPOOL_MANAGED, &VB, NULL);
VB->Lock(0,0,(void**)&VertexBufferStart,0);
memcpy(VertexBufferStart,cbuf,sizeof(cbuf));
VB->Unlock();
Device->SetFVF(D3D_CUSTOMVERTEX);[/cpp]
Den Speicher frisst?
Denn nach einiger Zeit stockt das Programm bzw. der Rechner.
Muss ich da noch etwas freigeben? Obwohl der VB ein Member der Klasse und keine temporäre Variable ist?du scherzkaeks

leg einmal einen buffer an, nur einmal beim initialisieren, der ausreichend gross ist, ja, klar weisst du die groesse nicht, aber schaetz irgendwas grosses ab und falls du mehr particle haben solltest, musst du eventuell mehrmals lock + draw machen oder du ignorierst nach ein paar tausend particle einfach was noch kommt.
-
rapso schrieb:
du hast doch gesagt dass du schon die matrix hast, weil du sie doch an D3D als world matrix uebergibst. multipliziere doch einfach die positionen der vertices mit dieser matrix, d3d hat schon alle funktionen die du dafuer brauchst, bzw die eine.
du scherzkaeks

leg einmal einen buffer an, nur einmal beim initialisieren, der ausreichend gross ist, ja, klar weisst du die groesse nicht, aber schaetz irgendwas grosses ab und falls du mehr particle haben solltest, musst du eventuell mehrmals lock + draw machen oder du ignorierst nach ein paar tausend particle einfach was noch kommt.
Hoppla
....Erstmal ein großes Danke! für die vielen Tipps.
Hab jetzt sowohl Spielfeld als auch Schüsse und Geschütztürme so umstrukturiert dass die DrawCalls minimiert wurden.
Allerdings bleibt das Problem bestehen dass die Framezahl absackt wenn man näher heranzoomt - damit das nicht falsch verstanden wird. die Framezahl bleibt dann auch so niedrig - das ist also kein kurzzeitiger effekt sondern sie geht erst wieder hinauf wenn ich weiter heraus"zoome"...Allerdings tritt das Problem auch erst auf wenn ich ca 100 Geschütze am Spielfeld habe...bei 20 passiert gar nichts beim kameraverschieben.Durch das ganze "Optimieren" sinkt die Framerate auch "nur" noch von 59/60 auf 50-57 herab wenn alle 100 Geschütze feuern.
Allerdings kann das ganze auch auf 60 FPS laufen - dafür muss ich nur mit der Kamera etwas weiter aus der Szene heraus .... Anscheinend beeinflusst das das ganze doch enorm...Liegt das wirklich nur am Vsync?
-
Kuldren schrieb:
Allerdings kann das ganze auch auf 60 FPS laufen - dafür muss ich nur mit der Kamera etwas weiter aus der Szene heraus .... Anscheinend beeinflusst das das ganze doch enorm...Liegt das wirklich nur am Vsync?
nein, an vsync liegt es wenn die framerate von 60 auf 30 ohne zwischenstufen faellt.
es kann sein dass es ganz normal langsam wird? wenn du dem nachgehen willst, schau dir z.b. NVIDIA PerfHUD oder AMD GPU PerfStudio an.
-
rapso schrieb:
Kuldren schrieb:
Allerdings kann das ganze auch auf 60 FPS laufen - dafür muss ich nur mit der Kamera etwas weiter aus der Szene heraus .... Anscheinend beeinflusst das das ganze doch enorm...Liegt das wirklich nur am Vsync?
nein, an vsync liegt es wenn die framerate von 60 auf 30 ohne zwischenstufen faellt.
es kann sein dass es ganz normal langsam wird? wenn du dem nachgehen willst, schau dir z.b. NVIDIA PerfHUD oder AMD GPU PerfStudio an.
Danke...
Leider wird meine Karte laut UserGuide nicht unterstützt bzw. beim Kompilieren meckert meine IDE dass
#include "NVPerfSDK.h"nicht gefunden werden kann.
Ist es denn normal dass es mehr Rechenleistung kostet wenn man näher an die Objekte heranzoomt? Die Geschütze sind so lowpoly dass ich mir das irgendwie nicht vorstellen kann.
-
Kuldren schrieb:
Leider wird meine Karte laut UserGuide nicht unterstützt bzw. beim Kompilieren meckert meine IDE dass
#include "NVPerfSDK.h"nicht gefunden werden kann.
und das obwohl du dir das nvperf sdk geladen und installiert hast?
Ist es denn normal dass es mehr Rechenleistung kostet wenn man näher an die Objekte heranzoomt? Die Geschütze sind so lowpoly dass ich mir das irgendwie nicht vorstellen kann.
ich hab keine ahnung was der grund ist, gibt sicher 100dinge die es sein koennten, ein screenshot und angabe welche graka du hast koennte erstmal helfen.
mach zudem mal alles in wireframe und sag ob es dann schneller bzw ohne den einbruch laeuft.
-
[quote="rapso"]und das obwohl du dir das nvperf sdk geladen und installiert hast?
Jup...Geladen und installiert.rapso schrieb:
ich hab keine ahnung was der grund ist, gibt sicher 100dinge die es sein koennten, ein screenshot und angabe welche graka du hast koennte erstmal helfen.
mach zudem mal alles in wireframe und sag ob es dann schneller bzw ohne den einbruch laeuft.Also im Solid Mode fallen die FPS in Relation zur Nähe zum Spielfeld.
Im WireframeMode (UND - das ist das wichtige- MIT geladenen Texturen also die Linien werden wie die Texturen gefärbt) läuft es bei egal welcher Distanz bei festen 59/60 FPS....
Außerdem ist mir aufgefallen dass wenn ich naheheranzoome und die FPS auf 29/30 fallen - auch das abfeuern der geschosse die FPS nicht mehr beeinflusst und dass sie bei 29/30 kleben bleiben...Total seltsamHier ein paar Screenshots: (Bitte beachte den Abstand zum Spielfeld und die damit zusammenhängenden FPS)
http://i191.photobucket.com/albums/z231/kuldren/14092008-01.jpg
http://i191.photobucket.com/albums/z231/kuldren/14092008-02.jpg
http://i191.photobucket.com/albums/z231/kuldren/14092008-03.jpg
http://i191.photobucket.com/albums/z231/kuldren/14092008-04.jpg
http://i191.photobucket.com/albums/z231/kuldren/14092008-05.jpg
http://i191.photobucket.com/albums/z231/kuldren/14092008-06.jpgMeine Grafikkarte ist die Nvidia Geforce 7500 LE (Ja ist echt untere klasse aber so schlecht dass sie das nicht packt? wie gesagt...oblivion und WoW laufen bei guter Auflösung und mittleren details auch flüssig...)
EDIT: es ist übrigens nicht beabsichtigt dass bei manchen bildern die FPS angaben doppelt vorhanden sind.....das ist wohl beim kopieren ins paint passiert also bitte die unteren werte ansehen
-
Kuldren schrieb:
rapso schrieb:
und das obwohl du dir das nvperf sdk geladen und installiert hast?
Jup...Geladen und installiert.
ich glaube du hast einfach nur nicht die include pfade usw. gesetzt.
wobei bisher bei perfHUD nichts zum includen war, man musste nur d3d speziell initialisieren udn ueber perfhud starten. schau in die doku, es ist nicht viel arbeit.rapso schrieb:
ich hab keine ahnung was der grund ist, gibt sicher 100dinge die es sein koennten, ein screenshot und angabe welche graka du hast koennte erstmal helfen.
mach zudem mal alles in wireframe und sag ob es dann schneller bzw ohne den einbruch laeuft.Also im Solid Mode fallen die FPS in Relation zur Nähe zum Spielfeld.
Im WireframeMode (UND - das ist das wichtige- MIT geladenen Texturen also die Linien werden wie die Texturen gefärbt) läuft es bei egal welcher Distanz bei festen 59/60 FPS....
Außerdem ist mir aufgefallen dass wenn ich naheheranzoome und die FPS auf 29/30 fallen - auch das abfeuern der geschosse die FPS nicht mehr beeinflusst und dass sie bei 29/30 kleben bleiben...Total seltsamtja, im wireframe fluessig, ohne wireframe faellt die fps, ich wuerde sagen du bist fillrate oder pixelshader oder texture limitiert.
Meine Grafikkarte ist die Nvidia Geforce 7500 LE (Ja ist echt untere klasse aber so schlecht dass sie das nicht packt? wie gesagt...oblivion und WoW laufen bei guter Auflösung und mittleren details auch flüssig...)
oblivion mit 60fps? ich glaube da kaempft die graka eher um ihre 30fps, oder?

aber ohne genau rauszufinden woran es liegt kann man nicht sinnvoll optimieren.
btw. http://developer.download.nvidia.com/presentations/2008/GDC/GDC_08_Perf_Tools.pdf
-
rapso schrieb:
ich glaube du hast einfach nur nicht die include pfade usw. gesetzt.
wobei bisher bei perfHUD nichts zum includen war, man musste nur d3d speziell initialisieren udn ueber perfhud starten. schau in die doku, es ist nicht viel arbeit.
Hab zwar schon mal reingeschaut und da steht direkt was von install only und dann die änderungen im code
tja, im wireframe fluessig, ohne wireframe faellt die fps, ich wuerde sagen du bist fillrate oder pixelshader oder texture limitiert.
das heißt? liegts nur an der Karte oder am code? bzw. wenn ich auf HW beschränkt bin kann ich doch ohnehin nicht viel tun oder?oblivion mit 60fps? ich glaube da kaempft die graka eher um ihre 30fps, oder?

"flüssig" also spielbar ohne dass es extrem ruckelt...;)
aber ohne genau rauszufinden woran es liegt kann man nicht sinnvoll optimieren.btw. http://developer.download.nvidia.com/presentations/2008/GDC/GDC_08_Perf_Tools.pdf
thx...werd mir mal alles ansehenDanke auf jeden fall für die viele Hilfe!