Multithreading problem

When I test on SIS integrated video card then the the thread that I use for rendering hangs when it executes opengl commands.
It is strange but the program works with other video cards fine.

Maybe there are some rules that I should follow writing multithreaded opengl application (windows)
Please give me a reference to such app’s.
Thanks

Read the manual for wglMakeCurrent: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/opengl/ntopnglr_2u0k.asp

Download the (stoneaged) GLthread.exe sample source package: http://support.microsoft.com/default.aspx?scid=kb;en-us;128122

Warning: This is just a dumb sample. Don’t create a new context so often.

If the SIS system runs with Microsoft’s OpenGL implementation, I think there are some multithreading bugs in it and I wouldn’t trust a driver from SIS either.

I’ve had a game which crashed some time after startup on a sis card only.
But upgrading to the latest driver solved it. So you may want to upgrade too :
http://download.sis.com/

As I understand it (someone please correct me if I’m wrong):

-if you are using the same context on different threads (each thread calls wglMakeCurrent() on the context when it wants to use it), you need to put a synchronization lock around your context to ensure that two threads don’t try to make it current at the same time

-if you are using different contexts on different threads, you don’t have to worry about synchronization at all, with the following provisio…

You still need to worry about synchronization for OpenGL objects though. If you are loading a texture on one thread and then using it in another, you need for the second thread to wait until the first is finished loading it.

You’ll also want to look into wglShareLists().

OpenGL support in general is pretty iffy on smaller brands.

I wouldn’t even try to make THREADED OpenGL work right on anything but the top tier vendors. Life is too short.

Originally posted by Stephen_H:
[b]As I understand it (someone please correct me if I’m wrong):

-if you are using the same context on different threads (each thread calls wglMakeCurrent() on the context when it wants to use it), you need to put a synchronization lock around your context to ensure that two threads don’t try to make it current at the same time

-if you are using different contexts on different threads, you don’t have to worry about synchronization at all, with the following provisio…
[/b]
For Windows OSes…

For any rendering context, one and only one thread can be made current with that context. For any thread, one and only one context can be made current to that thread. Once a context is current with a thread, subsequent requests to make current by another thread will fail and that thread will more than likely not be current with any context. Context swapping can be expensive.

One thread should be designated as the “main” thread and be responsible for all buffer swapping. Also it is important that all contexts be finished prior to any buffer swap – otherwise expect to lose or drop “in-transit” requests. Eventhough OpenGL contexts are thread-safe, GDI objects (e.g., HDC - device context handles) are not. Since GDI objects are not thread-safe, the use of CS_OWNDC styled windows can result in graphic anomalies or missing data since all calls to GetDC(HWND) return the same non-thread-safe HDC.

– tim

One thread should be designated as the “main” thread and be responsible for all buffer swapping. Also it is important that all contexts be finished prior to any buffer swap – otherwise expect to lose or drop “in-transit” requests. Eventhough OpenGL contexts are thread-safe, GDI objects (e.g., HDC - device context handles) are not. Since GDI objects are not thread-safe, the use of CS_OWNDC styled windows can result in graphic anomalies or missing data since all calls to GetDC(HWND) return the same non-thread-safe HDC.
Just to clarify things here, you’re talking about the case where you have multiple threads rendering to the same buffer?

Would it matter matter if I had context A on thread A uploading textures, context B on thread B rendering to a pbuffer, context C on thread C freeing old textures, and context D on thread D swapping buffers on the visible onscreen buffer? (Each has its own DC and RC, and they’re all wglShareList’ed)

Would it matter in the above case if A and C shared DCs (but not RCs) with context D?

Originally posted by Stephen_H:
[b]Just to clarify things here, you’re talking about the case where you have multiple threads rendering to the same buffer?

Would it matter matter if I had context A on thread A uploading textures, context B on thread B rendering to a pbuffer, context C on thread C freeing old textures, and context D on thread D swapping buffers on the visible onscreen buffer? (Each has its own DC and RC, and they’re all wglShareList’ed)

Would it matter in the above case if A and C shared DCs (but not RCs) with context D?[/b]
Yes, I was talking about multiple threads rendering to the same (visible) buffer. With respect to your example, hypothetically there shouldn’t be any visual problem even if A and C share the same HDC. At lot will depend on the driver’s ability to internally synchronize the pbuffer accesses and the display buffer accesses. If the graphics card doesn’t support multiple HW contexts, you may not see much benefit from rendering to a pbuffer and a display buffer at the same time. I’m also not sure how quickly a shared OpenGL object (e.g., bound texture) will become truly shared among the various contexts. Typically OpenGL requests are buffered on the client side and the only way to guarantee that all requests have been processed by a thread is to call glFinish(). If thread A is loading textures, threads B and D should not attempt to render with those textures until A has called glFinish(). Otherwise the texture application will fail (silently) until the texture operations from thread A against the bound target are processed. I don’t think it is an error to bind to an empty texture - you just get the default assignment for that target.

Regardless, you need to provide reliable sychronization for these shared objects and not depend on the results generated by your system’s configuration. For instance, a uniprocessor system behaves very differently than a multiprocessor system and a unicore HyperThreaded system (i.e., two states and one processor core) is almost not worth the effort in a single application.

HTH,
tim