AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi glDeleteTextures gibt Speicher nicht frei
Thema durchsuchen
Ansicht
Themen-Optionen

glDeleteTextures gibt Speicher nicht frei

Ein Thema von EWeiss · begonnen am 23. Mai 2008 · letzter Beitrag vom 21. Jul 2008
Antwort Antwort
Seite 1 von 3  1 23      
EWeiss
(Gast)

n/a Beiträge
 
#1

glDeleteTextures gibt Speicher nicht frei

  Alt 23. Mai 2008, 05:58
trotz alledem das ich die texturen lösche wird der Speicher nicht freigegeben


Delphi-Quellcode:
    if assigned(quadTexture) then
    begin
      for I := 0 to QuadCount - 1 do
      begin
       glDeleteTextures(i, @quadTexture);
       quadTexture[i] := 0;
      end;
    end;

    glDeleteTextures(1, @BackTexture); // Texture für Hintergrund
    glDeleteTextures(1, @GradientTex); // Texture für DiskSpectrum
    glDeleteTextures(1, @MeterTexture); // Texture für VUMeter
    glDeleteTextures(1, @PeaksTexture); // Texture für Peaks
    glDeleteTextures(1, @SpectrumTexture); // Texture für Spectrum
    glDeleteTextures(1, @BarTexture); // Texture für Slider
    glDeleteTextures(1, @PrivateTexture); // Texture für CDLabel
woran kann es liegen ?
Wüßte jetzt nicht was da falsch ist.

gruss Emil
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#2

Re: glDeleteTextures gibt Speicher nicht frei

  Alt 23. Mai 2008, 06:56
Moin Emil,

unabhängig von irgendwelchen Speicherfreigaben - müsste das nicht eher so aussehen?

Delphi-Quellcode:
begin
  if Assigned(QuadTexture) then
  begin
    glDeleteTextures(Length(QuadTexture), @QuadTexture[Low(QuadTexture)]);
    SetLength(QuadTextures, 0);
  end;
  if Assigned(BackTexture) then
    // ...
end;
Ich habe jetzt mal dynamische Texture-Arrays angenommen.

Freundliche Grüße
  Mit Zitat antworten Zitat
Benutzerbild von Corpsman
Corpsman

Registriert seit: 8. Nov 2005
Ort: nähe Stuttgart
981 Beiträge
 
Delphi XE2 Professional
 
#3

Re: glDeleteTextures gibt Speicher nicht frei

  Alt 23. Mai 2008, 07:16
@EWeiss

dir ist aber schon klar das deine Texture Variablen Pointer sind, oder ?

Das heist.

Wenn du eine Varaible

var b:TBitmap; hast. dann kannst du B.free machen , und gibst den speicher frei.


Die Abfrage

Delphi-Quellcode:
if assigned(b) then begin
end;
würde aber immer noch True ergeben, da b.free sich selbst nicht auf NIL setzt.

Genau das selbe ist es mit den OpenGL Texturen

als Test.

Gib deine Textur an einem Punkt frei nachdem du noch rendern kannst. ( also meinetwegen direkt wieder nach dem Laden )

dann stellst du fest das OpenGL dir stattdessen

1. Blödsinn
oder
2. eine weise Textur anzeigt

=> der speicher wurde freigegeben.
Uwe
My Sitewww.Corpsman.de

My marble madness clone Balanced ( ca. 70,0 mb ) aktuell ver 2.01
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#4

Re: glDeleteTextures gibt Speicher nicht frei

  Alt 23. Mai 2008, 10:36
@marabu
Dynamisches Array ist ok
hab dann wohl einen Denkfehler
Hab nicht daran gedacht das ganze Array auf einmal zu löschen.


werd mal schaun ob es dann freigegeben wird.

Delphi-Quellcode:
begin
  if Assigned(QuadTexture) then
  begin
    glDeleteTextures(Length(QuadTexture), @QuadTexture[Low(QuadTexture)]);
    SetLength(QuadTextures, 0);
  end;
  if Assigned(BackTexture) then
    // ...
end;
@Corpsman
Zitat:
dir ist aber schon klar das deine Texture Variablen Pointer sind, oder ?
Hmmm...
warum sollte es das nicht sein die Trexture ist ein Pointer auf GLUnit 'PGlUint'

quadTexture : array of GLuint; ist ein dynamisches array auf gluint da ist nix mit 'free'

EDIT:
Auch wenn ich das Array(Texturen) in einem zug frei gebe steigt die Speicherbelastung stetig..

