AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Beschleunigung von Laderoutine

Ein Thema von EWeiss · begonnen am 15. Aug 2016 · letzter Beitrag vom 17. Aug 2016
Antwort Antwort
Seite 3 von 3     123   
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.060 Beiträge
 
Delphi 10.4 Sydney
 
#21

AW: Beschleunigung von Laderoutine

  Alt 16. Aug 2016, 15:40
Zitat:
Warum lädst und erzeugst du die Texturen für jedes Abspielen eines einzelnen Songs neu?
Tue ich ja nicht nur am Anfang irgendwie muss ich ja mein QuadTexture Array mit Daten füllen.

Ist das Album im Karussell enthalten wird nichts geladen da im Array QuadTextures vorhanden.
Warum?
Behalte doch einfach die OpenGL-Texture während der Laufzeit des Plug-Ins?
Wenn ich das richtig verstehe, schmeißt du ja die Texturen weg, sobald die Grenze von (aCovers.count > QuadCount) überschritten ist.
Der Flaschenhals ist ja das übertragen des JPEG-Bildes auf das Bitmap-Bild.
Hier kannst du übrigens ein paar Zeilen einsparen:

Anstatt:
Delphi-Quellcode:
  // Create Bitmap
  BMP := TBitmap.Create;
  BMP.pixelformat := pf32bit;
  BMP.Width := JPG.Width;
  BMP.Height := JPG.Height;
  BMP.canvas.draw(0, 0, JPG); // Copy the JPEG onto the Bitmap
Kannst du auch das schreiben:
Delphi-Quellcode:
  BMP := TBitmap.Create;
  BMP.Pixelformat := pf32bit;
  BMP.Assign(JPG);
Es würde viel zu lange dauern 1000 Alben beim Start in ein Dictionary einzulesen und dann zu vergleichen wenn ein neuer Titel abgespielt wird.
Musst ja nicht beim Start über den ganzen Root-Ordner suchen, hat auch keiner vorgeschlagen.
Das Vergleichen mit den neuen Titel/Albumpfad ist übrigens super schnell per TDictonary.

Ich tue nichts anderes nur die Texture abspeichern halte ich für unnötig.
Wäre doch aber sinnvoller, da das neuladen ja anscheinend deine Performance-Bremse ist.

Letztendlich ist das auch nur ein *.jpg oder anderer typ.
Warum soll ich diese dann abspeichern wenn sie schon im Albums Pfad vorhanden ist.
Ich glaube du hast das falsch verstanden. Nicht abspeichern im Sinne von "auf die Festplatte schreiben" sondern abspeichern im Sinne von: im Arbeitsspeicher halten! Siehe TDictionary.
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#22

AW: Beschleunigung von Laderoutine

  Alt 16. Aug 2016, 15:51
Kannst mir das mal als Beispiele auf meine Routine übertragen?
So das ich das mal testen kann.

Ich bin mir auch nicht sicher ob D2010 TDictionary unterstützt (Habe es vorher noch nicht verwendet.)
Ok gibt es..

Zitat:
im Arbeitsspeicher halten! Siehe TDictionary.
Ah jo so wie ich sie im Array halte..

Zitat:
Behalte doch einfach die OpenGL-Texture während der Laufzeit des Plug-Ins?
Die frage wäre dann hier wie lange macht der Speicher das mit wenn ich innerhalb von 5 > 6 Stunden die ganzen Covers lade und im Speicher halte.

Das!
Delphi-Quellcode:
  BMP := TBitmap.Create;
  BMP.Pixelformat := pf32bit;
  BMP.Assign(JPG);
geht nicht.
Danach wird mein Plugin einfach beendet.

gruss

Geändert von EWeiss (16. Aug 2016 um 18:04 Uhr)
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.060 Beiträge
 
Delphi 10.4 Sydney
 
#23

AW: Beschleunigung von Laderoutine

  Alt 17. Aug 2016, 10:38
Kannst mir das mal als Beispiele auf meine Routine übertragen?
So das ich das mal testen kann.
Du pflegst ja eher einen struktuierten Programmierstil, daher so:

Delphi-Quellcode:
...

uses
  System.Generics.Collections;

...

var
  EWeissCoverDictionary: TDictionary<string, GLuint>;

procedure Construct;
begin
  EWeissCoverDictionary := TDictionary<string, GLuint>.Create;
end;

procedure LoadCovers(const CoverPath: string; out Texture: GLuint);
begin
  if not EWeissCoverDictionary.TryGetValue(CoverPath, Texture) then
  begin
    LoadTexture(CoverPath, Texture, False);
    EWeissCoverDictionary.Add(CoverPath, Texture);
  end;
end;

procedure MachKaputtWasEuchKaputtMacht;
var
  Texture: GLuint;
