Objective c 顶点数组对象(VAO)可以在OpenGL ES中的EAGLContexts之间共享吗?

Objective c 顶点数组对象(VAO)可以在OpenGL ES中的EAGLContexts之间共享吗?,objective-c,ios,multithreading,opengl-es,eaglcontext,Objective C,Ios,Multithreading,Opengl Es,Eaglcontext,扰流器:我很有信心答案是否,但那只是在一天非常沮丧的调试之后。现在我想知道情况是否确实如此(如果是,我怎么可能知道),或者我只是在做一些完全错误的事情 情况是这样的。我正在使用OpenGL ES 2.0渲染从各种文件(.obj、.md2等)加载的一些网格。为了性能和用户体验,我使用GCD将这些网格及其相关纹理的实际加载委托给背景线程 根据,在每个后台线程上,我创建并设置一个新的EAGLContext,其shareGroup与主渲染上下文相同。这允许在后台线程上创建的OpenGL对象(如纹理和缓冲

扰流器:我很有信心答案是
,但那只是在一天非常沮丧的调试之后。现在我想知道情况是否确实如此(如果是,我怎么可能知道),或者我只是在做一些完全错误的事情

情况是这样的。我正在使用OpenGL ES 2.0渲染从各种文件(.obj、.md2等)加载的一些网格。为了性能和用户体验,我使用GCD将这些网格及其相关纹理的实际加载委托给背景线程

根据,在每个后台线程上,我创建并设置一个新的EAGLContext,其
shareGroup
与主渲染上下文相同。这允许在后台线程上创建的OpenGL对象(如纹理和缓冲区对象)立即被主线程上的上下文使用

这一切进展顺利。现在,我最近了解了一种缓存OpenGL状态的方法,该状态与呈现特定缓冲区的内容相关。它看起来不错,并且减少了渲染每个网格所需的样板状态检查和设置代码。最重要的是,苹果还建议在指南中使用它们

但我在让VAO为我工作方面遇到了严重的问题。就像所有加载一样,我会将网格从文件加载到后台线程的内存中,然后生成所有相关的OpenGL对象。毫无疑问,当我第一次尝试使用VAO调用
glDrawerElements()
时,应用程序在
EXC\u BAD\u访问时崩溃。如果没有VAO,它会变得很好

调试
EXC_BAD_ACCESS
是一件痛苦的事,特别是当NSZombies帮不上忙时(他们显然帮不上忙),但在分析捕获的OpenGL帧一段时间后,我意识到,虽然在后台线程上创建VAO很顺利(没有
GL_ERROR
,并且id非零),当绑定到主线程上的VAO时,我会得到一个
GL\u INVALID\u操作
,在尝试绑定到不存在的VAO时会出现这种状态。果然,在渲染时查看当前上下文中的所有对象时,不会看到单个VAO,但同时使用VAO生成的所有VBO都存在。如果我在主线程上加载VAO,它工作正常。非常令人沮丧

我将加载代码提炼为更原子的形式:

- (void)generate {

    glGenVertexArraysOES(1, &_vao);
    glBindVertexArrayOES(_vao);

    _vbos = malloc(sizeof(GLuint) * 4);
    glGenBuffers(4, vbos);
}
当在后台线程上执行上述操作时,使用与主上下文相同的有效
EAGLContext
,主上下文将有4个VBO,但没有VAO。如果我在主线程上使用主上下文执行它,它将有4个VBO和VAO。这让我得出结论,在处理VAO时,
EAGLContext
s的对象共享特性存在一些奇怪的异常。如果真是这样的话,我真的希望苹果的文档会注意到这一点。要用手去发现那样的小道消息是很不方便的。是这样,还是我遗漏了什么?

根据,OpenGL ES明确禁止共享VAO对象:

顶点数组对象是否可以跨多个OpenGL ES共享 上下文

解决方案:否。OpenGL ES工作组进行了一次民意测验,结果 同意与OpenGL的兼容性和易实现性 比创建第一个非共享命名对象更重要 在OpenGLES中


正如您所指出的,VBO仍然是可共享的,因此您只需为绑定共享VBO的每个上下文创建一个VAO。

啊,太好了。那只是我要找的晦涩难懂的文档。很高兴知道这是预期的行为。谢谢,太好了。我在后台加载资源,但所有的几何体都是基于VAO的,所以我决定只加载背景中的纹理,并在主线程上生成几何体。我一定喜欢那些黄鼠狼的话。。。“我们将永远破坏后台加载(几何体可能非常庞大),因此我们不必在驱动程序中实现新的/更好的代码”;)。我刚刚艰难地找到了答案;-)