PDA

View Full Version : FBO synchronization



jastrother
08-06-2014, 06:56 PM
Hello,

I've been working on an opengl application and have come across a bug I can't seem to find, and was hoping someone who frequents this forum might be able to help. I've included a lot of detail below in case it is helpful, but the basic question is "how do you ensure that all drawing operations on an FBO have completed prior to trying to read out the FBO contents?"

Here are all the details. The application draws to an FBO, and then copies the contents of that FBO to the back buffer, then calls swap buffers. The bug is that when the window is resized there is flickering. It looks like the contents of the entire window are not being drawn for some frames but are instead being replaced by the background color. If I skip the FBO and write directly to the back buffer, then the bug goes away. If I open the application in gDEbugger and proceed frame by frame, then the bug goes away. In gDEbugger every frame looks perfect.

The bug seems to be associated with synchronizing the drawing to the FBO with reading from the FBO. In the original code, I didn't have anything explicit in the code to force the FBO to update prior to reading from it. When I added a glFinish() call things got a little better, but I still get occasional flickering. Nonetheless, the fact that things improved seemed like a clue that this is related.

Here is the list of calls that are performed on the frame just after resize as captured in gDEbugger:

/* stuff to resize the FBO */
glXMakeCurrent(0x0000000000654D90, 73400322, 0x00000000006F9440)
glBindFramebuffer(GL_FRAMEBUFFER, 1)
glBindRenderbuffer(GL_RENDERBUFFER, 1)
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, 640, 481)
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 1)
glCheckFramebufferStatus(GL_FRAMEBUFFER)
glBindFramebuffer(GL_FRAMEBUFFER, 0)
glViewport(0, 0, 640, 481)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(-0.5, 0.5, -0.37578124, 0.37578124, -1, 1)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()

/* empty the back buffer */
glClearColor(0, 0, 0, 0)
glClear(GL_COLOR_BUFFER_BIT)

/* draw to the FBO */
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 1)
glClearColor(0, 0, 0, 0)
glClear(GL_COLOR_BUFFER_BIT)
glDisable(GL_BLEND)
/* Draw stuff using combination of these calls:
glBindBuffer
glDrawElements
glUniform
glVertexAttrib
glEnableClientState
glVertexAttribPointer
glVertexPointer
glUseProgram
*/

/* copy FBO to the back buffer */
glEnable(GL_BLEND)
glBlendFunc(1, 1)
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0)
glBindFramebuffer(GL_READ_FRAMEBUFFER, 1)
glUseProgram(1)
glFinish()
glCopyPixels(0, 0, 640, 480, GL_COLOR)
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0)
glUseProgram(0)
glXSwapBuffers(0x0000000000654D90, 73400322)


Does anyone have any idea how one is supposed to synchronize drawing to an FBO with reading from the FBO? I've checked the documentation but I've come up empty.

Many thanks!

-Jim

Dark Photon
08-07-2014, 06:43 PM
You shouldn't have to do anything special for synchronization so, barring a bug in your driver, I'd suspect a bug in your code or something odd in the window manager configuration for your code.Y

First, you don't have a compositing window manager enabled, do you? If so, disable the compositor -- one less variable.

Clear your FBO to bright red and your back buffer to bright green each time. Now resize the window. Which clear color do you see?

I'd use glBlitFramebuffer, not glCopyPixels. Do you have the raster pos or pixel transfer modes setup properly, or even know what they are? If not, then definitely use glBlitFramebuffer.

Also, on resize (e.g. ConfigureNotify), are you immediately changing your off-screen FBO viewport that you're going to render to the next redisplay, and redrawing to that size on every subsequent redisplay until the next resize? Might double check that.