asynchrones laden (opengl)



  • Hey,

    ich bin gerade dabei ein kleinen platformer zu bauen und bisher klappt auch alles. Da es langsamm merkliche ladezeiten gibt wollte ich eine art ladescreen machen, welcher angezeigt wird wärend im hintergrund in nem anderen thread die spielscene geladen wird. Was ich dabei nicht bedacht hatte ist, das ich nur in dem thread opengl objekte erstellen/benutzen darf der opengl initialisiert hat. Jetzt hab ich aber das problem das ich einmal die scene hab die meine ladeanimation zeigt wärend ich in einem anderen thread gerne die spielscene zusammen bauen möchte. Mir fehlt jetzt ein ansatz wie ich das sinnvoll regeln könnte. Mommentan laden alle objekte im spiel ihre eigenen ressourcen, so das ich auch nicht wirklich eine große liste hab, die ich im voraus laden kann. Und selbst wenn ich die hätte könnte ich ja keinen "flüssigen" übergang machen da trozdem die opengl objekte mit den daten die ich geladen hab initialisiert werden müßten. Wie habt ihr das geregelt?



  • Mir fehlt jetzt ein ansatz wie ich das sinnvoll regeln könnte.

    1. Möglichkeit: Du lädst nur die Daten von der Festplatte asynchron. Die Eigentliche Initialisierung der Objekt machst du dann im OpenGL Thread.
    2. Möglichkeit: Du benutzt mehr als nur einen OpenGL Context. Mit einem zeichnest du dann, mit dem anderen lädts du dann die Daten.
    AFAIK: Mit hilfe von wglCreateContextAttribsARB kannst du einen zweiten OpenGL Kontext erstellen der seine Daten mit dem anderen Teilt. (Zumindest unter Windows)

    Wie habt ihr das geregelt?

    DirectX 11, da ist das einfacher 🙂

    Zu wglCreateContextAttibsARB:
    http://www.opengl.org/registry/specs/ARB/wgl_create_context.txt#wglCreateContextAtribsARB

    floorball



  • Hmm bisher hatte ich context/window creation mit glfw weggekapselt, das jetzt selber zu machen oder glfw zu erweitern wär doch ein bischen viel aufwand. Dann läufts wohl darauf hinnaus das man nochmal kurz warten muss bis die opengl ressourcen erstellt wurden. Alles nicht so tolle lösungen 😞



  • Hi,

    es gibt eine weitere Möglichkeit. Du mappst deine Buffers im GL Thread und füllst sie in einen anderen Thread. In diesem Fall ist kein zweiter Context notwendig. Du musst dann aber von Hand mit glFenceSync und glClienWaitSync synchronisieren.

    Schau dir am Besten dieses kostenlose Probekapitel aus dem Buch OpenGL Insights an. Eine weitere wertvolle Quelle ist das OpenGL Wiki. Dort dürften dich folgende Artikel interessieren: Buffer Object sowie Buffer Object Streaming.

    Es gibt auch eine sehr gute Präsentation von Nvidia zur OpenGL Performance Optimierung. Dort wird auch das Thema "Buffer Storage" angesprochen. Vortragsvideo: Youtube Link, Folien: pdf pptx

    Das ganze geht aber schon etwas über dein Problem hinaus. Dort geht es hauptsächlich um Streaming also nachladen von Resourcen bei Bedarf, beziehungsweise Generierung dieser On-the-fly.


  • Mod

    floorball schrieb:

    Mir fehlt jetzt ein ansatz wie ich das sinnvoll regeln könnte.

    1. Möglichkeit: Du lädst nur die Daten von der Festplatte asynchron. Die Eigentliche Initialisierung der Objekt machst du dann im OpenGL Thread.

    das halte ich auch fuer das beste. laden von der festplatte laeuft mit (wenn man noch dekomprimiert) zwischen ein paar hunder KB/s bis vielleicht 50MB/s, wobei da noch zugriffzeiten dazu kommen usw. wohingegen du vermutlich 8GB/s vom ram zur graka hochladen kannst, meistens nutzt du bei weitem keine 2GB graka ram, gerade bei einem platformer wuerde ich mit ein paar hundert MB im worst case ausgehen. du wirst also im bruchteil einer sekunde (vermutlich <100ms) fertig sein mit dem kopieren.
    es macht also nicht soviel sinn dass du viel aufwand treibst wegen openGL, lade einfach nur die daten von der HDD ins ram im zweiten thread und kopiere danach im opengl thread alles kurz hoch.



  • Du könntest SDL2 verwenden oder im Quellcode abgucken. Damit kann man relativ einfach OpenGL Kontexte erzeugen die sich Ressourcen Teilen.

    Wie jedoch schon erwähnt wurde, lohnt sich der Aufwand eher nicht.



  • Ich hab' mir auch sinnloserweise die Arbeit gemacht das Resourcen-Laden (inklusive Upload!) "threadable" zu machen.
    Nachdem es mein Framework-Code jetzt schon kann verwende ich es auch, aber der eigentliche Upload geht wirklich so flott, dass ich mir den ganzen Aufwand hätte sparen können.
    Das schlimmste dabei ist nichmal dass ich dafür 1-2 Tage Arbeit investieren musste, sondern dass es den ganzen Resource-Management Code unnötig kompliziert macht.

    Es rauszureissen wäre aber auch wieder ein nicht unerheblicher Aufwand, also bleibt es jetzt erstmal so.


  • Mod

    haettest du vorher mal lieber das nette forum hier konsultiert 🤡

    hast du etwas was corss platform funzt oder pro vendor bzw OS ?



  • Nur Windows, nur D3D9.
    Mit D3D ist der multi-threaded Upload zwar viel einfacher als mit OGL hinzubekommen. Dass es kaum was bringt haben aber wohl alle Systeme gemeinsam, von daher dachte ich ich erwähn es trotzdem hier.



  • Dann werd ichs wohl mit den erst laden dann initialisieren machen, scheint ja doch ganz gut zu gehen, danke 🙂


Log in to reply