[gelöst] std::bad_alloc trotz ausreichendem Speicher



  • wenn ich COUNT einfach auf 2048 festlege, läuft alles wie geschmiert, obwohl ja im Endeffekt genauso viel Speicher reserviert wird.

    Im Vergleich zu wenn COUNT auf 1024 festgelegt ist, wie du ja zuvor gesagt hattest? Zweifelhaft 😉
    Wenn das keine Konstante ist, dass wird COUNT u.U. einfach nicht [mehr] das enthalten, was du eigentlich glaubst.

    Und sonst klingt das alles etwas wirr. Man zeichnet keine Texturen, es ist unklar was deine ganzen Vertexarrays überhaupt sollen (enthalten die irgendwelche sinnvollen Daten oder legst du die rein nach dem Prinzip "mehr ist besser" an?).

    _vcount enthält dabei die Anzahl an aktuell verwendeten Vertex*

    ...?



  • COUNT ist per #define festgelegt, wäre also sehr seltsam, wenn sich das ändert.
    Tut mir Leid, dass der Code etwas schwer zu verstehen ist, ich kenn mich mit der ganzen Materie noch nicht so super aus.

    Die ganzen Vertex Arrays haben aber trotzdem einen Grund. Ich versuche bei dem Zeichnen der Texturen mit möglichst wenig Draw Calls auszukommen. Dazu erstelle ich mir Vertex Arrays der Größe 4 * COUNT (4 weil eine Textur nun mal 4 Ecken hat) und wenn eins davon voll ist, wird ein neues erstellt. Es kann ja auch mal vorkommen, dass eine Textur mehr als 1024 mal gezeichnet werden soll (Particle Engine, große TileMap etc.).

    Am Ende werden dann alle Vertices, die sich angesammelt haben, gezeichnet. Ich könnte natürlich auch nur ein Vertex* verwenden und per realloc vergrößern, oder einen vector verwenden, aber dann müsste ich den VertexBuffer jedes mal neuerstellen, wenn mehr Vertices dazugekommen sind.

    Ich hab mir eben noch einmal den SpriteBatch von ANX (sozusagen das OpenSource XNA) angeschaut, und dort werden die Vertices erst ganz am Ende erstellt, wenn sie gezeichnet werden. Davor werden nur Texturen, Positionen und Farben gespeichert. Vielleicht werde ich mal versuchen das so rum zu implementieren.



  • Wenn ich das richtig verstehe, möchtest du also nur 2D-Grafiken rendern.

    So lange ich "nur" 1024 mal eine Textur zeichne, funktioniert alles, sobald ich aber mehr als 1024 Texturen zeichne

    Wie machst du das, wenn deine Vertexarrays nur Platz für jeweils 1024 Quads bieten?

    oder einen vector verwenden, aber dann müsste ich den VertexBuffer jedes mal neuerstellen, wenn mehr Vertices dazugekommen sind.

    Wie kommst du zu der Aussage? Es zwingt dich niemand, die Größe eines vectors zu verändern, aber im Gegensatz zu C-Arrays sind std::vector und std::array in der Lage out-of-bounds-Zugriffe im Debug-Modus zu erkennen, wie SeppJ ja schon gesagt hat.



  • Wenn die Arrays keinen Platz mehr haben, hab ich eben ein neues erstellt.
    Egal, ich habs jetzt so gemacht, dass ich alle Vertices in einen Vector speicher und dann ganz am Ende den Vector sozusagen in Arrays der Größe COUNT aufspalte um die Daten in den VertexBuffer zu kopieren und zu rendern. So funktioniert das nun auch, auch wenn bei 4096 mal eine Textur rendern das Bild blinkt und nur ca. 20FPS auf die Reihe bekommt, während so viele Texturen XNA keinesfalls aus dem Schritt bringen, auch wenn dieses auf C# basiert. Na ja, da werd ich mal noch ein bisschen nach Optimierungen suchen müssen.
    Auf jeden Fall mal ein Dankeschön an alle Helfenden hier 🙂

    Nur noch eine klitzekleine Frage:
    wenn ich per
    for each(pair<ID3D11ShaderResourceView*, vector<Vertex>> p in _textures)
    durch eine map<ID3D11ShaderResourceView*, vector<Vertex> durchiteriere, wirft IntelliSense einen Fehler, dass for each den Ausdruck nicht verarbeiten könnte, kompilieren tut es aber wunderbar. Sollte ich trotzdem lieber etwas (meiner Meinung nach unübersichtliches) wie
    for(map<ID3D11ShaderResourceView*, vector<Vertex>>::iterator i = _textures.begin(); i != _textures.end(); i++)
    verwenden, gibt es da noch eine viel bessere Variante, oder soll ich den Fehler einfach ignorieren?



  • Er hat also eine Größe von 36Bytes.

    Das kann man einfach so sagen? Ist das nicht total maschinenabhängig?



  • Kann sein, ich bin jetzt einfach mal von sizeof(float) = 4 Bytes ausgegangen, kann aber natürlich variieren, im Code verwende ich natürlich immer sizeof(Vertex), die 36 Bytes waren nur zum anschaulich machen.


  • Mod

    Xwin7userX schrieb:

    Nur noch eine klitzekleine Frage:
    wenn ich per
    for each(pair<ID3D11ShaderResourceView*, vector<Vertex>> p in _textures)
    durch eine map<ID3D11ShaderResourceView*, vector<Vertex> durchiteriere, wirft IntelliSense einen Fehler, dass for each den Ausdruck nicht verarbeiten könnte, kompilieren tut es aber wunderbar. Sollte ich trotzdem lieber etwas (meiner Meinung nach unübersichtliches) wie
    for(map<ID3D11ShaderResourceView*, vector<Vertex>>::iterator i = _textures.begin(); i != _textures.end(); i++)
    verwenden, gibt es da noch eine viel bessere Variante, oder soll ich den Fehler einfach ignorieren?

    for each ist eine nicht standardgemäße Compilererweiterung von MSVC++. Nutz lieber die standardkonforme zweite Variante, std::for_each oder am besten, falls MSVC++ dies inzwischen kann, ein range-based for.



  • Oder:
    map<ID3D11ShaderResourceView*, vector<Vertex>>::iterator ➡ auto

    <:xmas2:>



  • Vielen Dank, ein ranged based for war genau das, was ich gesucht hab (entspricht ja sozusagen dem MS for each). Jetzt wirft IntelliSense auch keinen Error mehr 🙂

    Edit: Also entweder hat MS bei der Implementierung von Ranged Based For ziemlich geschlampt, oder das ist, warum auch immer, immer so unperformant. Denn mit for(auto i : _textures) hab ich bei 4096 * mal eine Textur zeichnen 18FPS, wenn ich for(auto i = _textures.begin(); i != _textures.end(); i++) verwende, bekomme ich 23FPS. Oder kann es sein, dass dadurch, dass _textures im Moment nur eine Länge von 1 hat (ich zeichne ja bisher nur eine Textur) ranged base for noch einen sehr großen OverHead hat, der sich bei größeren Größen von _textures auszahlt?



  • die Textur wird jedes mal kopiert.



  • for(auto &i : _textures)
    

    ohne das & iteriert er by value, bzw erstellt eine Kopie und arbeitet damit.



  • Wunderbar, jetzt läuft das so auch mit 23FPS 😃
    Vielen Dank!


Anmelden zum Antworten