Kein OpenGL-Kontext im aktuellen Thread gefunden

8

Ich benutze LibGDX um ein Spiel zu machen. Ich möchte Assets bei Bedarf gleichzeitig laden / entladen. Das Warten auf das Laden von Assets im Hauptthread verursacht jedoch Verzögerungen. Um dies zu beheben, habe ich einen Hintergrund-Thread erstellt , der überwacht, welche Assets geladen werden müssen (Texturen, Sounds usw.) und sie entsprechend lädt / entlädt.

Leider erhalte ich den folgenden Fehler beim Aufruf von AssetManager.update() von diesem Thread.

%Vor%

Ich habe versucht, den Hintergrundthread im Hauptthread am Anfang zu bearbeiten und nur mit den ersten paar Screens zu arbeiten, und alles funktioniert gut. Ich kann den Algorithmus auch ändern, um alles von Anfang an im selben Thread in den Speicher zu laden, und das funktioniert auch. Beide funktionieren jedoch nicht im Hintergrundthread.

Wenn ich dies unter Android mit OpenGL ES 2.0 (das auf seltsame Weise flexibel ist) anstelle von Windows ausführe, läuft alles gut, und ich kann sogar die Pixelmaße der Bilder abrufen - , aber die Texturen werden schwarz gerendert .

Meine Suchanfragen haben mir gezeigt, dass dies ein Problem des OpenGL-Kontexts ist, der an einen einzelnen Thread gebunden ist, aber nicht viel anderes. Das erklärt, warum alles funktioniert, wenn ich es in den Hauptthread schiebe, und nicht, wenn ich es in einen anderen Thread lege. Wie behebe ich dieses Kontextproblem?

    
GraphicsMuncher 24.04.2013, 22:20
quelle

1 Antwort

9

Als Erstes sollten Sie nicht außerhalb des Render-Threads auf den OpenGL-Kontext zugreifen.

Ich nehme an, Sie haben sich diese bereits angesehen, aber Sie müssen sich nur den AssetManager Wiki-Artikel , das ein wenig darüber spricht, wie der AssetManager für die asynchrone Verwaltung von Assets verwendet wird. Schauen Sie sich zusätzlich zum Wiki-Artikel die AssetManagerTest um besser zu verstehen, wie man es benutzt. Der Asset-Manager-Test ist wahrscheinlich die beste Lösung beim Laden, wie Assets dynamisch geladen werden können.

Wenn Sie eine Menge Material laden, möchten Sie vielleicht eine Ladeleiste erstellen, um etwas Großes im Voraus zu laden. Es könnte funktionieren, Assets und solche aus einem anderen Thread zu prüfen (und ein Flag setzen, um ein Update aufzurufen), aber am Ende des Tages müssen Sie update () im Rendering-Thread.

Wenn man bedenkt, dass man update () von einem anderen Thread aufrufen muss, sehe ich nicht, warum ein anderer Thread die Bedingungen überprüfen und ein Flag setzen sollte. Wahrscheinlich gibt es mehr Overhead, wenn Sie einen anderen Thread verwenden und den update () -Aufruf synchronisieren, anstatt alles im Rendering-Thread zu tun. Außerdem wird die update () -Methode nur für jeweils einige Millisekunden angehalten, wenn Dateien inkrementell geladen werden. Normalerweise würden Sie einfach load () für Ihr Asset, dann überprüfen Sie isLoaded () auf Ihrem Asset. Wenn es nicht geladen ist, würden Sie update () einmal pro Frame aufrufen, bis isLoaded () true zurückgibt. Sobald es wahr zurückgibt, können Sie dann get () und lade jedes Asset, das du geladen hast. Dies kann alles über den Hauptrendering-Thread erfolgen, ohne dass die App während des Ladens verzögert wird.

Wenn Sie möchten, dass Ihr anderer Thread update () aufruft, müssen Sie ein Runnable Objekt und rufe postRunnable () , wie sie im Wiki-Artikel auf Threading mit libGDX. Dies verhindert jedoch den ganzen Sinn der Verwendung anderer Threads, da alles, was Sie mit postRunnable verwenden, synchron auf dem Rendering-Thread ausgeführt wird.

    
Jyro117 24.04.2013, 23:02
quelle