Skip to main content
GameDev.net gamedev.net
🔒 Locked

Separating rendering and input

Started by Joni-Matti Feb 23, 2008 at 4:31 PM 5 replies 1.8k views
Original Post
Joni-Matti
Joni-Matti
I'm working on a multithreaded game engine where the game update loop would be running on the main thread (at fixed 60 fps) and rendering in another thread (as fast as possible). The problem I now faced was that I was creating the game window in the main thread, and apparently DirectX 10 can't handle windows not created by the calling thread. So obviously I have to move all my window handling into the rendering thread. My keyboard and mouse input is handled using WM_INPUT window messages, so I can't think of anything else but to move my input systems also to the rendering thread. But this would make my input handling dependent on the rendering framerate. How can I separate the input handling from the rendering thread, so that the input handling could be updated in sync with the game update (at 60 fps) independent of the rendering thread's framerate? One thing also came to my mind: is it possible to only create the window in the rendering thread (keeping DX10 happy) and then have the message pump in the main thread (I really doubt this)?
Darragh
Darragh
Quote:
Original post by Joni-Matti
I'm working on a multithreaded game engine where the game update loop would be running on the main thread (at fixed 60 fps) and rendering in another thread (as fast as possible). The problem I now faced was that I was creating the game window in the main thread, and apparently DirectX 10 can't handle windows not created by the calling thread.

So obviously I have to move all my window handling into the rendering thread. My keyboard and mouse input is handled using WM_INPUT window messages, so I can't think of anything else but to move my input systems also to the rendering thread. But this would make my input handling dependent on the rendering framerate.

How can I separate the input handling from the rendering thread, so that the input handling could be updated in sync with the game update (at 60 fps) independent of the rendering thread's framerate?


Hmmm.. I'm not sure if this would work but have you considered getting the rendering thread to do the render to an offscreen render target and then allowing then the main thread to simply display it when it's ready ? There would be an additional cost to this scheme naturally, but if it worked it would allow the two threads to operate quite happily independently of each other and you could recoup the cost by increased parallelism. Worth a shot perhaps!

Quote:
Original post by Joni-MattiOne thing also came to my mind: is it possible to only create the window in the rendering thread (keeping DX10 happy) and then have the message pump in the main thread (I really doubt this)?


No it's not possible, having ran into this limitation myself before I can confidently say that! [smile] Unfortunately Windows requires that message processing be done by the thread that created the window, so that's out of the question. That's also probably the reason DX runs into problems with windows not created by the calling thread either, it's simply a limitation of the underlying operating system.
Joni-Matti
Joni-Matti
Quote:

Original post by Darragh
Hmmm.. I'm not sure if this would work but have you considered getting the rendering thread to do the render to an offscreen render target and then allowing then the main thread to simply display it when it's ready ? There would be an additional cost to this scheme naturally, but if it worked it would allow the two threads to operate quite happily independently of each other and you could recoup the cost by increased parallelism. Worth a shot perhaps!


Maybe I didn't understand what you meant, but DirectX needs the window handle when creating the swap chain. So I can't even initialize DirectX without the window.

The easiest solution would of course be to have the rendering and the game update both in the main thread, but I would really like to have the performance improvement from the parallelism.

I'm wondering how this is handled in commercial multithreaded engines.
Darragh
Darragh
Quote:
Original post by Joni-Matti
Quote:

Original post by Darragh
Hmmm.. I'm not sure if this would work but have you considered getting the rendering thread to do the render to an offscreen render target and then allowing then the main thread to simply display it when it's ready ? There would be an additional cost to this scheme naturally, but if it worked it would allow the two threads to operate quite happily independently of each other and you could recoup the cost by increased parallelism. Worth a shot perhaps!


Maybe I didn't understand what you meant, but DirectX needs the window handle when creating the swap chain. So I can't even initialize DirectX without the window.


That's fair enough; but once you've created the window and initialized DX (both on the main thread) can you not point DX to render to an offscreen target and forget about windows entirely ? You could then get the main thread to take a rendered scene (in a render target) and actually handle the swap, drawing it to the screen when needed.
Joni-Matti
Joni-Matti
Actually I already gave a try to something like you mentioned :) I created the device and swap chain in the main thread and then created the renderer thread to do all rendering stuff. And because DX10 is fully thread-safe, I could even swap the buffers in the renderer thread (using the default swap chain and Present())!! I don't know if this is performance-wise (DX10 uses critical sections for synchronization), maybe some could light me up on this issue. Doing it your way would be as easy, but maybe DX10 is already doing it good enough.

Why I didn't try this before was because I had read here in gamedev.net that all DX calls (although it was about DX9) should be done in the same thread for performance reasons.
MJP
MJP
Quote:
Original post by Joni-Matti
Why I didn't try this before was because I had read here in gamedev.net that all DX calls (although it was about DX9) should be done in the same thread for performance reasons.


That was certainly the case for D3D9, where the device you created wasn't thread-safe by default and the docs actually warned you that using the MULTITHREADED flag would cause poor behavior. I'm not sure if they're significantly optimized the locks better for D3D10 and that's why it's enabled by default, but I'm sure there's still some overhead there. It's also probably much more likely that your app will able to optimize the locks much better than D3D could, since it probably has to lock and then unlock for almost every method you call.

MJP
MJP
Quote:
Original post by Joni-Matti

One thing also came to my mind: is it possible to only create the window in the rendering thread (keeping DX10 happy) and then have the message pump in the main thread (I really doubt this)?


No you can't do this, at least not directly. Windows have thread affinity, and will post their messages to the message queue of the thread that created them. However if you wanted you could re-post the WM_INPUT messages to your input thread using PostThreadMessage().

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.