WM_INPUT polling rate

Started by
17 comments, last by tanzanite7 11 years, 11 months ago

The preferred way is as suggested by ApochPiQ. You must, and I repeat absolutely must use events to handle input. Have you ever played a game that forgot to fire even though you clearly hit the fire button? Only via polling can this happen. And it is extremely irritating to any human when it happens.
Listening to events is the only way to ensure this never happens.
And only by listening to events on a second thread is this guaranteed to work as promised. Smooth mouse movements require this, and there is some work involved in making it happen correctly, but your players will appreciate it.


This is interesting. Thus far I've always let the input reading(via polling or events) be done in the same thread as the game loop. But I see the issues with this and have encountered many of them in the past, though I've never considered multithreading the input as an option.

Now, if we disregard polling, should it be done by running your message loop in a separate thread or the way DirectInput does it, with a hidden window that only handles input messages? My guess is the first option, but I may have overlooked something, like a third option, hence the question.
Advertisement
When I said polling, I mentioned using GetRawInputBuffer so that even if I were only checking for inputs during a render loop, I'd still get all inputs since the last as I'd be getting an array of events. However, I was going to post another question, and what you're saying about a proper event manager with timestamps pretty much answered it.

I was considering the case where between frames, the user taps forward, then taps left, then releases. I'm guessing I should treat all of these events individually - when the user taps forward, check if they collide with anything e.t.c, then again when they tap left e.t.c., rather than combining these movements and testing at a certain increment. The timestep would be used to correctly space tests and game logic out relative to the input events, so I see the benefit in message handling now over polling, even if I were to get a whole array of buffered inputs (don't think they're timestamped). I've never separated game logic, rendering, and event handling before, as I've only developed homebrew games for consoles where 60fps was pretty much guaranteed, so do you have any good resources or tutorials to help me get thinking about the right way to do it?

P.S. I took a look at your blog, and funnily enough I came across it a few days ago on Google and have been meaning to read that "Fix your timestep" article you linked to.

Now, if we disregard polling, should it be done by running your message loop in a separate thread or the way DirectInput does it, with a hidden window that only handles input messages? My guess is the first option, but I may have overlooked something, like a third option, hence the question.

Windows requires that the message loop be the same thread that created the window, so the option I would suggest is that the main thread handles input, and #2 be game/rendering, or #2 be game and #3 be rendering. Of course making the render thread its own thread is an entirely different topic and if you don’t need that kind of performance then don’t try it.


The timestep would be used to correctly space tests and game logic out relative to the input events, so I see the benefit in message handling now over polling, even if I were to get a whole array of buffered inputs (don't think they're timestamped). I've never separated game logic, rendering, and event handling before, as I've only developed homebrew games for consoles where 60fps was pretty much guaranteed, so do you have any good resources or tutorials to help me get thinking about the right way to do it?

Unfortunately I do not, but this is something I might consider for an upcoming tutorial.
Without being able to give you any further resources for studying up on this, I can just suggest that you think about it for a while on your own before implementing it. In everything I do there is always this thought process beforehand where I try to visualize what needs to be addressed and what implementation will address it fully without creating side-effects in any other subsystems. It seems as though you have understood what needs to be addressed so just ponder for a while how to properly implement it.

I also try to look past my current needs and think about what the future might hold and also consider all kinds of variants that have been noticed in games I have played and try to think of an implementation that could handle all of those variants. And don’t feel rushed on this. Most things take me days, some complicated things take me months.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

Sorry for bringing up a somewhat old thread...

Wouldn't it be appropriate to use the windows message queue on the same thread as your game logic/rendering, and just utilize the MSG::time parameter to determine when to apply user input to the game simulation?

Sorry for bringing up a somewhat old thread...

Wouldn't it be appropriate to use the windows message queue on the same thread as your game logic/rendering, and just utilize the MSG::time parameter to determine when to apply user input to the game simulation?

UI messages need to be handled on the thread that created the Window. This is a requirement of windows.

The actual issue with the code has to do with the message loop, which insists on drawing each and every time through. Thus only a single message is ever processed per iteration. The correct message loop syntax should only operate during the IDLE time, all windows messages have been processed. This is typically done with a loop that looks something like:
while(true) {
if(PeekMessage) {
Do stuff with the windows message
} else {
Do your game processing stuff here
}
}

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.

I'm aware the win32 message pump needs to be handled on the same thread as the window. I'm curious why to separate input and game logic/rendering to two threads. Why can't we do this to process all messages instead of just one?

while(true) {
while(PeekMessage) {
Do stuff with the windows message
}
Do your game processing stuff here
}


All messages are processed before stepping forward the game sim. During your gamelogic update, more messages will be queue'd up by Windows.

The messages from PeekMessage can be put into a queue and stamped with MSG::time parameter. Then those messages can be used to determine when to apply inputs to your fixed time step game logic.

Are there any problems with this approach?

EDIT: I suppose using that 'while loop' could indefinitely keep you from processing and rendering the scene. i.e. Constant mouse movement. Therefore... two threads are needed to give gamelogic updates/renders and input handling a chance to run.

I'm aware the win32 message pump needs to be handled on the same thread as the window. I'm curious why to separate input and game logic/rendering to two threads. Why can't we do this to process all messages instead of just one?

while(true) {
while(PeekMessage) {
Do stuff with the windows message
}
Do your game processing stuff here
}


All messages are processed before stepping forward the game sim. During your gamelogic update, more messages will be queue'd up by Windows.

Check again. My loop processes all messages before rendering.

The difference between the two is actually just one simple thing: Exit condition handling. In the while/if version you can simple call "break" to exit the message loop. In the double loop version you have to do more work, specifically you need a boolean variable to determine when to end the message processing/break out of the game loop:

bool run = true;
while(run) {
while(PeekMessage) {
if quit message:
run = false;
}
if(run) {
Do game stuff
}
}



The messages from PeekMessage can be put into a queue and stamped with MSG::time parameter. Then those messages can be used to determine when to apply inputs to your fixed time step game logic.

Are there any problems with this approach?
[/quote]
Not really, but its kind of silly. Just use rawinput and handle it in thread. It's very very very minor where you pickup the input. Using another thread just for input is stupid and wasteful.

EDIT: I suppose using that 'while loop' could indefinitely keep you from processing and rendering the scene. i.e. Constant mouse movement. Therefore... two threads are needed to give gamelogic updates/renders and input handling a chance to run.
[/quote]
No. How do you think games worked before the "magical threading" craze.

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.

Check again. My loop processes all messages before rendering.[/quote]
Sorry, misread that code. You are correct.

I guess I'm mostly interested in knowing why input should be handled on a separate thread. I'm working on a deterministic game simulation with fixed time increments, and I want my input to be applied at the correct times in the simulation. I'm planning on using raw input via WM_INPUT msg, instead of WM_KEYDOWN, WM_KEYUP, etc, etc.

L. Spiro says the proper way is to thread the input. You say it's wasteful. I suppose I can continue implementing and make a decision for myself. Thanks for all your help :)
The only reason to thread message loop (and by extension, input) is to avoid the blocking nature of the message handling. Ie DefWindowProc is a, potentially, blocking call (for example, dragging a window makes it block until you stop dragging it). If main thread stopping for a long (several hundred frames for example) is not a problem - then there is no reason i am aware of to bother threading it.

One needs (or might want) to record the input with a low level keyboard proc anyway (to allow using all the keys for game purposes: for example the "Win" key etc) and it, iirc, has sufficiently precise message timecodes (not relevant for me atm, so, not actually using thous).

This topic is closed to new replies.

Advertisement