From d9bbbbfaacca2b58495ee4ea03a537a945c094c1 Mon Sep 17 00:00:00 2001 From: Kaldaien Date: Tue, 17 Dec 2024 02:17:00 -0500 Subject: [PATCH] Reduce latency on HID output reports (i.e. rumble, lighting changes, etc.) --- CHANGELOG.txt | 7 ++++++- include/SpecialK/DLL_VERSION.H | 4 ++-- include/SpecialK/input/input.h | 3 +++ src/input/game_input.cpp | 2 ++ src/input/hid_reports/playstation.cpp | 20 +++++++++++++++----- src/input/windows.gaming.input.cpp | 8 ++++++++ src/input/xinput_core.cpp | 15 +++++++++------ 7 files changed, 45 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 66b0bd27a..6db8df841 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,4 +1,9 @@ -24.12.17.1 +24.12.17.2 +========== + + Reduce latency on HID output reports (i.e. rumble, lighting changes, etc.) + for DualShock 4 and DualSense{Edge} controllers. + +24.12.17.1 ========== + Revert ResizeTarget optimization from 24.12.15.4, because it only works as intended in D3D11 games. diff --git a/include/SpecialK/DLL_VERSION.H b/include/SpecialK/DLL_VERSION.H index 7718f3624..4a45ba705 100644 --- a/include/SpecialK/DLL_VERSION.H +++ b/include/SpecialK/DLL_VERSION.H @@ -3,8 +3,8 @@ #define SK_YEAR 24 #define SK_MONTH 12 #define SK_DATE 17 -#define SK_REV_N 1 -#define SK_REV 1 +#define SK_REV_N 2 +#define SK_REV 2 #ifndef _A2 #define _A2(a) #a diff --git a/include/SpecialK/input/input.h b/include/SpecialK/input/input.h index e78ea2713..c869ff261 100644 --- a/include/SpecialK/input/input.h +++ b/include/SpecialK/input/input.h @@ -962,6 +962,9 @@ struct SK_HID_PlayStationDevice USHORT vid = 0x0; USHORT pid = 0x0; + volatile UINT output_requests = 0; + volatile UINT input_requests = 0; + // Interpretation of reports using HID APIs PHIDP_PREPARSED_DATA pPreparsedData = nullptr; diff --git a/src/input/game_input.cpp b/src/input/game_input.cpp index 9dae81149..5fa4d032f 100644 --- a/src/input/game_input.cpp +++ b/src/input/game_input.cpp @@ -1049,6 +1049,8 @@ SK_IGameInputDevice::SetRumbleState (GameInputRumbleParams const *params) noexce static_cast (std::min (65535UL, static_cast (std::clamp (params_.rightTrigger, 0.0f, 1.0f) * 65536.0f))), 65535ui16 ); + + pNewestInputDevice->write_output_report (); } } } diff --git a/src/input/hid_reports/playstation.cpp b/src/input/hid_reports/playstation.cpp index 61ea3ad0c..93bb2c1c6 100644 --- a/src/input/hid_reports/playstation.cpp +++ b/src/input/hid_reports/playstation.cpp @@ -60,9 +60,8 @@ struct SK_HID_DualSense_GetHWAddr // 0x09 : USB // indication that the device was removed is one of these error codes... bool SK_HID_IsDisconnectedError (DWORD dwError) { - return dwError == ERROR_INVALID_HANDLE || - dwError == ERROR_NO_SUCH_DEVICE || - dwError == ERROR_DEVICE_NOT_CONNECTED; + return dwError == ERROR_INVALID_HANDLE;// || + //dwError == ERROR_DEVICE_NOT_CONNECTED; } SK_HID_PlayStationDevice::SK_HID_PlayStationDevice (HANDLE file) @@ -1126,8 +1125,11 @@ SK_HID_PlayStationDevice::request_input_report (void) WriteRelease (&bNeedOutput, TRUE); } + InterlockedIncrement (&input_requests); + if (hInputEvent == nullptr) - { hInputEvent = + { std::scoped_lock _initlock(*xinput.lock_report); + hInputEvent = SK_CreateEvent ( nullptr, TRUE, TRUE, SK_FormatStringW (L"[SK] HID Input Report %p", hDeviceFile).c_str ()); @@ -1290,7 +1292,7 @@ SK_HID_PlayStationDevice::request_input_report (void) // Input Report Waiting if (dwWaitState == (WAIT_OBJECT_0 + 1)) { - std::scoped_lock __(*pDevice->xinput.lock_report); + std::scoped_lock __(*pDevice->xinput.lock_report); DWORD dwBytesTransferred = 0; @@ -2602,8 +2604,12 @@ SK_HID_PlayStationDevice::write_output_report (bool force) return false; } + InterlockedIncrement (&output_requests); + if (hOutputEnqueued == nullptr) { + std::scoped_lock _initlock(*xinput.lock_report); + hOutputEnqueued = SK_CreateEvent (nullptr, TRUE, TRUE, nullptr); @@ -3332,8 +3338,12 @@ SK_HID_PlayStationDevice::write_output_report (bool force) return false; } + InterlockedIncrement (&output_requests); + if (hOutputEnqueued == nullptr) { + std::scoped_lock _initlock(*xinput.lock_report); + hOutputEnqueued = SK_CreateEvent (nullptr, TRUE, TRUE, nullptr); diff --git a/src/input/windows.gaming.input.cpp b/src/input/windows.gaming.input.cpp index d985a9c7b..be0866d19 100644 --- a/src/input/windows.gaming.input.cpp +++ b/src/input/windows.gaming.input.cpp @@ -671,6 +671,12 @@ WGI_Gamepad_put_Vibration_Override (ABI::Windows::Gaming::Input::IGamepad // control panel. SK_WGI_READ (SK_WGI_Backend, sk_input_dev_type::Gamepad); + if (config.input.gamepad.disable_rumble) + { + SK_XInput_ZeroHaptics (0); + return S_OK; + } + bool bRedirected = false; SK_HID_PlayStationDevice *pNewestInputDevice = nullptr; @@ -700,6 +706,8 @@ WGI_Gamepad_put_Vibration_Override (ABI::Windows::Gaming::Input::IGamepad 65535ui16 ); + pNewestInputDevice->write_output_report (); + bRedirected = true; } diff --git a/src/input/xinput_core.cpp b/src/input/xinput_core.cpp index 28c1160e8..6307a9c0a 100644 --- a/src/input/xinput_core.cpp +++ b/src/input/xinput_core.cpp @@ -148,14 +148,17 @@ struct SK_XInputContext if (! InterlockedCompareExchange (&haptic_warned [dwUserIndex], 1, 0)) { - SK_LOG0 ( ( L"WARNING: Recursive haptic feedback loop detected on XInput controller %lu!", - dwUserIndex ), - L" Input " ); + if (! config.input.gamepad.xinput.emulate) + { + SK_LOG0 ( ( L"WARNING: Recursive haptic feedback loop detected on XInput controller %lu!", + dwUserIndex ), + L" Input " ); - SK_ImGui_Warning (L"Problematic third-party XInput software detected (infinite haptic feedback loop), disabling vibration." - L"\n\n\tRestart your game to restore vibration support."); + SK_ImGui_Warning (L"Problematic third-party XInput software detected (infinite haptic feedback loop), disabling vibration." + L"\n\n\tRestart your game to restore vibration support."); - config.input.gamepad.xinput.hook_setstate = false; + config.input.gamepad.xinput.hook_setstate = false; + } } return true;