begin
  for Texture in EWeissCoverDictionary.Values do
  begin
    glDeleteTextures(1, @Texture);
  end;
  EWeissCoverDictionary.Free;
end;
Das!
Delphi-Quellcode:
  BMP := TBitmap.Create;
  BMP.Pixelformat := pf32bit;
  BMP.Assign(JPG);
geht nicht.
Danach wird mein Plugin einfach beendet.
Haste dir schonmal nen try-except darum gebastelt und dir die Exception.Message ausgeben lassen?
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#24

AW: Beschleunigung von Laderoutine

  Alt 17. Aug 2016, 11:42
Zitat:
EWeissCoverDictionary
Cool so bin ich verewigt.

Werde es mir mal anschauen danke für das Beispiel.
Obwohl ich eigentlich mit dem aktuellen Stand zufrieden bin.
Hab das Teil im Hintergrund so ca. 5 Stunden laufen lassen.
Keine Probleme und der speicherverbrauch liegt so bei 48 MB.

EDIT:
Habe mir da mal angeschaut.

Letztendlich ist es so das es keinen sinn macht alle Covers incl. Texturen zu speichern.
Im habe maximal 25 Cover im Karussell wird das 26 Geladen dann wird das erste gelöscht
die anderen rücken dann nach und das 25 ist das aktuell spielende Album.
Wenn ich das erste Cover lösche welchen sinn macht es dann dieses gespeichert zu lassen
es kann aus dem Plugin dann nicht mehr abgespielt werden.

Der sinn des Karussell ist das man ein beliebiges Album nochmals spielen kann.
Ein gelöschtes Album kann man aber nicht mehr spielen von daher muss ich es auch nicht abspeichern
weder im Array, Dictionary noch in einer Datei.

Trotz allem ist schon interessant.

gruss

