gpt4 book ai didi

android - 为什么不能从另一个线程调用 OpenGL ES 函数

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:07:15 27 4
gpt4 key购买 nike

我正在尝试使用 OpenGL ES 为 Android 编写一个小型游戏引擎。我创建了一个 Game Thread 来更新游戏对象,并使用 GLThread 绘制场景。我读过你需要在 GLSurfaceView 的 onSurfaceCreated 方法中加载纹理。我正在关注它,但出于某些调试目的,我试图从我的游戏线程而不是 GLThread 加载纹理。我没有出错,纹理也没有显示在屏幕上。我花了一整天的时间试图找出问题所在,最后我阅读了下面的 here

“只要确保只在主线程中使用 OpenGL。”很重要。您不能在游戏引擎(可能在另一个线程中)中调用不与 gl 线程同步的纹理加载函数。在那里设置一个标志来通知您的 gl 线程加载新纹理(例如,您可以在 OnDrawFrame(GL gl) 中放置一个函数来检查是否必须加载新纹理。

我将修改我的代码,以便从 GL 线程加载纹理。我只是不明白为什么会这样?为什么 OpenGL 函数在另一个线程中不起作用?

我知道如何创建线程,但我不知道同步是什么意思。上面的摘录提到,“你不能在你的游戏引擎(可能在另一个线程中)中调用一个与 gl 线程不同步的纹理加载函数。”所以我猜我的游戏线程可能与 GL 线程不同步。是否可以创建另一个与 GL 线程同步的线程,以便从中调用 GL 函数?我应该在线程中学习什么才能理解这些概念?

最佳答案

我认为 quixoto 的评论最接近。 OpenGL 上下文在几乎每个平台上都是线程特定的传统原因是 OpenGL 严重依赖于状态并且没有使一系列更改原子化的语义。因此,例如,一个线程上的绘制操作可能是:

glVertexPointer(... supply vertex positions ...)
glTexCoordPointer(... provide texture positions ...)
/* and supply a few other pointers, maybe bind a texture */

glDrawArrays(... draw some geometry ...)

因此,最终调用仅在前面调用的上下文中提供可预测的结果。如果您允许那段代码在例如 glVertexPointer 之后暂停,另一个线程跳入并执行大致相同的序列来绘制其几何图形,然后继续执行此代码,它将以相当大的速度绘制错误的几何形状,如果一些被替换的数组小于原始数组,甚至可能导致越界内存访问。

Android 提供 EGL,它支持 OpenGL 共享组的通用概念(尽管是隐含的;您提供一个现有上下文,您希望新上下文通过 eglCreateContext 的第三个参数位于一个通用组中)。如果两个上下文在一个共享组中,那么它们中的每一个都有一个独立的状态,并且可以安全地从一个线程中调用,但是命名对象(例如纹理或顶点缓冲对象)对它们中的每一个都是可用的。因此,使用共享组,您可以同时在多个线程上执行 OpenGL 操作,以便能够在单个线程上合并结果。

因此,将上下文绑定(bind)到单个线程并不是什么大问题。在 OpenGL 本身中规划这个问题也不是一个开始,因为 OpenGL 上下文以特定于操作系统的方式创建、管理和处理的部分原因是一些操作系统需要以与其他操作系统完全不同的方式处理这些东西或者能够通过展示自己独特的解决方案来提供更好的解决方案。

关于android - 为什么不能从另一个线程调用 OpenGL ES 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7879224/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com