Vertex Arrays mit VBO's sind langsamer ? :(



  • Wenn du genau wissen willst, wo der Flaschenhals ist, dann empfehle ich dir einen guten Profiler (z.B CodeAnalyst).



  • Vielen Dank für eure Tipps:

    Das es mit dem linearen Beschreiben ein Problem gibt, würde ich erstmal ausschließen, da ich selbe Ergebnisse mit glBufferSubData bekomme.
    Der Flaschenhals muss woanders liegen. Ich werde mir mal "volatile" dazu ansehen.
    Da die Vertexdaten abhängig von der aktuellen Kamerasicht sind, also voll dynamisch errechnet werden, können sich theoretisch alle Daten ändern. Das mit den floats ist eine gute Idee, 1 Byte pro Farbe würde auch ausreichen 🙂 Was mich halt nur sehr wundert, ist die Tatsache, das die FPS' mit VBO's deutlich in den Keller gehen.
    Ich verstehe, dass bei meiner Vorgehensweise VBO's nicht wirklich mehr bringen müssen, aber sie sollten doch zumindest gleich schnell sein oder ?

    Bei Vertex-array habe ich die Daten im RAM und die müssen dann auch zur Grafikkarte gepumpt werden. Bei VBO's (So habe ich es zumindest verstanden) schreibe ich direkt in den Speicher der Grafikkarte und schicke dann nur noch den glDrawArray()-Befehl rüber. Oder sind hier die Übertragungswege unterschiedlich. Vielleicht liegt es auch daran, das ich schnellen Speicher habe (DDR2 666MHZ) und meine Graka nicht die schnellste ist (Geforce 8600 GT) ?
    CodeAnalyst schaue ich mir mal an. Der Profiler vom Visualstudio zeigt an, das
    die meiste Performance bei irgendeiner nvidia-dll draufgeht..also Treiber vermute ich. Habt ihr sonst noch eine Idee..oder vielleicht sogar Ratschläge, wie man performantes Scrollen mit mehreren Layer (alles nur 2D) alternativ lösen kann, außer mit Renderpages. Eine Tileengine (mit homogenen Tiles) hatte ich auch schon, aber da bin ich nicht flexibel genug finde ich. Ich würde ja alles
    direkt in der Grafikkarte verstauen, aber die Welt soll recht groß sein und möglichst wenig dynamisch nachladen.

    Vielleicht habt ihr da noch ein paar Tipps zu meinem Code oder generelle Ratschläge 🙂

    Vielen Dank schonmal

    Gruß

    FbrJogl



  • Ich denke hier liegt ein grundsaetzliches Missverstaendnis vor.
    Du hast vermutlich irgendwo gelesen, dass VBOs toll und schnell sind und glaubst, dass es schneller sein muesste, die Daten direkt in den Grafikspeicher anstatt zunaechst in den Hauptspeicher zu schreiben.
    Effektiv macht der Treiber mit den Daten im Hauptspeicher aber nichts anderes als sie in einen (internen) Vertexbuffer zu schreiben (also das gleiche wie Du jetzt auch).
    Der Treiber kann das nun offenbar schneller als Du.
    Das liegt einerseits daran, dass der Zwischenstop im Hauptspeicher wegen ueberschaubarer Datenmenge nichts kostet und dass der Treiber die Daten cache-freundlich (Indexing etc) aufbereitet und somit weniger zu uebertragen ist *und* schneller gerendert werden kann.
    Du hast leider einfach an der falschen Stelle "optimiert"...



  • Ok, verstehe 🙂 Dann kann ich da wohl nicht mehr rausholen 😞
    Sind denn ~200 FPS für ca. 5000 Quads (Mit Alphablending) nicht trotzdem noch recht wenig ? Meine CPU ist gerade mal zu 30% ausgelastet, also kommt die Karte irgendwie schon nicht hinterher. Dachte immer es sei meist umgekehrt, das die CPU nicht mit dem schaufeln hinterherkommt ? Und 20000 Vertices sollten eine Geforce 8600 GT
    nicht allzu in Schwitzen bringen oder ?



  • Wenn Deine Quads alle bildschirmfuellend sind, kriegst Du die GPU auch schon mit 100 in die Knie 😉
    Davon abgesehen scheint mir Dein Konzept einfach nicht hardware-nah.
    Falls Du mal erklaeren moechtest, was Du ueberhaupt erreichen willst und was Du dazu genau anstellst, kann man Dir vielleicht konkretere Ratschlaege geben...



  • hi, ok ich erkläre mal kurz was ich mir so vorgestellt habe.
    Und zwar möchte ich in späterer Zukunft (denke so 2-3 Jahre Entwicklungszeit für die Engine)
    anfangen, etwas umfangreichere 2D-Spiele wie Turrican, R-Type, Probotector etc.
    zu entwickeln. Hierfür wollte ich mir erstmal eine eigene 2D-Engine basteln,
    welche von den meisten "hardware-nahen" Operationen abstrahiert und mich voll
    auf das eigentliche Spiel konzentrieren lässt. Um gute Performance und Platformunabhängigkeit
    zu bekommen habe ich mich für OpenGL, GLFW und GLEW entschieden. Für Sound wird dann
    noch FMOd dazukommen. Denke das ist eine gute Kombination. Momentan habe ich auch schon
    ein paar Klassen auf die Beine gestellt:

    TGALoader, Logger, FPSCounter, TextureManager, ConfigFileReader, Renderer

    ..Und genau bei dem Renderer haperts ein bisschen bei mir.

    Meine Engine ist momentan so aufgebaut, das ich ein Objekt von der Engine
    instanziere, dann 3 CallBackfunktionen registriere (Initialisieren, MainLoop, Exit)
    und gleich mit dem Spiel loslegen kann.

    Der TextureManager funktioniert so, das er 1024x1024 große Texturen
    in die Grafikkarte lädt und dann eine Schnittstelle bereitstellt,
    mit der auf Ausschnitte der Textur zugegriffen werden kann.
    Dadurch spare ich mir dann einiges an TexturSwitching.
    Als nächstes kann eine sogenannte TilePalette definiert werden.
    Jedes Tile der Palette besitzt dabei eine Grafik (Zeigt auf das Subtexture)
    des TextureManagers. Mithilfe der Palette können dann beliebig viele
    Tiles erstellt werden und dann in einer großen Welt statisch platziert werden.
    Bei einer 400 Bildschirmgroßen Welt und 2 Millionen darin platzierten Tiles
    verbrauche ich hier "nur" 40-50 MB an RAM. Es sind deshalb so viele Tiles,
    weil diese auch hintereinander angeordnet werden können, sprich es sind
    einige Layer möglich. Da ich nciht alle 2 Millionen Tiles auf einmal rendern
    kann, hatte ich nun die Idee, meine Welt in Renderpages aufzuteilen.
    eine Renderpage ist sogroß wie der Bildschirm und je nachdem wo sich
    der aktuelle Viewport befindet, müssen bis zu 4 Renderpages zum rendern in Betracht
    gezogen werden. Beim rendern werden dann diese 4 Seiten durchgegangen und
    per Bounding-Box verfahren geschaut, was tatsächlich sichtbar auf dem Viewport ist.
    Die ermittelten Tiles werden dann in einige VertexArrays geschrieben.
    Und zwar in x = (AnzahlLayer * Anzahl verschiedene Texturen) verschiedene
    Vertex-Arrays. Das sind bei mir momentan bei 8 Verschiedenen Texturen
    und 6 Layern 48 VertexArrays. So spare ich mir das Sortieren der Layer,
    welches trotz Z-Buffer nötig ist, weil jedes Tile Alphablending unterstützt.
    Habe auch gelesen, das es eventuell hilfreich ist, nicht alle mit Alphablending-Möglichkeiten
    zu versehen, sondern erst einige mit Alpha-Test und dann nur zum Schluss die mit
    Alphablending. Da ich Layerweise rendere, kann ich zwischen den Layern dann
    die dynamischen Objekte rendern. Also quasi verschiedene Backgrounds, Hauptlayer,
    Dynamische Objekte (Player etc.), Frontlayer.

    Das ist so momentan mein Ansatz für den Renderer, aber mittlerweile glaube ich, dass
    es bestimmt bessere Ansätze gibt. Wie sieht es mit Quadtrees aus anstatt Renderpages ?
    Würde sich das lohnen ? Kennt jemand einen Link, wo man sich über das Design
    von einfachen Renderern für Spiele schlau machen kann. Es gibt bestimmt viel
    bessere Ansätze, wie man so ein Projekt strukturieren kann. Vielleicht haben die Erfahrenen
    unter euch da ein paar gute Tipps für do's und dont's 🙂

    Wer mal meinen bisherigen Stand sehen möchte kann sich hier
    die Exe (Für Windows) herunterladen. Sie gibt auch die aktuellen FPS
    in einer Textdatei aus. (Vertex-Array ohne VBO)- Version.
    Vielleicht habt ihr ja viel mehr und mein Vista ist das ganze Prob xD

    http://rapidshare.com/files/119825927/Retro2DEngine.zip

    Gruß

    Fbrjogl



  • Wenn ich Dich richtig verstehe sind die anfangs erwaehnten 5000 Quads dann jene Objekte die aktuell gerade sichtbar auf dem Bildschirm sind?
    Warum musst Du die denn unbedingt bei jedem Frame neu erzeugen?
    Da wird sich von einem Bild zum naechsten doch vermutlich nicht viel dran aendern - und dann macht auch der VBO wieder Sinn...



  • hmm...aber wenn sich meine Kamera nur um eine Pixel verändert..dann ändern sich alle 5000 ja auch um 1 Pixel....vieleicht sollte ich mal mit translate arbeiten..also ein translate vor allen 5000 Quads..anstatt jeden Quad einzeln zu verschieben ? 🙂



  • ein translate vor allen 5000 Quads..anstatt jeden Quad einzeln zu verschieben ?

    Eine hervorragende Idee! 😉



  • wie viel performance bringen vertex arrays?


Anmelden zum Antworten