Geändert von EWeiss (17. Aug 2016 um 12:13 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#25

AW: Beschleunigung von Laderoutine

  Alt 17. Aug 2016, 14:06
Bei der von mir vorgeschlagenen Lösung würdest du jeweils maximal 25 Texturen behalten, aber müsstest trotzdem immer nur Eine neu laden.

Init:
Delphi-Quellcode:
InsertIndex := 0;
for I := Low(TextureArray) to High(TextureArray) do
begin
  TextureArray[I] := NoCoverTexture;
end;
Neues Album laden:
Delphi-Quellcode:
if (TextureArray[InsertIndex] <> NoCoverTexture) then
begin
  DeleteTexture(TextureArray[InsertIndex]);
end;
LoadTexture(Pfad, TextureArray[InsertIndex]);
Inc(InsertIndex);
if (InsertIndex = Length(A)) then
begin
  InsertIndex := Low(A);
end;
Zeichnen vom Carousel:
Delphi-Quellcode:
for I := InsertIndex to High(TextureArray) do
begin
  RenderTexture(TextureArray[I]);
end;
for I := Low(TextureArray) to InsertIndex - 1 do
begin
  RenderTexture(TextureArray[I]);
end;
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.060 Beiträge
 
Delphi 10.4 Sydney
 
#26

AW: Beschleunigung von Laderoutine

  Alt 17. Aug 2016, 17:01
Letztendlich ist es so das es keinen sinn macht alle Covers incl. Texturen zu speichern.
Im habe maximal 25 Cover im Karussell wird das 26 Geladen dann wird das erste gelöscht
die anderen rücken dann nach und das 25 ist das aktuell spielende Album.
Wenn ich das erste Cover lösche welchen sinn macht es dann dieses gespeichert zu lassen
es kann aus dem Plugin dann nicht mehr abgespielt werden.
Lösche doch einfach nicht???
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#27

AW: Beschleunigung von Laderoutine

  Alt 17. Aug 2016, 18:42

Lösche doch einfach nicht???
Warum?

Wie soll ich dann das nächste Album addieren wenn das Maximum erreicht ist?
Was soll ich mit einem Cover das keine Verwendung mehr findet?
Warum soll ich unnötiger weise den Speicher mehr belasten als nötig?

gruss
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#28

AW: Beschleunigung von Laderoutine

  Alt 17. Aug 2016, 19:06
Zitat:
Bei der von mir vorgeschlagenen Lösung würdest du jeweils maximal 25 Texturen behalten, aber müsstest trotzdem immer nur Eine neu laden.
Danke das tut meine Version auch.. Trotz allem Danke für dein Beispiel.

Beim Start werden all Texturen mit NoCoverTexturen befüllt.
Delphi-Quellcode:
    // fill all Quads with NoCoverTexture
    if FileExists(FullDataPath + 'images\Default\NoCover.JPG') then
    begin
      LoadTexture(FullDataPath + 'images\Default\NoCover.JPG', NoCoverTexture, False);

      for q := 0 to QuadCount - 1 do
        quadTexture[q] := NoCoverTexture;
    end
    else
      NoCoverTexture := 0;
Anschließend wird die INI eingeladen.
Delphi-Quellcode:
procedure LoadINI;
var
  I: Integer;
  str: string;
  tmpList: TStringList;

begin

  tmpList := TStringList.Create;
  try
    With AlbumIni do
    begin
      aCovers.Clear;
      CoverCount := StrToInt(ReadString('AlbumCover', 'Count', '0'));
      if CoverCount > 0 then
      begin
        for I := 0 to CoverCount - 1 do
        begin
          str := ReadString('AlbumCover', 'Folder' + IntToStr(I), '');
          if (Length(str) > 0) then
            if FileExists(str) then
              aCovers.Add(str)
            else
              tmpList.Add(str);
        end;
      end;
    end;
  finally
    if tmpList.count > 0 then
    begin
      AlbumIni.EraseSection('AlbumCover');
      for I := 0 to aCovers.count - 1 do
        AlbumIni.WriteString('AlbumCover', 'Folder' + IntToStr(I), aCovers.strings[I]);
    end;

    tmpList.Free;
  end;

  AlbumIni.Free;

end;
In aCovers stehen jetzt alle 25 Pfade zu den Album Covers.
Jetzt werden all NoCoverTexturen mit den vorhandenen Covers gefüllt.

Delphi-Quellcode:
          if (aFileName = 'FOLDER') or (aFileName = Name) then
          begin
            if quadTexture[I] = NoCoverTexture then
              LoadTexture(aCovers[I], quadTexture[I], False);
            // add to List
            LstCoverPath.Add(aCovers[I]);
          end;
Und hier wird jetzt nur noch 1 Cover geladen..
Delphi-Quellcode:
      if (aCovers.count > QuadCount) then
      begin
        // delete first Cover
        aCovers.Delete(0);
        // move textures from destination to source
        for I := 0 to (aCovers.count - 1) do
        begin
          quadTexture[I] := quadTexture[I + 1];
          // add to List
          LstCoverPath.Add(aCovers[I]);
          // Load last Testure
          if I = (QuadCount - 1) then
          begin
            // extract Filename
            aFileName := ExtractFileName(aCovers[I]);
            // extract extension
            aFileName := Copy(aFileName, 1, Length(aFileName) - Length(ExtractFileExt(aFileName)));
            // uppercase
            aFileName := AnsiUpperCase(aFileName);

            Name := ExtractFileName(GetAlbumArtistName);
            if Name <> 'then
              Name := Copy(Name, 1, Length(Name) - Length(ExtractFileExt(Name)));
            if (aFileName = 'FOLDER') or (aFileName = Name) then
            begin
              if quadTexture[I] <> NoCoverTexture then
                glDeleteTextures(1, @quadTexture[I]);

              LoadTexture(aCovers[I], quadTexture[I], False);
            end;
          end;
        end;
      end
Der erste Eintrag in der Liste für die Pfade zu den Cover Bildern wird geöscht.
aCovers.Delete(0);

Hier werden die Texturen verschoben
quadTexture[I] := quadTexture[I + 1];

Jetzt wird die Liste zu den Cover Bildern aktualisiert
LstCoverPath.Add(aCovers[I]);

Wenn I das gleiche wie Maximaler Cover Count -1 dann wird die letzte Texture gelöscht
glDeleteTextures(1, @quadTexture[I]);

und nur noch einmalig für dieses Album geladen
LoadTexture(aCovers[I], quadTexture[I], False);

Das geht schnell ohne merklichen Performance Verlust.

Ich weiß das Rendern von dir ist nur ein Beispiel aber da steckt im Original einiges mehr an Funktionen drin
Delphi-Quellcode:
procedure RenderAlbum(aDeltaTime: single);
// Diese Funktion zeichnet die Quader. ColorScale skaliert dabei die Farbwerte der oberen beiden Ecken
procedure DrawQuads();
var
  I: Integer; // index der for-schleife
  QuadAngle: single; // die Rotation des aktuellen Quads
  aPos: TGLVectord3; // die finale Position des aktuellen Quads [aPos = array[0..2] of single]
begin

  glEnable(GL_TEXTURE_2D);

  glInitNames;
  glPushName(0);

  // alle Quads durchgehen
  for I := 0 to QuadCount - 1 do
  begin

    // Position initialisieren (aPos[0] = 0, aPos[1] = 0, aPos[2] = 10)
    aPos := Vector_Make3f(0, 0, 12);

    // Die Rotation des Quads (um den Mittelpunkt des Kreises, der durch die Quads gebildet wird)
    // + ListAnge, also die Rotation, die mit der Maus gemacht wird
    QuadAngle := DegToRad(360 / (QuadCount) * I) + ListAngle;

    // Den Positionvektor um den Mittelpunkt des Kreises um die Y-Achse rotieren
    aPos := Vector_Rotatef3(aPos, Vector_Make3f(0, 0, 0), QuadAngle, False, True, False);

    glBindTexture(GL_TEXTURE_2D, quadTexture[I]);

    if I = CurrentQuad then
    begin
      // Jetzt brauchen wir Blending
      glEnable(GL_BLEND);
      // nun die Blending-Funktion setzen
      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
      glColor4f(1, 1, 1, 0.7);
      // move to foreground
      StayOnTop(aPos, 1.5);
      // show only available cover
      if not(quadTexture[I] = NoCoverTexture) then
      begin
        win.IMGTexture := quadTexture[I];
        win.bRenderGUI := True;
      end;
    end
    else
    begin
      // Original Farben setzen
      glColor4f(1, 1, 1, 1);
      // Blenden ausschalten
      glDisable(GL_BLEND);
    end;

    if not(LastAddCover = Round(NoCoverTexture)) then
      if LastAddCover = Trunc(quadTexture[I]) then
      begin
        glColor3f(1.0, 1.0, 1.0);
        glDisable(GL_TEXTURE_2D);
        // rahmen zeichnen
        glLineWidth(1);
        glBegin(GL_LINE_LOOP);
        glVertex3f(aPos[0] - QuadSizeS, aPos[1] + QuadSizeS * 2, aPos[2]);
        glVertex3f(aPos[0] - QuadSizeS, aPos[1], aPos[2]);
        glVertex3f(aPos[0] + QuadSizeS, aPos[1], aPos[2]);
        glVertex3f(aPos[0] + QuadSizeS, aPos[1] + QuadSizeS * 2, aPos[2]);
        glEnd;
        glEnable(GL_TEXTURE_2D);

        // Quad zeichnen
        glBegin(GL_QUADS);
        glTexCoord2f(0, 1);
        glVertex3f(aPos[0] - QuadSizeS, aPos[1] + QuadSizeS * 2, aPos[2]);
        glTexCoord2f(0, 0);
        glVertex3f(aPos[0] - QuadSizeS, aPos[1], aPos[2]);
        glTexCoord2f(1, 0);
        glVertex3f(aPos[0] + QuadSizeS, aPos[1], aPos[2]);
        glTexCoord2f(1, 1);
        glVertex3f(aPos[0] + QuadSizeS, aPos[1] + QuadSizeS * 2, aPos[2]);
        glEnd();
      end;

    // Quad zeichnen
    glBegin(GL_QUADS);
    glTexCoord2f(0, 1);
    glVertex3f(aPos[0] - QuadSize, aPos[1] + QuadSize * 2, aPos[2]);
    glTexCoord2f(0, 0);
    glVertex3f(aPos[0] - QuadSize, aPos[1], aPos[2]);
    glTexCoord2f(1, 0);
    glVertex3f(aPos[0] + QuadSize, aPos[1], aPos[2]);
    glTexCoord2f(1, 1);
    glVertex3f(aPos[0] + QuadSize, aPos[1] + QuadSize * 2, aPos[2]);
    glEnd();

    glLoadName(I + 1);
  end;
  glPopName;

end;

begin

  glDepthMask(ByteBool(GL_TRUE));

  // Kamera ausrichten, damit man was sieht
  glTranslatef(0, -7, -30);

  // Maus verarbeiten
  if FMousePos.X > 0 then
  begin
    if FMousePos.X < 30 then
      ListAngle := ListAngle - pi / 4 * aDeltaTime
    else if FMousePos.X > _FNormal.Image1.Width - 30 then
      ListAngle := ListAngle + pi / 4 * aDeltaTime;
  end;

  // Wichtig für die Spiegelung
  glDisable(GL_CULL_FACE);

  glEnable(GL_BLEND);
  // Jetzt spiegel wir alles an der x-z-Ebene
  glScalef(1, -1, 1);
  // Jetzt zeichnen wir zuerst die Reflektionen der Quads
  DrawQuads();

  glDisable(GL_BLEND);
  // Dann spiegel wir wieder zurück
  glScalef(1, -1, 1);
  // und zeichnen die eigentlichen Quads
  DrawQuads();

  // Jetzt brauchen wir Blending
  glEnable(GL_BLEND);
  // nun die Blending-Funktion setzen
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

  glBegin(GL_QUADS);
  glColor4f(0.0, 0.0, 0.0, 0.7);
  glVertex3f(-15, 0, 15);
  glVertex3f(-15, 0, -15);
  glVertex3f(15, 0, -15);
  glVertex3f(15, 0, 15);
  glEnd();
  glDisable(GL_BLEND);

  glLoadIdentity;

end;

gruss

Geändert von EWeiss (17. Aug 2016 um 19:21 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 3 von 3     123   


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 16:44 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