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

d3d / direct input multi threading

Started by damsku Jul 30, 2007 at 6:21 AM 9 replies 3.7k views
Original Post
damsku
damsku
Hi, I am having some troubles with the multithreading and direct input / 3d. I have 2 threads, one dedicated to the rendering and another one to the update, the update thread is responsible to gather synchronously the input data at constant rate and schedule the other threads for the game logic. Till there, i'm all fine and it works great, but i m bumping into some issues with direct x. The d3d device is created in the same thread which creates the window since in fullscreen exclusive mode, it will fail somehow the resetdevice if i do differently (http://msdn2.microsoft.com/en-us/library/bb147224.aspx), unfortunately, i would need the input thread to be the same than the window one so the dinput will work properly which would end up having the input update in the render thread. Not what i want... Creating the dinput device in the update thread works fine apparently for gathering input, but the mouse acquire method will not show/hide the mouse cursor as it is supposed to do... Any suggestion? How can i work around that?
Evil Steve
Evil Steve
Do you need the player to be able to move twice in one frame? If not, you almost certainly don't need threaded input. if you do - what on earth are you doing?
And you shouldn't be using DirectInput unless you're reading input from something other than the keyboard or mouse.
damsku
damsku
I want the input to be read at constant rate cause when the rendering goes under ~60 fps, you can notice a terrible growing lag with the controls and it s super annoying. SO yes, in the worst case scenario, i wamt the input to be updated more than once per render frame.. That s the idea of using multithreading for that.
Plus i heard dinput is more appropriate to use, not that the window message have ever been a problem in the past, but i wanted to change it for once :) Dinput seems very appropriate for keyboard and mouse though, why wouldn't i use it?
Evil Steve
Evil Steve
Quote:
Original post by damsku
I want the input to be read at constant rate cause when the rendering goes under ~60 fps, you can notice a terrible growing lag with the controls and it s super annoying. SO yes, in the worst case scenario, i wamt the input to be updated more than once per render frame.. That s the idea of using multithreading for that.
Plus i heard dinput is more appropriate to use, not that the window message have ever been a problem in the past, but i wanted to change it for once :) Dinput seems very appropriate for keyboard and mouse though, why wouldn't i use it?
Well, you're not going to be taking input more than once a frame there, since the two "frames" of input will be coalesced into one frame (You'll only see the result of both frames of input in one frame of video). DirectInput buffered input will work fine for that if it's single threaded and you read all of the input from the buffer every frame, but then so will window messages.