gruss Emil
  Mit Zitat antworten Zitat
Benutzerbild von littleDave
littleDave

Registriert seit: 27. Apr 2006
Ort: München
556 Beiträge
 
Delphi 7 Professional
 
#5

Re: glDeleteTextures gibt Speicher nicht frei

  Alt 23. Mai 2008, 11:42
Woran erkennst du denn, dass die Texturen nicht freigegeben werden? Dem Arbeitsspeicher kannst du das eigentlich nicht ansehen, da die Texturen im Grafikkarten-RAM gespeichert werden. Wenn der Grafikkarten-Speicher voll ist, werden die Texturen dann in den Arbeitsspeicher geschoben, aber sonst nicht.

Noch was zu deinem Code
Delphi-Quellcode:
if assigned(quadTexture) then
begin
  for I := 0 to QuadCount - 1 do
  begin
    glDeleteTextures(i, @quadTexture);
    quadTexture[i] := 0;
  end;
end;
Dieser Code funktioniert nicht. glDeleteTextures erwartet zwei Parameter. Der erste Parameter sagt OGL, wieviele Texturen gelöscht werden sollen. Der zweite Parameter ist ein Pointer auf das erste Element eines glUint-arrays (wenn nur eine Textur gelöscht werden soll, dann muss es kein array sein).
Dein Code von oben müsste man also folgendermaßen umschreiben (nur wenn du ihn mit der for-schleife benutzen willst)
Delphi-Quellcode:
if assigned(quadTexture) then
begin
  for I := 0 to QuadCount - 1 do
  begin
    glDeleteTextures(1, @quadTexture[i]);
    quadTexture[i] := 0;
  end;
end;
//Edit:
Ach noch was: sind die anderen Variablen zufällig auch arrays? Wenn du den Pointer auf das erste Element eines arrays zurückgeben willst, würd ich das immer so machen:
@NameDesArrays[0]
Jabber: littleDave@jabber.org
in case of 1 is 0 do external raise while in public class of object array else repeat until 1 is 0
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#6

Re: glDeleteTextures gibt Speicher nicht frei

  Alt 23. Mai 2008, 11:51
Zitat:
Woran erkennst du denn, dass die Texturen nicht freigegeben werden? Dem Arbeitsspeicher kannst du das eigentlich nicht ansehen, da die Texturen im Grafikkarten-RAM gespeichert werden. Wenn der Grafikkarten-Speicher voll ist, werden die Texturen dann in den Arbeitsspeicher geschoben, aber sonst nicht.
Danke für deine Antwort

Ich erkenne es daran das nach etwa 20 Titeln die Anwendung 150MB speicher belegt
Beim start sind es 30MB und es steigt stetig wenn das Album sich ändert
und die Texturen neu eingeladen werden.

Zitat:
Dieser Code funktioniert nicht. glDeleteTextures erwartet zwei Parameter. Der erste Parameter sagt OGL, wieviele Texturen gelöscht werden sollen. Der zweite Parameter ist ein Pointer auf das erste Element eines glUint-arrays (wenn nur eine Textur gelöscht werden soll, dann muss es kein array sein).
Ja hast du recht .. war ein flüchtigkeits fehler
Habe ja oben die einzelnen Texturen auch mit
glDeleteTextures(1, @BackTexture); // Texture für Hintergrund 1 gelöscht.

Die schleife ansich macht das gleiche wie marabus vorschlag.
Nur seiner ist eleganter kann mir die schleife dann sparen.

EDIT:
Zitat:
Ach noch was: sind die anderen Variablen zufällig auch arrays? Wenn du den Pointer auf das erste Element eines arrays zurückgeben willst, würd ich das immer so machen:
Nein sind einzelne Texturen.

gruss Emil
  Mit Zitat antworten Zitat
Benutzerbild von littleDave
littleDave

Registriert seit: 27. Apr 2006
Ort: München
556 Beiträge
 
Delphi 7 Professional
 
#7

Re: glDeleteTextures gibt Speicher nicht frei

  Alt 23. Mai 2008, 12:26
Ich glaube, dass das Problem nicht bei glDeleteTextures liegt. Ich glaube, es liegt er daran, dass du die Texturdaten nach dem Laden nicht freigibst.

