Spoiler:我非常确信答案是NO
,但这只是经过一天非常沮丧的调试之后。现在我想知道是否确实如此(如果是这样,我可能知道的话),或者我是否只是做了一些完全错误的事情。
这是情况。我正在使用OpenGL ES 2.0来渲染我从各种文件(.obj,.md2等)加载的一些网格物体。为了性能和用户体验,我使用GCD将这些网格及其相关纹理的实际加载委托给后台线程。
每个Apple's instructions,在每个后台线程上,我创建并设置一个与主渲染上下文具有相同shareGroup
的新EAGLContext。这允许在后台线程上创建的OpenGL对象(如纹理和缓冲区对象)立即被主线程上下文使用。
这一直在努力。现在,我最近了解了Vertex Array Objects作为缓存与呈现某些缓冲区内容相关联的OpenGL状态的方法。它看起来不错,并减少了样板状态检查和设置渲染每个网格所需的代码。最重要的是,Apple还建议在Best Practices for Working with Vertex Data指南中使用它们。
但是我在让VAO为我工作时遇到了严重的问题。就像我对所有加载一样,我会将网格从文件加载到后台线程的内存中,然后生成所有关联的OpenGL对象。没错,我第一次尝试使用VAO拨打glDrawElements()
时,应用程序崩溃了EXC_BAD_ACCESS
。没有VAO,它就会很好。
调试EXC_BAD_ACCESS
很痛苦,特别是当NSZombies无法帮助时(他们显然不会这样做),但经过一段时间分析捕获的OpenGL帧后,我意识到,在创建VAO时后台线程很好(没有GL_ERROR
,并且是一个非零的id),当主线程上绑定到VAO的时候,我会得到一个GL_INVALID_OPERATION
,{{3}尝试绑定到不存在的VAO时会发生状态。当然,在渲染时查看当前上下文中的所有对象时,没有一个VAO可以看到,但是所有使用VAO生成的VBO AT THE存在相同时间 。如果我在主线程上加载VAO它可以正常工作。很沮丧。
我将加载代码提炼为更原子的形式:
- (void)generate {
glGenVertexArraysOES(1, &_vao);
glBindVertexArrayOES(_vao);
_vbos = malloc(sizeof(GLuint) * 4);
glGenBuffers(4, vbos);
}
当在后台线程上执行上述操作时,使用与主上下文具有相同EAGLContext
的有效shareGroup
,主上下文将具有4个VBO,但没有VAO。如果我在主线程上执行它,使用主上下文,它将有4个VBO和VAO。这使我得出结论:在处理VAO时EAGLContext
的对象共享性质存在一些奇怪的例外。如果确实如此,我真的希望Apple文档能够在某处注明。不得不手动发现这样的小花絮是非常不方便的。是这样的,还是我错过了什么?
答案 0 :(得分:21)
根据this,OpenGL-ES明确禁止共享VAO对象:
顶点数组对象应该可以跨多个OpenGL ES共享 上下文
决议:不会.OpenGL ES工作组进行了一次民意调查 同意与OpenGL的兼容性和易于实现 比创建第一个非共享命名对象更重要 在OpenGL ES中。
正如您所指出的,VBO仍然是可共享的,因此您只需为绑定共享VBO的每个上下文创建一个VAO。