PDA

View Full Version : Multi-threaded OpenGL Applications



MonoFocus
05-02-2010, 10:15 AM
Hi,

I have just used a fair amount of time debugging a multi-threaded OpenGL application, so I thought I would share a few steps on how to setup the GLRC that may save you a headache if you ever need to create a similar application with a dedicated rendering/worker thread:

1: The thread that creates the output window must also create the DC and GLRC (ie. do not attempt to create/get the DC and GLRC in the worker thread (WT) even if it has access to the HWND of the output window).

2: Make sure the DC and GLRC are available to the worker thread; either pass them as arguments when you created the thread or simply make them global, and have the WT make the GLRC current.

That's it! Enjoy multi-threading with OpenGL :)

PS: If you create the DC and GLRC in the WT it will actually work, but you will not be able to use extensions, so if you know you will never use functionality beyond OpenGL 1.1 (which is the version of the standard Windows implementation) go ahead and do so if this approach fits better into your program.

Jan
05-02-2010, 11:37 AM
You mean you create the window in the main thread (not the worker thread), but only do actual rendering from the worker thread (and not from the main thread) ?

But why should one not be able to use extensions, when creating the context in the worker thread? That makes no sense IMO.

Jan.

yooyo
05-02-2010, 02:59 PM
@MonoFocus:
Totally wrong. Usually I create window in UI thread and pass HWND to workerthread. WT read DC from HWND then create RC and initialise all extension.

MonoFocus
05-02-2010, 03:34 PM
I agree it sounds strange and that is exactly why I spend a lot of time spotting the error. I was primarily focusing on the system architecture so the WT just drew a spinning test triangle which indeed is possible with OpenGL 1.1.

However, whenever I tried to load extensions in the WT wglGetProcAddress returned NULL with error code 127 ("The specified procedure could not be found"). At that time the WT obtained the DC (using GetDC) from the main window's HWND and created the GLRC afterwards.

Then, I tried to create the HGLRC in the main thread instead (by simply moving 10 lines of code) and immediately everything was working! - plus the framerate went up from around 1100 to 9600 FPS! (Which also led me to suspect that the other/old way of doing it uses the standard Microsoft implementation)

Another guy replied that he doesn't have any problems when creating the GLRC in the WT, so maybe it depends on which OS you are using? (I'm using XP Pro)

MonoFocus
05-02-2010, 03:35 PM
Please read my reply to the other comment.

mhagain
05-06-2010, 02:38 PM
I believe it's more the case that you need to create the RC in the same thread as you create the window in (or more specifically the same thread as your WNDPROC runs in). It doesn't actually matter which thread, so long as they're both created in the same.

This is a D3D restriction too, which leads me to the conclusion that it's the underlying subsystems that are the source of it.

It can be very useful to know some D3D if you're doing OpenGL under Windows for this kind of reason...

Heiko
05-07-2010, 01:47 AM
My limited experiences with doing OpenGL in Windows (Vista 64 bits to be precise):

MT (main thread): create Window, setup pixel format, hand HDC to worker thread, run WNDPROC.

WT (worker thread): create OpenGL context using HDC from MT, retrieve wglCreateContextAttribsARB, create new context using the ARB function. Thereafter do all rendering.

yooyo
05-09-2010, 03:28 PM
Yes.. Im using that approach because I want to decouple my rendering loop from windows messaging. In UI thread im handling sizing, mouse and keyboard messages, and post specific messages to WT.