我有一个应用程序需要执行以下操作:
我有那么多工作。
接下来,我希望能够将步骤#2移动到单独的共享GL上下文中。
在初始化时,我创建了一个共享上下文:
rootContext = CGLGetCurrentContext();
CGLPixelFormatObj pf = CGLGetPixelFormat(rootContext);
CGLCreateContext(pf, rootContext, &childContext);
...然后将其设置为当前并在其上设置帧缓冲...
CGLSetCurrentContext(childContext);
glGenTextures(1, &childTexture);
glBindTexture(GL_TEXTURE_2D, childTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glGenFramebuffers(1, &childFramebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, childFramebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, childTexture, 0);
然后,当渲染每一帧时,我将childContext
设为当前并呈现给它:
CGLSetCurrentContext(childContext);
glBindFramebuffer(GL_FRAMEBUFFER, childFramebuffer);
glUseProgram(childProgram);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, inputTexture);
glUniform1i(childTextureUniform, 0);
glBindBuffer(GL_ARRAY_BUFFER, childQuadPositionBuffer);
glVertexAttribPointer(childPositionAttribute, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*2, (void*)0);
glEnableVertexAttribArray(childPositionAttribute);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, childQuadElementBuffer);
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, (void*)0);
glDisableVertexAttribArray(childPositionAttribute);
glUseProgram(0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
...然后我将rootContext
设为当前并将FBO的纹理渲染到屏幕:
CGLSetCurrentContext(rootContext);
glUseProgram(rootProgram);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, childTexture); // This texture was created and populated on childContext.
glUniform1i(rootTextureUniform, 0);
glBindBuffer(GL_ARRAY_BUFFER, rootQuadPositionBuffer);
glVertexAttribPointer(rootPositionAttribute, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*2, (void*)0);
glEnableVertexAttribArray(rootPositionAttribute);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, rootQuadElementBuffer);
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, (void*)0);
glDisableVertexAttribArray(rootPositionAttribute);
glUseProgram(0);
如果我发表CGLSetCurrentContext(childContext);
次来电,则完全。
但是,如果我切换到共享上下文渲染到FBO,我会看到屏幕上呈现出毛刺的垃圾,好像什么都没有渲染到childTexture
上一样:
......这真的很酷,但我想在这里找到更多的现实主义美学。
关于在使用共享上下文时如何使其工作的任何想法?
CGLError
- 没有错误;它已成功创建。glGetError()
- 没有错误。glCheckFramebufferStatus()
- 它是GL_FRAMEBUFFER_COMPLETE
。glBindTexture(GL_TEXTURE_2D, 0);
通话后拨打glDisableVertexAttribArray()
。没有变化。我创建了2个简单的测试应用程序,它们都表现出同样的问题:
答案 0 :(得分:7)
无法在上下文之间共享帧缓冲区对象(FBO)。 Only data carrying objects (textures, buffer objects, etc) are shared。抽象对象,即仅绑定其他对象和管理状态的对象(帧缓冲对象,顶点数组对象)不是。
因此,绑定您在其他上下文中创建的FBO不起作用。 BUT 你可以在辅助上下文中创建一个FBO,并将纹理对象从主要上下文绑定为颜色附件就好了。
如果FBO目标纹理在主要上下文中作为纹理源绑定,则可能会出现另一个问题,同时它也应该用作渲染目标。我实际上并不确定OpenGL规范对这种情况所说的^ 1(我必须深入研究规格大概是我们左右的一半),但我猜驱动程序可能会认为这是一种情况,纹理不能被FBO瞄准。因此,我建议您使用互斥锁或信号量来同步主线程中纹理的绑定/解绑定与辅助线程中FBO的绑定。
1: EDIT OpenGL规范说,可以在光栅化操作中获取片段的纹理层不能同时用作FBO渲染目标;但OpenGL规范中的措辞并未明确考虑共享上下文。但我很确定,受共享上下文约束并且可以随时获取,可以满足此约束条件。在我自己的项目中,如果我在这种情况下实现这样的事情,我会自动实现双缓冲或三缓冲方案,并在从缓冲区(n+1)%M
获取数据时渲染缓冲区n%M
。
答案 1 :(得分:3)
我完成了它,对上面的示例代码进行了2次更改:
glViewport()
glFlushRenderAPPLE();