Normalerweise schaut das Laden einer Textur ungefähr so aus
Delphi-Quellcode:
glEnable(GL_TEXTURE_2D);
glGenTextures(1, @Texture);
glBindTexture(GL_TEXTURE_2D, Texture);
// Textur mit Daten füllen
glTexImage2D(GL_TEXTURE_2D, 0, 3, 512, 512, 0, GL_RGB, GL_UNSIGNED_BYTE, pTexData);
(die einzelnen Parameter sind jetzt mal beliebig gewählt)

In pTexData befinden sich jetzt die einzelnen RGB-Werte der Textur (in diesem Beispiel 768 KB). Diese Daten solltest du nach dem Laden wieder freigeben. Am besten mit FreeMem(pTexData);. Sonst spuken diese Daten im RAM herum, obwohl du sie nicht mehr brauchst.
Jetzt ist auch noch die Frage, wie du die Texturdaten aus der Datei in den Speicher bekommst (also pTexData mit RGB-Daten füllst). Wenn du z.B. TBitmap verwendest kann es noch sein, dass du die Instanz TBitmap nicht mehr freigibst.

Das ist jetzt alles nur eine Vermutung. Was du auch noch machen kannst: schau dir mal die Werte an, die die einzelnen Textur-Indizes haben (in meinem Beispiel den Wert von Texture). Soweit ich beobachtet habe sucht OpenGL den niedrigsten freien Wert und setzt ihn dann in die Variable. Wenn die Werte jetzt immer größer werden, werden die Texturen vielleicht nicht freigegeben. Ich bin mir da aber überhaupt nicht sicher, ob das überhaupt funktionierten kann.
Jabber: littleDave@jabber.org
in case of 1 is 0 do external raise while in public class of object array else repeat until 1 is 0
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#8

Re: glDeleteTextures gibt Speicher nicht frei

  Alt 23. Mai 2008, 12:42
Ich lade sie so..

Delphi-Quellcode:
    if Assigned(QuadTexture) then
    begin
      glDeleteTextures(Length(QuadTexture), @QuadTexture[Low(QuadTexture)]);
      SetLength(QuadTexture, 0);
    end;

    glDeleteTextures(1, @BackTexture); // Texture für Hintergrund
    glDeleteTextures(1, @GradientTex); // Texture für DiskSpectrum
    glDeleteTextures(1, @MeterTexture); // Texture für VUMeter
    glDeleteTextures(1, @PeaksTexture); // Texture für Peaks
    glDeleteTextures(1, @SpectrumTexture); // Texture für Spectrum
    glDeleteTextures(1, @BarTexture); // Texture für Slider
    glDeleteTextures(1, @PrivateTexture); // Texture für CDLabel

    if assigned(aCovers) then
     aCovers.Free;

    // Lade Cover für Quader
    aCovers := TStringList.Create;
    if CoverPath <> 'then
    begin
      if CoverPath <> Path then
        ScanDirectory(CoverPath, 'bmp, tga, jpg', True);

      tmpC := 0;
      if (aCovers.count <= QuadCount) then
      begin
        for i := 0 to aCovers.count-1 do
        begin
          if (ExtractFileName(AnsiLeftStr(aCovers.Strings[i], Length(aCovers.Strings[i]) - 4)) = 'COVER')
            or (ExtractFileName(AnsiLeftStr(aCovers.Strings[i], Length(aCovers.Strings[i]) - 4)) = 'CDLABEL') then
            begin
              if FileExists(Path + UpperCase('Data\images\CompDisk\Default\NoCover.jpg')) then
                LoadTexture(Path + 'Data\images\CompDisk\Default\NoCover.jpg', quadTexture[i], False);
              dec(tmpC);
            end else
            begin
              LoadTexture(aCovers.Strings[i], quadTexture[tmpC], False);
            end;
            inc(tmpC);

        end;

        if (QuadCount >= (aCovers.count - 1)) then
        begin
          for q := (aCovers.count - 1) to QuadCount do
            if FileExists(Path + UpperCase('Data\images\CompDisk\Default\NoCover.jpg')) then
              LoadTexture(Path + 'Data\images\CompDisk\Default\NoCover.jpg', quadTexture[q-1], False);
        end;
        exit;
      end;


      tmpA := 0;
      if (aCovers.count >= QuadCount) then
      begin
        for i := 0 to aCovers.count-1 do
        begin
          if (ExtractFileName(AnsiLeftStr(aCovers.Strings[i], Length(aCovers.Strings[i]) - 4)) = 'COVER')
            or (ExtractFileName(AnsiLeftStr(aCovers.Strings[i], Length(aCovers.Strings[i]) - 4)) = 'CDLABEL') then
            begin
              if FileExists(Path + UpperCase('Data\images\CompDisk\Default\NoCover.jpg')) then
                LoadTexture(Path + 'Data\images\CompDisk\Default\NoCover.jpg', quadTexture[i], False);
              dec(tmpA);
            end else
            begin
              if (tmpA) <= QuadCount-1 then
                LoadTexture(aCovers.Strings[i], quadTexture[tmpA], False);
            end;
            inc(tmpA);
          end;

          if (QuadCount >= (aCovers.count - 1)) then
          begin
          for q := (aCovers.count - 1) to QuadCount do
            if FileExists(Path + UpperCase('Data\images\CompDisk\Default\NoCover.jpg')) then
              LoadTexture(Path + 'Data\images\CompDisk\Default\NoCover.jpg', quadTexture[q-1], False);
          end;
      end;
    end;
