PDA

View Full Version : FBO and multiple threads



arithon
10-24-2007, 08:24 AM
Does anyone have any tips in order to get FBOs working with multiple threads?

After fighting with it for a while I decided to make it easy for me and do a simple test. The main thread first initializes the GL context and then does:


glGenFramebuffersEXT( 1, &_object );
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, _object );

GLboolean isValid = glIsFramebufferEXT( _object );isValid is true and I can call all other FBO-related functions. I then create a second thread, a compatible context and share the data, which basically boils down to calls to wglCreateContext, wglShareLists, wglCopyContext and wglMakeCurrent (this code is well tested and works with other tests).

Finally I perform the same code as above in the second thread and isValid is now false. In fact, all FBO-related functions are completely messed up. glCheckFramebufferStatusEXT for example returns zero, something it shouldn't do unless it generates and error, but glGetError then returns no error.

Anything specific I should keep in mind when dealing with FBOs and threads?

This is on a Windows XP system with a nVidia 8600 GTS card. Oh, and it works just as it should on my MacBook Pro with an ATI card.

Lindley
10-24-2007, 11:04 AM
I know GLEW contains some kind of multi-context support, but don't really understand the specifics. Could that be related?

speedy
10-24-2007, 01:06 PM
AFAIK, drawing from multiple threads with attached contexts can cause many different types of breakage because drivers are very poorly written in that regard.
There are code-paths which have better multi-thread testing coverage - background texture streaming comes to mind as one of the examples. :)

arithon
10-24-2007, 01:15 PM
Let me clarify: In this simple test case I'm not doing anything GL related whatsoever in the main thread after the initial FBO create code, and it still doesn't work in the second thread/context.

OneSadCookie
10-24-2007, 01:22 PM
Usual GL threading rules apply:
1) contexts are current per-thread, make sure you explicitly make the context current in the appropriate thread at the appropriate time
2) contexts are not thread-safe, make sure you only make GL calls on a given context from one thread at a time.

knackered
10-24-2007, 01:47 PM
2 is impossible if rule 1 is obeyed.
I think you mean that if you sharelists between two contexts, make sure only one thread at a time changes the shared resource.

V-man
10-24-2007, 06:01 PM
Are you sure wglShareLists is succeeding?
One of the problems I had long ago was creating some textures and VBOs in context 1, then create context 2 and call wglShareLists.
If I created both context and call wglShareLists, it succeeds.

OneSadCookie
10-24-2007, 08:25 PM
Originally posted by knackered:
2 is impossible if rule 1 is obeyed.Not at all... you've just got to be careful with your locks.


I think you mean that if you sharelists between two contexts, make sure only one thread at a time changes the shared resource. Changing the same resource from multiple threads should be fine; it's up to the driver to do the synchronization in that case. Of course, you're likely to hit a race condition where you don't know what your texture (or whatever) actually looks like if you're not careful...

Relic
10-25-2007, 03:24 AM
wglShareLists can fail if there are objects already created inside the main context you want to attach to.
Always share first, then create objects.

arithon
10-25-2007, 04:44 AM
Yeah, the share lists call is successful. And yes, only the second thread access any GL resources at the time I'm trying to setup my FBO in this simple test.

I'm bound to write this off to driver weirdness since I can do anything else GL-wise not related to FBO in the second thread without any problem.

yooyo
10-25-2007, 04:47 AM
Create all contexts, share data and then start thread and call wglMakeCurrent from thread func.

It is safe to create context in thread1 and pass context to thread2 for use. Just make sure that context is not current in thread1 before you pass it to thread2.