【发布时间】:2011-08-19 17:33:24
【问题描述】:
剧透:我相当有信心答案是NO,但这只是在经过一天非常沮丧的调试之后。现在我想知道情况是否确实如此(如果是,我可能怎么知道),或者我只是做错了什么。
情况是这样的。我正在使用 OpenGL ES 2.0 来渲染从各种文件(.obj、.md2 等)加载的一些网格。为了性能和用户体验,我将这些网格及其相关纹理的实际加载委托给使用 GCD 的后台线程。
根据Apple'sinstructions,在每个后台线程上,我创建并设置了一个新的EAGLContext,其shareGroup 与主渲染上下文相同。这允许在后台线程上创建的 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,在尝试绑定时会发生the docs 状态到一个不存在的VAO。果然,在渲染时查看当前上下文中的所有对象时,没有看到单个 VAO,但是所有使用 VAO 生成的 VBO AT THE SAME TIME在场。如果我在主线程上加载 VAO,它工作正常。非常令人沮丧。
我将加载代码提炼成更原子的形式:
- (void)generate {
glGenVertexArraysOES(1, &_vao);
glBindVertexArrayOES(_vao);
_vbos = malloc(sizeof(GLuint) * 4);
glGenBuffers(4, vbos);
}
当上述在后台线程上执行时,具有相同shareGroup的有效EAGLContext作为主上下文,主上下文将有4个VBO,但没有VAO。如果我在主线程上执行它,使用主上下文,它将有 4 个 VBO 和 VAO。这使我得出结论,在处理 VAO 时,EAGLContexts 的对象共享性质存在一些奇怪的例外。如果情况确实如此,我真的希望 Apple 文档会在某处注意到这一点。不得不用手去发现这样的小花絮是非常不方便的。是这样吗,还是我错过了什么?
【问题讨论】:
-
我刚刚找到了答案 ;-)
标签: objective-c ios multithreading opengl-es eaglcontext