As for reasons not to use DirectInput for keyboard input:
  • No speed advantage over using Window messages - and is likely to be even slower, since your window will receive keyboard messages anyway, you just ignore them.
  • Excessive code to accomplish the same thing as Window messages.
  • DirectInput ignores all user control pannel settings (repeat delay, etc).
  • Emulating key repeat is a pain to do in DirectInput, but is free with window messages.
    Link and relevant excerpt:
    Quote:
    Overall, using DirectInput offers no advantages when reading data from mouse or keyboard devices, and the use of DirectInput in these scenarios is discouraged.


    It's less of an issue with keyboard input than it is with mouse input, but it's still not really a good idea to use DirectInput for keyboard input. It's not really that there's any bad things about it (Aside from time to implement), it's just there's no good things.
  • damsku
    damsku
    Yes, "(You'll only see the result of both frames of input in one frame of video)" sounds very much like it should be. I want the lag of the input be independent of how slow the render loop is, that's why i want to read the input in another thread. If the input is read 6 times while only 1 frame was render. It means the rendering is pretty slow, but my controls will not be affected by how slow the rendering is.
    Using window messages will make them to be updated only once per video frame: in other word, if the game runs 30 fps, it will feel laggy on the input... What am i supposed to do then to avoid that?
    PS: i am quite positive in case of multithreading, the input MUST be in the update and not in the render thread..
    Evil Steve
    Evil Steve
    Quote:
    Original post by damsku
    Yes, "(You'll only see the result of both frames of input in one frame of video)" sounds very much like it should be. I want the lag of the input be independent of how slow the render loop is, that's why i want to read the input in another thread. If the input is read 6 times while only 1 frame was render. It means the rendering is pretty slow, but my controls will not be affected by how slow the rendering is.
    Using window messages will make them to be updated only once per video frame: in other word, if the game runs 30 fps, it will feel laggy on the input... What am i supposed to do then to avoid that?
    I don't really see the problem I'm afraid...

    You could update the input 100 times in one frame, but you'll only be able to see the results of that in one frame. For example, if you move left and right on alternate input frames, and you read 5 frames of input, your end result is "right once", which is what you'll see.

    Reading input 5 or 6 times across one frame is exactly the same as reading all the data you would get in 6 reads, but reading it once at the start of the frame. DirectInput and window messages will give you the same result in this case.
    damsku
    damsku
    Yes, at the difference the time spent by the CPU to read the input is wasted time for the rendering. So it is not at all the same. The idea of using multithreading is to make the CPU works while the GPU works too unlike the single threaded application which have the CPU waiting for the GPU to finish 80% of the time of a frame...
    So what i am looking for is, back to the original question, "how do i get dinput to work in a different thread than the window proc? If it is possible :)"
    And yes, btw, it will not speed up my rendering, but 30fps doesn't look jerky... what looks jerky is the non-constant rate the input is being checked, cinematics, i.e are perfectly smooth, but in-game which requires input looks jerky and feels laggy.
    Evil Steve
    Evil Steve
    I know I'm derailing this thread slightly, sorry [smile]

    Quote:
    Original post by damsku
    So what i am looking for is, back to the original question, "how do i get dinput to work in a different thread than the window proc? If it is possible :)"
    All DirectInput does is use window messages internally anyway (WM_INPUT). DirectInput spawns another thread to get these messages out (See the link I gave a couple of posts ago). Having yet another thread to poll DirectInput really won't make any difference and is likely to be slower if anything (Due to the overhead of context switching).
    As for the original question; "Is it possible", I don't know, sorry.

    Quote:
    Original post by damsku
    Yes, at the difference the time spent by the CPU to read the input is wasted time for the rendering. So it is not at all the same. The idea of using multithreading is to make the CPU works while the GPU works too unlike the single threaded application which have the CPU waiting for the GPU to finish 80% of the time of a frame...
    Rendering is already asyncronous. The GPU can buffer up to 1.5 frames (More with some non-standard driver hacks) and let the CPU get on with what it's doing.

    If you're using buffered input, then I still can't see how it'd make any difference. When you come to use the input, it'll be in exactly the same state if you read it 6 times over one frame, or if you read it once at the start of the frame.
    damsku
    damsku
    i don't use buffered input for in-game. I used buffered only for the UI stuff. But well. At the moment, i'm not even worrying about that, this is really a trivial problem for me to make it work afterward, what is a real blocker for me is that i can't get the initialization of my modules with direct x (input/3d) in 2 different threads working properly...
    Plus, http://msdn2.microsoft.com/en-us/library/bb147224.aspx states "In particular, an application must be sure to strongly segregate its window message handling threads from its Direct3D threads. An application that causes a mode change on one thread but makes Direct3D calls on a different thread in its window procedure is in danger of deadlock."
    If you segregate its window message handling threads from its Direct3D threads, doesn't that mean mode changes will FOR SURE be called from another thread???
    Evil Steve
    Evil Steve
    Quote:
    Original post by damsku
    i don't use buffered input for in-game. I used buffered only for the UI stuff. But well. At the moment, i'm not even worrying about that, this is really a trivial problem for me to make it work afterward, what is a real blocker for me is that i can't get the initialization of my modules with direct x (input/3d) in 2 different threads working properly...
    Plus, http://msdn2.microsoft.com/en-us/library/bb147224.aspx states "In particular, an application must be sure to strongly segregate its window message handling threads from its Direct3D threads. An application that causes a mode change on one thread but makes Direct3D calls on a different thread in its window procedure is in danger of deadlock."
    If you segregate its window message handling threads from its Direct3D threads, doesn't that mean mode changes will FOR SURE be called from another thread???
    Ah, if you're using immediate mode input then I can see the reason - but then why are you doing that? [smile]

    There's some D3D calls that must be called from the main window thread, because D3D subclasses the window. The point that page is making is that the mode change has to happen from the same thread as the main window. So Reset(), etc needs to be called from the same thread as is running the window, meaning mode changes have to originate from the window / D3D reset thread.
    damsku
    damsku
    yup. Thanks for the help :)
    Is there any good tutorials and suggestions or whatever like that to develop multi-threaded game engine? It is a real pain in the butt to move an existing single threaded engine...

    Topic Locked

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

    Sign in to reply to this topic.