【问题标题】:No OpenGL context found in the current thread在当前线程中找不到 OpenGL 上下文
【发布时间】:2024-01-22 18:39:01
【问题描述】:

我正在使用 LibGDX 制作游戏。我想根据需要同时加载/卸载资产。但是,等待资产在主线程中加载会导致延迟。为了解决这个问题,我创建了一个后台线程,它监控需要加载哪些资产(纹理、声音等)并适当地加载/卸载它们。

不幸的是,我在从该线程调用AssetManager.update() 时收到以下错误。

com.badlogic.gdx.utils.GdxRuntimeException: java.lang.RuntimeException: No OpenGL context found in the current thread.

我一开始就在主线程中尝试runing 后台线程,只处理前几个屏幕,一切正常。我还可以更改算法,在同一个线程中从一开始就将所有内容加载到内存中,这也很有效。但是,两者都不能在后台线程中工作。

当我在 Android 上使用 OpenGL ES 2.0(以奇怪的方式灵活)而不是在 Windows 上运行它时,一切运行良好,我什至可以获得图像的像素尺寸 - 但纹理呈现黑色

我的搜索告诉我,这是 OpenGL 上下文 绑定到单个线程的问题,但其他问题不大。这就解释了为什么当我把它推到主线程时一切正常,而不是当我把它放在另一个线程中时。如何解决这个上下文问题?

【问题讨论】:

    标签: multithreading opengl-es opengl-es-2.0 libgdx


    【解决方案1】:

    首先,您不应该在渲染线程之外访问 OpenGL 上下文。

    我假设您已经看过这些,但只是为了确保阅读AssetManager wiki article,其中谈到了如何使用 AssetManager 进行资产的异步管理。除了 wiki 文章,查看 AssetManagerTest 以更好地了解如何使用它。资产管理器测试可能是您了解如何动态加载资产的最佳选择。

    如果您要加载大量内容,您可能需要考虑创建一个加载栏来预先加载任何大型内容。从另一个线程检查资产等可能会起作用(并设置一个标志来调用更新),但最终您需要在渲染线程上调用update()

    请记住,您必须从不同的线程调用 update() 它,我不明白为什么您希望另一个线程检查条件并设置标志。使用另一个线程和同步 update() 调用可能比仅在渲染线程上完成所有这些开销更多。此外,update() 方法在增量加载文件时每次只暂停几毫秒。通常,您只需为您的资产调用load(),然后在您的资产上检查isLoaded()。如果未加载,您将每帧调用一次 update(),直到 isLoaded() 返回 true。一旦它返回 true,您就可以调用 get() 并获取您正在加载的任何资产。这一切都可以通过主渲染线程完成,而不会在加载时出现应用延迟。

    如果你真的希望你的其他线程调用 update(),你需要创建一个 Runnable 对象并调用 postRunnable(),例如他们在使用 libGDX 的多线程的wiki article 中如何描述它。但是,这会破坏使用其他线程的全部意义,因为您在 postRunnable 中使用的任何内容都会在渲染线程上同步运行。

    【讨论】:

    • -1 错误地说明 OpenGL 上下文不能从多个线程中使用。完全可以从一个线程中分离 OpenGL 上下文并将其附加到另一个线程。
    • 如何在多线程意义上使用上下文将上下文分离和附加到另一个线程?上下文本身一次只能由单个线程访问,除非您想尝试使用锁定来实现它。然而,这违背了整个观点。
    • 您确实声称只能从渲染线程使用 OpenGL 上下文,这意味着只有创建上下文的线程才能使用它。顺便说一句:您可以使用共享对象命名空间在同一个可绘制对象上创建多个 OpenGL 上下文,并将每个上下文附加到自己的线程。这为您提供了多线程。
    • 我明白你在说什么,它是可能的并且有它的用途,但是对于 libGDX 的这个特殊问题,我不建议这样做。我会更新我的答案。
    最近更新 更多