Puzzled by OpenGL multi threaded slowdown

Started by
2 comments, last by fboivin 14 years, 10 months ago
Hi, I'm investigating a puzzling overhead I'm having while multithreading an opengl renderer. I'll skip the details but what I basically have is instead of doing Render() on the same thread as anything else, I set an event that wakes up the render thread which then calls Render. For debugging purposes I currently have the main thread immediately wait for the rendering to be finished with its frame before continuing. This is so I can keep exactly the same behavior as the single threaded code. Thus what I have is instead of calling Render from the main thread, it's called from the render thread, that's it, verify and debugged! ;) The puzzling part is that code adds a overhead of approx 10ms to my rendering! The only overhead that should append is the one from context switching, but I've timed it to only 0.02ms. It's not also some sort of global lock since while the render thread is working, the main thread is sleeping and vice-versa. Intel Thread Profiler shows it's constantly context switching to a thread internal to the driver called DrvCopyContext (nvidia hw). The question is why?! The only thing different from my single and multi threaded application is the fact that the Render function is called on a separate thread and the rendering context is created on that thread. After all the tests I've done, I'm now clueless! Could it be because the rendering context is created on a different thread than it used to be? Does it needs to be created on the same thread the window is on? That defeat all purposed of multi threading! I'll appreciate any feedback/clues you can give me! Thanks francis
Advertisement
Quote:Original post by fboivin
Does it needs to be created on the same thread the window is on? That defeat all purposed of multi threading!
You can in theory submit OpenGL commands from whatever thread you like, if you glMakeCurrent() the context before.

However, the only really painless and efficient way is to submit all commands from the thread that created the OpenGL context. This does not necessarily need to be the same thread that created the window and runs the message loop.
Creating the window first, then spawning a thread which creates a GL context, and continuing the message loop in the original thread is something I'm doing too, it works without any problems. It doesn't yield the boost that you maybe expect, though. The main reason why one would want to do that is to prevent the game from freezing while the user drags the window. The actual performance gains to be expected from running the message loop and the render loop separately are minuscule.

However...
Quote:I set an event that wakes up the render thread
This really defeats the purpose of multithreading. The way you describe it, the render thread blocks until some other thread tells it to render a frame.
It should not block, instead you should have the render thread submit one frame after the other as fast as it can (only limited by vertical blank). It could interpolate between two states that are updated on a fixed time step (by another thread, or preferrably by a pool of threads that is fed by a job scheduler).
I've done some more testing and if I create my window on the same thread I'm creating my OpenGL context I don't have any more weird overhead. However that's complete bs as I don't want to create my window and manage the message loop on the render thread.

As for the synchronizing story (the vent) it's a completely different subject. Right now I'm only interested in running my Render in a separate thread in a serial way without that insane non-sense overhead

Are there any flags I'm missing?
Might be a stupid question, but why don't you go the other way around, id est running your render in the same thread in which you create your window and everything else (data loading, message loop, etc) in a separate thread ? Or is there a specific reason for which you want to separate window and context creation ?
Quote:Original post by trexmaster78
Might be a stupid question, but why don't you go the other way around, id est running your render in the same thread in which you create your window and everything else (data loading, message loop, etc) in a separate thread ?

This is something I tried once upon a time when the meadows were green and the hobbits were plentiful, but it's something that never worked properly, as Windows seems to expect some functions to be called only from the same thread that created the window. Maybe there is a way, but not one that is immediately obvious to me.

The other thing, spawn a thread, pass it the HWND and let it create a context, is something that worked out of the box on the first attempt and runs 100% well with no hassle at all, for many months.
Basically, everything after and including ChoosePixelFormat() goes into the thread, and that's it.
Ahhh! I've moved ChoosePixelFormat and down to the rendering thread and everything is fine now! No stupid overhead!

Thanks for the advice!

This topic is closed to new replies.

Advertisement