[PATCH 1/3] dinput: Stop sending WM_WINE_NOTIFY_ACTIVITY on every input.
Rémi Bernon
rbernon at codeweavers.com
Mon Jun 8 02:47:07 CDT 2020
This message triggers screensaver notification in the user drivers, but
it is not useful to send it on every input message, and it even hurts
performance when high polling mouse is used.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=33643
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46976
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
Notes:
This only partially solves the mentionned bugs. Performance can be
improved even more by using rawinput API instead of low-level hooks,
but it requires the wineserver side to be implemented first.
Because wiggling the mouse is a bit unpredictable, I've used evemu to
create a fake evdev mouse device. And I've then injected events using
this python / evemu-play script:
python -u - <<EOF | stdbuf -oL evemu-play /dev/input/eventX
for i in range(0, 1000*10000):
print('E: {:.06f} 0002 0001 +001 # EV_REL / REL_Y'
' +1'.format(i / 1000.))
print('E: {:.06f} 0000 0000 0000 # ------------ '
'SYN_REPORT (0) ---------- +1ms'.format(i / 1000.))
EOF
Event injection time is not 100% reliable, but it is consistent and the
event frequency is approximately 1kHz, similar to a high polling rate
mouse.
I've used Sekiro as a test case, with graphics settings set to lowest
possible. The game runs at ~60fps without mouse input. The fps is not
completely stable, and I believe it may be because the game is doing
things at the same time. So I've measured the average fps of the first
game scene after letting the injection run for a long time.
Only positive REL_Y events are used so that the game camera gets down
quickly and stops moving, to smooth variation that could be caused by
the draw calls.
With Wine 5.10, the fps drop to about ~40fps while input is injected,
and PATCH #1 makes it go up to ~50fps.
The other two patches have smaller effect and not easily measurable,
but I believe they are still helpful -- perf indicates a lot of cache
misses around the list iterations -- and they are also preparing ground
for the rawinput patches.
dlls/dinput/device.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c
index 8c5aa318837..51ae349f34e 100644
--- a/dlls/dinput/device.c
+++ b/dlls/dinput/device.c
@@ -931,13 +931,19 @@ HRESULT _set_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, L
void queue_event(LPDIRECTINPUTDEVICE8A iface, int inst_id, DWORD data, DWORD time, DWORD seq)
{
+ static ULONGLONG notify_ms = 0;
IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
int next_pos, ofs = id_to_offset(&This->data_format, inst_id);
+ ULONGLONG time_ms = GetTickCount64();
/* Event is being set regardless of the queue state */
if (This->hEvent) SetEvent(This->hEvent);
- PostMessageW(GetDesktopWindow(), WM_WINE_NOTIFY_ACTIVITY, 0, 0);
+ if (time_ms - notify_ms > 1000)
+ {
+ PostMessageW(GetDesktopWindow(), WM_WINE_NOTIFY_ACTIVITY, 0, 0);
+ notify_ms = time_ms;
+ }
if (!This->queue_len || This->overflow || ofs < 0) return;
--
2.27.0
More information about the wine-devel
mailing list