aCovers ist ne TStringList

Ok kann man besser machen
Das laden funktioniert ja lediglich das freigeben nicht

Zum laden benutze ich den Textureloader von Sulaco

gruss Emil
  Mit Zitat antworten Zitat
Benutzerbild von littleDave
littleDave

Registriert seit: 27. Apr 2006
Ort: München
556 Beiträge
 
Delphi 7 Professional
 
#9

Re: glDeleteTextures gibt Speicher nicht frei

  Alt 23. Mai 2008, 13:21
Ok, der Texturloader vom Jan Horn sollte nicht das Problem sein, den hab ich früher auch verwendet.
Ich glaube, du lädst die Texturen doppelt. Die if-Abfragen
Delphi-Quellcode:
if (aCovers.count <= QuadCount) then
// ...
if (aCovers.count >= QuadCount) then
überlagern sich, falls aCovers.Count = QuadCount ist. Außerdem: kann es ein, dass du aCovers nicht mehr freigibst (oder hast du das aCovers.Free einfach nur nicht mit in den Post kopiert)?

Ich würd die Lade-Routine mal umschreiben, im Moment ist die noch relativ umständlich:

Delphi-Quellcode:
if FileExists(Path + UpperCase('Data\images\CompDisk\Default\NoCover.jpg')) then
   LoadTexture(Path + 'Data\images\CompDisk\Default\NoCover.jpg', NoCoverTexture, False)
else
   NoCoverTexture := 0;

aCovers := TStringList.Create;
try
  if CoverPath <> Path then
     ScanDirectory(CoverPath, 'bmp, tga, jpg', True);

  aFilledQuads := 0;
  for i:=0 to aCovers.Count-1 do
  begin
    // den Dateinamen extrahieren
    aFileName := ExtractFileName(aCovers[i]);
    // die Dateiendung abscheiden
    aFileName := Copy(aFileName, 1, length(aFileName) - length(ExtractFileExt(aFileName)));
    // Upper-Case machen
    aFileName := AnsiUpperCase(aFileName);

    if (aFileName = 'COVER') or (aFileName = 'CDLABEL') then
    begin
      LoadTexture(aCovers[i], quadTexture[i], False);
    end else
      QuadTexture[i] := NoCoverTexture;

    inc(aFilledQuads);
    
    // Schleife beenden, falls alle Elemente von quadTexture gefüllt sind
    if i >= High(quadTexture) then
       break;
  end;
 
  // Falls noch ein paar ungefüllte Quads übrig sind, werden die auch noch mit der
  // NoCoverTexture gefüllt
  for i:=aFilledQuads to High(quadTexture) do
    QuadTexture[i] := NoCoverTexture;
finally
  aCovers.Free;
end;
Keine Garantie auf Korrektheit, hab den Quelltext ohne offene IDE geschrieben
Jabber: littleDave@jabber.org
in case of 1 is 0 do external raise while in public class of object array else repeat until 1 is 0
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#10

Re: glDeleteTextures gibt Speicher nicht frei

  Alt 23. Mai 2008, 13:30
Zitat:
überlagern sich, falls aCovers.Count = QuadCount ist. Außerdem: kann es ein, dass du aCovers nicht mehr freigibst (oder hast du das aCovers.Free einfach nur nicht mit in den Post kopiert)?
Steht oben
Zitat:
if assigned(aCovers) then
aCovers.Free;
Werde deine Routine mal testen.
Danke!

aCovers.free darf in Finaly nicht freigegeben werden da später im Code noch verwendet
Erst bei erneuten aufruf wenn neue Cover eingeladen werden.

gruss Emil
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:26 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz