Jump to content
  • Advertisement
Sign in to follow this  
Floating

OpenGL OpenGL and multi-threaded applications...

This topic is 4865 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, I know that OpenGL doesn't support multiple threads and I try to keep all rendering in one single thread. However there a cases where I want a working thread to prepare and create a texture for the rendering thread. First I forgot about the fact that OpenGL doesn't support multiple threads and my textures appeared in white.. it took ages to find out where the error came from. How I solve the problem now is create a data structure in my working thread that describes what needs to be created and then set a flag for the rendering thread to create the requested object. That works fine, however I feel that this is not an elegant solution (depending on what needs to be created a whole bunch of parameters are needed). Is there some way where I can block my rendering thread (with a simple flag), switch the OpenGL context to a different thread, do the job there and then switch back to my rendering thread? That would be very convenient. Thanks :)

Share this post


Link to post
Share on other sites
Advertisement
Quote:
Original post by Floating
Hi,

I know that OpenGL doesn't support multiple threads and I try to keep all rendering in one single thread. However there a cases where I want a working thread to prepare and create a texture for the rendering thread. First I forgot about the fact that OpenGL doesn't support multiple threads and my textures appeared in white.. it took ages to find out where the error came from.
How I solve the problem now is create a data structure in my working thread that describes what needs to be created and then set a flag for the rendering thread to create the requested object. That works fine, however I feel that this is not an elegant solution (depending on what needs to be created a whole bunch of parameters are needed). Is there some way where I can block my rendering thread (with a simple flag), switch the OpenGL context to a different thread, do the job there and then switch back to my rendering thread? That would be very convenient.

Thanks :)



Is there any specific reason that you wish to use threads in a case like the above. Graphics/Rendering dont thread well for various reasons and I would suggest against using them (fine for physics, AI, etc if you need it) but they'll probably slow down your rendering quite a bit.

In any case have a look at sempaphores (can used for synchronization) and maybe the producer/consumer pattern.

HTH

Share this post


Link to post
Share on other sites
Thank you for your reply nts,

Rendering is in my case only secondary. If it halts from time to time this is not important at all. Threads are critical in my case since there is socket communication, serial communication, etc. and basically the application is a server application that gets commands from another application. Synchronisation between threads is not my problem, I just want to be able to use thread A and thread B in turn for rendering purposes (or rather thread A will always render, but thread B will create new objects to render (like textures)).

Share this post


Link to post
Share on other sites
OpenGL does support multithreading; however, only one thread can access a context at a time, so each thread will need it's own thread. See MSDN KB Q128122 for an example using wgl (I assume you're using Windows-- if not, it can be done with glX, agl, etc. as well, but obviously the particular methods will be different)

It's worth noting, though, that since the threads use different contexts, a context switch overhead occurs since they are almost definitely using a graphics card. That is, the driver serializes the calls, with added context switch overhead, so don't expect to get blistering performance gains on most architectures (at least not yet). However, for the situation you've described of loader threads, this solution is quite nice. I use it in my engine.

Hope this helps,
-bodisiw

Share this post


Link to post
Share on other sites
The only hard rule is that only one thread can have a context selected at a time. You can deselect the context, and select it another thread though. If you set up the context to use shared display list you ought to be able to share other resources as well (otherwise how could the shared display list work?).

I started working on this, but never took it to completion. I was focusing on having a seperate rendering thread from the windows message pump at the time.

Switching OGL contextes is very expensive; you have to employ a monitor syncronization scheme so that you only (de)select when you absolutely must.

Share this post


Link to post
Share on other sites
Thank you for the quick replies.

I tried it but now somehow my main thread can't get the control back...
Here is how I switch between threads:

Rendering thread:
wglMakeCurrent(NULL,NULL);
sleepUntilWakingUpFlagSet();
wglMakeCurrent(hDC,hRC);


Working thread:
wglMakeCurrent(hDC,hRC);
DoSomeOpenGLStuff();
wglMakeCurrent(NULL,NULL);
setWakingUpFlag()

In both cases hDC and hRC are the same (the ones created at the beginning of the application by the rendering thread).
What am I doing wrong?

Share this post


Link to post
Share on other sites
If you're not too fussed about performance you could do it as follows using a mutex;


mutextype mutex;

// rendering thread
mutex.lock(); // lock the mutex or wait until we can
wglMakeCurrent(hDC,hRC); // get the rendering context
renderstuff();
wglMakeCurrent(NULL,NULL); // release rendering context
mutex.release();

// worker thread
mutex.lock()
wglMakeCurrent(hDC,hRC);
DoSomeOpenGLStuff();
wglMakeCurrent(NULL,NULL);
mutex.release();



You can ofcourse put some flags in place to prevent it aquring the context when its not needed.

The other option would be a simple signal system, so your code would be more like;


// rendering thread
while(!rendertime){ sleep(0);}
wglMakeCurrent(hDC,hRC); // get the rendering context
renderstuff();
wglMakeCurrent(NULL,NULL); // release rendering context
rendertime = false;

// worker thread
wglMakeCurrent(hDC,hRC);
DoSomeOpenGLStuff();
wglMakeCurrent(NULL,NULL);
rendertime = true;
while(rendertime){ sleep(0);}



very basic syncing system, but it should do the trick.
Just make sure before you kick your worker off that rendertime = false and that the main thread has given up the context.

You could go more over the top with slots and signals , but thats just over kill [wink]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!