windows: Prevent high freq mice from slowing down event loops #4792
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR changes event polling behavior - and in particular
WIN_PumpEvents
- to not waste time when dealing with high frequency mice continuously generating new messages on every poll / pump on Windows.Description
I'm going to preface this with the huge code comment that I've been writing for a while now.
Windows mouse movement events seems to work in a "get as much as you want, anything else gets combined" manner, which seems to cause problems with how most SDL applications implement their event polling and handling loops. In particular, polling currently always calls the event pump function, which on Windows goes through the entire message queue including new auto-generated mouse moves, even when there are still old events left in SDL's queue. With high frequency mice, this means that "new" mouse events just kept appearing between polls, keeping the loop stuck for as long as the mouse is being moved! The fact that Windows internally sends and handles
WM_HITTEST
andWM_SETCURSOR
on everyWM_MOUSEMOVE
autogenerated byPeekMessage
didn't make it perform better either.This PR changes the following:
WM_MOUSEMOVE
messages immediately.WM_MOUSEMOVE
s after all other events (which is when they should appear anyway, among a few other auto-generated messages, according to all docs I was able to find), up to N (currently 3) consecutive "mouse move only" pumps.SDL_WaitEventTimeout
(used bySDL_PollEvent
) to check for old events before callingSDL_PumpEvents()
.I am concerned about the following things:
SDL_WaitEventTimeout
works? I'm a bit worried about changing something that could affect many platforms only because "it makes sense to this one Windows user."MAX_MOUSEMOVE_PUMPS
become a hint? What should it default to? (Realistically a single mouse move per "game update" should be enough, but this change possibly affects a very wide variety of applications, and this change still allows for mouse moves between other events.)SDL_PumpEvents
in a manner which could cause this PR to introduce negative effects? I personally can't think of any, but I'm still trying to be cautious, and would love to hear alternative solutions to handle the lack of a "poll loopstart_ticks
" instead of a "pumpstart_ticks
".WndProc
? This change in its current form also skips / delays the execution of those forWM_MOUSEMOVE
, but I figured I'd ask for feedback on the current impl before banging my head against a wall on how to makeWIN_WindowProc
tellWIN_PumpEvents
to handle the last mouse movement with the least spaghetti involved, instead of havingWIN_WindowProc
process every autogenerated mouse movement.#if 1
for future reference and / or quick testing, or should I clean it up and remove the old loop? CTRL+F-ing for#if 0
across the SDL source gives a few results after all.Existing Issue(s)
#4376 was already marked as closed, but I've still been able to replicate noticeable performance loss on interaction before and after replacing most of my machine (including reinstalling the OS, upgrading the CPU, RAM, SSD and replacing the USB controller) with the same mouse in 1000 Hz mode and SDL built from source.