glDeleteTextures scheint den Texturspeicher unter Windows nicht freizugeben, gibt es keine Lösung?

8

Ich habe einige Probleme mit meiner openGL-Anwendung, die nicht genügend Arbeitsspeicher hat und versuche mein Problem zu finden. Zu diesem Zweck habe ich ein kleines Testprogramm erstellt, das im Grunde nur eine riesige Textur aus einer Datei lädt glDeleteTextures lädt und lädt es dann erneut, wenn ich dieses Testprogramm auf OSX diesen Prozess für hunderte von Iterationen ohne Probleme ausführen kann (am meisten Ich lief es war 1024 und das hatte keine Probleme) aber nach etwa 14 Iterationen auf Windows bekomme ich einen GLU_OUT_OF_MEMORY Fehler. Die Textur, die ich immer wieder lade, ist eine riesige Himmelskuppel (4096 x 1024 und 4,9 MB).

Hier ist der Code, den ich mit Kommentaren für die nicht Lispeln geneigt bin:

Testprogramm:

%Vor%

Create-texture-from-file (das meiste dieser Methode besteht aus OpenGL-Aufrufen, daher denke ich, dass die meisten openGL-Leute ein vernünftiges Verständnis davon haben sollten, was hier passiert, aber ich kann alles, was verwirrend ist, klären):

%Vor%

Ich habe an anderer Stelle gelesen, dass die glDeleteTextures nicht alle Ressourcen vollständig abhandeln, aber keiner dieser Beiträge Alternativen oder Lösungen bietet. Gibt es keine solche Lösung?

    
Mike2012 01.12.2011, 00:26
quelle

3 Antworten

10

Windows OpenGL-Treiber basieren auf der Annahme, dass Ihr Code irgendwann Zeichen zeichnet. Aus diesem Grund neigen sie dazu, Dinge genau dann zu vermeiden, wenn sie von ihnen verlangt werden, und verschieben sie auf eine passendere Zeit. Und darauf kommst du hier rein.

Nur weil Sie OpenGL mitteilen, dass Sie mit einem Texturobjekt fertig sind, heißt das nicht, dass OpenGL sofort diesen Speicher freigeben muss. Dies erfordert in der Regel einige ziemlich schwere Operationen. Stattdessen werden die Treiber dies bis später verschieben.

Das Problem ist, dass "später" normalerweise als eine Art von glDraw* -Befehl, glEnd , glFlush/Finish oder ein Swap-Buffer-Befehl definiert wird. Oder etwas von dieser Art. Wenn Sie nur in einer Schleife sitzen und Texturen erstellen / löschen, erhält der Treiber möglicherweise keine Möglichkeit, tatsächlich etwas zu löschen.

Versuchen Sie, Ihren Test weniger künstlich zu machen. Fügen Sie glFinish nach jedem glDeleteTextures hinzu. Wenn das nicht funktioniert, zeichne Zeug zwischen Löschungen.

Letztendlich können Sie erzwingen Treiber nicht das tun, was Sie wollen. Alles, was Sie tun können, ist, dass sich Ihre Testanwendung mehr wie eine normale Anwendung verhält.

    
Nicol Bolas 01.12.2011 01:27
quelle
0

Da Ihr Fehler das GLU-Präfix hat, könnten Sie versuchen, das gleiche Programm auszuführen, ohne Mipmaps zu erstellen? [bereits erledigt] Ich glaube nicht, dass GLU_OUT_OF_MEMORY notwendigerweise bedeutet, dass Sie aus sind GPU-Speicher (in der Tat sind die Mipmaps wahrscheinlich auf der CPU gebaut), vielleicht leiden Sie unter Heap Fragmentierung . Die Tatsache, dass Sie den Fehler auf verschiedenen Windows-Rechnern mit sehr unterschiedlichen Grafikprozessoren erhalten, scheint darauf hinzudeuten, dass es sich nicht um ein spezifisches OpenGL-Treiberproblem handelt. Sie sind zu unterschiedlich zwischen den Anbietern.

Da Sie eine große Textur verwenden und nicht gluBuild2DMipmaps das Problem nicht löst, können Sie den GPU-Speicher für Ihre große (n) Textur (en) beim Starten der App vorab zuweisen und die Texturobjekte wiederverwenden mit glTexSubImage , anstatt neue beim erneuten Laden zu erstellen.

edit: Folgendes bietet keine Lösung (siehe Fragekommentare), ist aber meiner Meinung nach noch nützlich

Da du GLU_OUT_OF_MEMORY und nicht GL_OUT_OF_MEMORY bekommst, gehe ich davon aus, dass das Problem während der Mipmap-Erstellung mit gluBuild2DMipmaps auftritt. Da vielleicht die Glu-Funktion fehlerhaft ist, könnten Sie vielleicht versuchen, Ihre Mipmaps in einem Offline-Prozess zu erstellen und dann einfach in Create-Texture-from-file laden. Abgesehen davon, dass Sie möglicherweise Ihren Speichermangel beheben, können Sie dadurch die tatsächliche Mipmap-Generation viel besser steuern. Sie könnten zum Beispiel ein Gauss-Filter anstelle eines Box-Filters verwenden. Es würde auch identische mipmap-Inhalte für verschiedene Plattformen sicherstellen. Mein Verständnis ist, dass Mipmaps normalerweise so gehandhabt werden.

    
bernie 06.12.2011 16:47
quelle
0

Ich denke, Sie könnten versuchen, ein leeres Bild mit glTexImage2d / 3d zu der Textur zu verschieben, die Sie löschen möchten. Es funktionierte für mich mit VBOs - ich entferne die Daten von den Grafikkarten, indem ich mit glBufferData Pufferdaten lösche und ein leeres Array-Handle übergebe, weil die glDeleteBuffers die Daten nicht selbst entfernt haben.

    
spectre 13.02.2014 09:42
quelle

Tags und Links