WinPumpMessages - High CPU cost of Windows mouse events

I’m having an issue where Windows mouse inputs cause a large CPU spike in WinPumpMessages, particularly with click events. I added traces to track down where the costs are coming from and it seems to be coming from FWindowsApplication::SetCapture and FWindowsApplication::SetHighPrecisionMouseMode.

Looking at the code, FSlateApplication::ProcessMouseButtonDownEvent will always call PlatformApplication->SetCapture so I’m assuming it’s supposed to be fast. Can you think of any reason why these calls would be so expensive?

This was seen with Unreal 5.5.4 on Windows 11 Pro (10.0.26100).

Steps to Reproduce
Run an application in standalone mode with tracing enabled and click the mouse.

I was able to reproduce the issue in the ShooterGame sample.

Here is the trace file.

Hi,

Do you happen to be using a very high DPI mouse? We saw some performance issues related to high DPI mice, and checked in a fix for 5.7 at CL#42232996. If you want to try backporting that change, you can use the CVar WindowsApplication.UseWorkerThreadForRawInput to toggle the new behavior and see if it helps. There are a few other relevant fixes there that you may want to grab as well (CL#42762914, CL#43032922, CL#43352118), hopefully that’s sufficient to improve performance for you.

Best,

Cody

I do have a high DPI mouse but this specific issue is around clicking the mouse button and the subsequent calls to PlatformApplication->SetCapture. It looks like the behaviour of mouse input (movement & buttons) has drastically changed in the CLs you posted above but I don’t see any changes to the way application capture/focus is handled.

Is this method of handling mouse input going to be the default in 5.7?

I tried bringing those CLs into our version of the engine and it is still displaying the same behaviour with the multiple calls to SetFocus within a single button input on the main thread.

Hi,

I added similar traces, and I’m seeing pretty similar times in Lyra. Here’s an example of a double click:

[Image Removed]The three calls to SetCapture is unfortunate, but at least two of them are probably necessary. The first could be important since we may potentially short circuit the ProcessMouseButtonDown handler via a preprocessor, while the second is the standard SetCapture call for a click. However, the third SetCapture and SetHighPrecisionMouseMode seem a bit redundant, as we should already be in high precision mode (via FSceneViewport::AcquireFocusAndCapture) as long as the viewport is focused and the cursor is hidden.

Any changes here are fairly dangerous since there are a ton of edge cases with input handling, but it may be safe to make some changes to FSlateApplication::ProcessReply to check IsUsingHighPrecisionMouseMode before making any changes:

// If the mouse is being captured or released, toggle high precision raw input if requested by the reply. // Raw input is only used with mouse capture if (TheReply.ShouldUseHighPrecisionMouse() && !PlatformApplication->IsUsingHighPrecisionMouseMode()) { const TSharedRef< SWindow> Window = CurrentEventPath.GetWindow(); PlatformApplication->SetCapture(Window->GetNativeWindow()); PlatformApplication->SetHighPrecisionMouseMode(true, Window->GetNativeWindow()); ...We already do a similar check when releasing high precision mode, so I’ll run this by the team and see if there are any concerns. Early results are pretty promising, if you want to give it a try:

[Image Removed]

Best,

Cody

Thanks for the update Cody! I’ll try those changes to SetHighPrecisionMouseMode.

I put this code into SetCapture:

void FWindowsApplication::SetCapture( const TSharedPtr< FGenericWindow >& InWindow ) { if ( InWindow.IsValid() ) { if (!bHasCapture) { ::SetCapture( (HWND)InWindow->GetOSWindowHandle() ); bHasCapture = true; } } else { if (bHasCapture) { ::ReleaseCapture(); bHasCapture = false; } } }The only issue we noticed was around Alt+Space which I disabled in the WindowsEngine.ini with

[WindowsApplication] bConsumeAltSpace=True

Hi,

I had considered caching the capture state as well, though I had some concerns that it may desynchronize if the capture was ended at the OS level (which I imagine could happen in some cases where Windows wants to take back control). Perhaps we could add some handling for the WM_CAPTURECHANGED message to properly handle that scenario.

Hi,

To close the loop on this, I checked in CL#44455025 with a handful of optimizations based on our findings here. Thanks again for bringing that up, and let me know if you run into any issues with those changes!

Best,

Cody

Excellent, thank you for the update and I’m happy to see the changes become official! :slight_smile: