From 21093ca1a15f774e60eba47058c447a7248d1075 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 9 Sep 2023 15:12:58 +0200 Subject: [PATCH] Implement NVIDIA Reflex Low Latency technology --- r5dev/common/global.cpp | 8 +++++++ r5dev/common/global.h | 3 +++ r5dev/core/CMakeLists.txt | 1 + r5dev/core/stdafx.h | 4 ++++ r5dev/engine/sys_dll.cpp | 2 +- r5dev/engine/sys_dll2.cpp | 46 +++++++++++++++++++++++++++++++++++++ r5dev/engine/sys_dll2.h | 8 +++++++ r5dev/engine/sys_engine.cpp | 1 + r5dev/engine/sys_engine.h | 18 ++++++++++----- r5dev/public/iengine.h | 2 +- 10 files changed, 85 insertions(+), 8 deletions(-) diff --git a/r5dev/common/global.cpp b/r5dev/common/global.cpp index d9b53957..07f63f13 100644 --- a/r5dev/common/global.cpp +++ b/r5dev/common/global.cpp @@ -64,6 +64,9 @@ ConVar* r_drawWorldMeshesDepthAtTheEnd = nullptr; #ifndef DEDICATED ConVar* r_visualizetraces = nullptr; ConVar* r_visualizetraces_duration = nullptr; + +ConVar* gfx_nvnUseLowLatency = nullptr; +ConVar* gfx_nvnUseLowLatencyBoost = nullptr; #endif // !DEDICATED ConVar* stream_overlay = nullptr; @@ -300,6 +303,11 @@ void ConVar_StaticInit(void) r_drawWorldMeshesDepthOnly = ConVar::StaticCreate("r_drawWorldMeshesDepthOnly" , "1", FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT, "Render world meshes (depth only).", false, 0.f, false, 0.f, nullptr, nullptr); r_drawWorldMeshesDepthAtTheEnd = ConVar::StaticCreate("r_drawWorldMeshesDepthAtTheEnd", "1", FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT, "Render world meshes (depth at the end).", false, 0.f, false, 0.f, nullptr, nullptr); +#ifndef DEDICATED + gfx_nvnUseLowLatency = ConVar::StaticCreate("gfx_nvnUseLowLatency" , "1", FCVAR_RELEASE | FCVAR_ARCHIVE, "Enables NVIDIA Reflex Low Latency SDK." , false, 0.f, false, 0.f, nullptr, nullptr); + gfx_nvnUseLowLatencyBoost = ConVar::StaticCreate("gfx_nvnUseLowLatencyBoost", "1", FCVAR_RELEASE | FCVAR_ARCHIVE, "Enables NVIDIA Reflex Low Latency Boost.", false, 0.f, false, 0.f, nullptr, nullptr); +#endif // !DEDICATED + //------------------------------------------------------------------------- // SHARED | modsystem_enable = ConVar::StaticCreate("modsystem_enable", "1", FCVAR_RELEASE, "Enable the modsystem.", false, 0.f, false, 0.f, nullptr, nullptr); diff --git a/r5dev/common/global.h b/r5dev/common/global.h index 0a0d6cfd..d0865f56 100644 --- a/r5dev/common/global.h +++ b/r5dev/common/global.h @@ -55,6 +55,9 @@ extern ConVar* r_drawWorldMeshesDepthAtTheEnd; #ifndef DEDICATED extern ConVar* r_visualizetraces; extern ConVar* r_visualizetraces_duration; + +extern ConVar* gfx_nvnUseLowLatency; +extern ConVar* gfx_nvnUseLowLatencyBoost; #endif // !DEDICATED extern ConVar* stream_overlay; diff --git a/r5dev/core/CMakeLists.txt b/r5dev/core/CMakeLists.txt index 75fec9ab..0c1c6161 100644 --- a/r5dev/core/CMakeLists.txt +++ b/r5dev/core/CMakeLists.txt @@ -98,6 +98,7 @@ target_link_libraries( ${PROJECT_NAME} PRIVATE "rui" "d3d11.lib" + "${THIRDPARTY_SOURCE_DIR}/nvapi/amd64/nvapi64.lib" ) endif() diff --git a/r5dev/core/stdafx.h b/r5dev/core/stdafx.h index bcd0380e..ce176603 100644 --- a/r5dev/core/stdafx.h +++ b/r5dev/core/stdafx.h @@ -35,6 +35,10 @@ #include "thirdparty/imgui/misc/cpp/imgui_stdlib.h" #include "thirdparty/imgui/backends/imgui_impl_dx11.h" #include "thirdparty/imgui/backends/imgui_impl_win32.h" + +#include "thirdparty/nvapi/pclstats.h" +#include "thirdparty/nvapi/nvapi.h" +#include "thirdparty/nvapi/nvapi_lite_common.h" #endif // !DEDICATED && !PLUGINSDK diff --git a/r5dev/engine/sys_dll.cpp b/r5dev/engine/sys_dll.cpp index dbea2b05..e6f5187d 100644 --- a/r5dev/engine/sys_dll.cpp +++ b/r5dev/engine/sys_dll.cpp @@ -79,7 +79,7 @@ int CModAppSystemGroup::StaticMain(CModAppSystemGroup* pModAppSystemGroup) g_pEngine->SetQuitting(IEngine::QUIT_NOTQUITTING); if (g_pEngine->Load(pModAppSystemGroup->IsServerOnly(), g_pEngineParms->baseDirectory)) { - if (CEngineAPI_MainLoop()) + if (CEngineAPI::MainLoop()) { nRunResult = RUN_RESTART; } diff --git a/r5dev/engine/sys_dll2.cpp b/r5dev/engine/sys_dll2.cpp index dd724580..402ecb52 100644 --- a/r5dev/engine/sys_dll2.cpp +++ b/r5dev/engine/sys_dll2.cpp @@ -10,12 +10,14 @@ #include "tier1/cmd.h" #include "tier1/cvar.h" #include "tier1/strtools.h" +#include "engine/sys_engine.h" #include "engine/sys_dll.h" #include "engine/sys_dll2.h" #include "engine/host_cmd.h" #include "engine/traceinit.h" #include "rtech/rtech_utils.h" #ifndef DEDICATED +#include "windows/id3dx.h" #include "client/vengineclient_impl.h" #endif // !DEDICATED #include "filesystem/filesystem.h" @@ -151,11 +153,54 @@ void CEngineAPI::VSetStartupInfo(CEngineAPI* pEngineAPI, StartupInfo_t* pStartup #endif // !(GAMEDLL_S0) || !(GAMEDLL_S1) } +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CEngineAPI::MainLoop() +{ + // Main message pump + while (true) + { + // Pump messages unless someone wants to quit + if (g_pEngine->GetQuitting() != IEngine::QUIT_NOTQUITTING) + { + if (g_pEngine->GetQuitting() != IEngine::QUIT_TODESKTOP) + return true; + + return false; + } + +#ifndef DEDICATED + const bool bUseLowLatencyMode = gfx_nvnUseLowLatency->GetBool(); + const bool bUseLowLatencyBoost = gfx_nvnUseLowLatencyBoost->GetBool(); + //const float fpsMax = fps_max->GetFloat(); + + NV_SET_SLEEP_MODE_PARAMS_V1 params = {}; + params.version = NV_SET_SLEEP_MODE_PARAMS_VER1; + + params.bLowLatencyMode = bUseLowLatencyMode; + params.bLowLatencyBoost = bUseLowLatencyMode && bUseLowLatencyBoost; + params.minimumIntervalUs = 0;// /*!!!leaving this 0 results in better performance!!!*/ fpsMax > 0 ? (NvU32)((1000.0f / fpsMax) * 1000.0f) : 0; + params.bUseMarkersToOptimize = false; + + NvAPI_Status status = NvAPI_D3D_SetSleepMode(*g_ppGameDevice, ¶ms); + + if (status == NVAPI_OK) + NvAPI_D3D_Sleep(*g_ppGameDevice); + + CEngineAPI_PumpMessages(); +#endif // !DEDICATED + + g_pEngine->Frame(); + } +} + /////////////////////////////////////////////////////////////////////////////// void VSys_Dll2::Attach() const { DetourAttach(&CEngineAPI_Init, &CEngineAPI::VInit); DetourAttach(&CEngineAPI_ModInit, &CEngineAPI::VModInit); + DetourAttach(&CEngineAPI_MainLoop, &CEngineAPI::MainLoop); DetourAttach(&v_CEngineAPI_SetStartupInfo, &CEngineAPI::VSetStartupInfo); } @@ -163,5 +208,6 @@ void VSys_Dll2::Detach() const { DetourDetach(&CEngineAPI_Init, &CEngineAPI::VInit); DetourDetach(&CEngineAPI_ModInit, &CEngineAPI::VModInit); + DetourDetach(&CEngineAPI_MainLoop, &CEngineAPI::MainLoop); DetourDetach(&v_CEngineAPI_SetStartupInfo, &CEngineAPI::VSetStartupInfo); } \ No newline at end of file diff --git a/r5dev/engine/sys_dll2.h b/r5dev/engine/sys_dll2.h index 6f76c014..a56e8f3c 100644 --- a/r5dev/engine/sys_dll2.h +++ b/r5dev/engine/sys_dll2.h @@ -33,6 +33,8 @@ public: static InitReturnVal_t VInit(CEngineAPI* thisp); static bool VModInit(CEngineAPI* pEngineAPI, const char* pModName, const char* pGameDir); static void VSetStartupInfo(CEngineAPI* pEngineAPI, StartupInfo_t* pStartupInfo); + + static bool MainLoop(); //private: void* m_hEditorHWnd; bool m_bRunningSimulation; @@ -54,6 +56,9 @@ inline bool(*CEngineAPI_ModInit)(CEngineAPI* pEngineAPI, const char* pModName, c inline CMemory p_CEngineAPI_MainLoop; inline bool(*CEngineAPI_MainLoop)(void); +inline CMemory p_CEngineAPI_PumpMessages; +inline void(*CEngineAPI_PumpMessages)(void); + inline CMemory p_CEngineAPI_SetStartupInfo; inline void(*v_CEngineAPI_SetStartupInfo)(CEngineAPI* pEngineAPI, StartupInfo_t* pStartupInfo); @@ -78,6 +83,7 @@ class VSys_Dll2 : public IDetour LogFunAdr("CEngineAPI::Connect", p_CEngineAPI_Connect.GetPtr()); LogFunAdr("CEngineAPI::ModInit", p_CEngineAPI_ModInit.GetPtr()); LogFunAdr("CEngineAPI::MainLoop", p_CEngineAPI_MainLoop.GetPtr()); + LogFunAdr("CEngineAPI::PumpMessages", p_CEngineAPI_PumpMessages.GetPtr()); #if defined (GAMEDLL_S2) || defined (GAMEDLL_S3) LogFunAdr("CEngineAPI::SetStartupInfo", p_CEngineAPI_SetStartupInfo.GetPtr()); #endif @@ -103,6 +109,7 @@ class VSys_Dll2 : public IDetour p_CEngineAPI_MainLoop = g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ?? 84 C0 B9 ?? ?? ?? ??").FollowNearCallSelf(); p_PakFile_Init = g_GameDll.FindPatternSIMD("44 88 44 24 ?? 53 55 56 57"); #endif + p_CEngineAPI_PumpMessages = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 55 48 81 EC ?? ?? ?? ?? 45 33 C9"); p_CEngineAPI_SetStartupInfo = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? ?? 48 81 EC ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ?? 48 8B DA"); p_ResetMTVFTaskItem = g_GameDll.FindPatternSIMD("48 83 EC 28 48 8B 15 ?? ?? ?? ?? 48 85 D2 0F 84 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? 48 8B 01 FF 90 ?? ?? ?? ?? 33 C9 E8 ?? ?? ?? ?? 0F 28 05 ?? ?? ?? ?? 0F 28 0D ?? ?? ?? ?? 0F 11 05 ?? ?? ?? ?? 0F 28 05 ?? ?? ?? ?? 0F 11 0D ?? ?? ?? ?? 0F 28 0D ?? ?? ?? ?? 0F 11 05 ?? ?? ?? ?? 0F 11 0D ?? ?? ?? ?? 48 C7 05 ?? ?? ?? ?? ?? ?? ?? ?? FF 15 ?? ?? ?? ??"); @@ -111,6 +118,7 @@ class VSys_Dll2 : public IDetour CEngineAPI_Connect = p_CEngineAPI_Connect.RCast(); /*48 83 EC 28 48 8B 05 ?? ?? ?? ?? 48 8D 0D ?? ?? ?? ?? 48 85 C0 48 89 15 ?? ?? ?? ??*/ CEngineAPI_ModInit = p_CEngineAPI_ModInit.RCast(); /*48 89 5C 24 ?? 48 89 4C 24 ?? 55 56 57 41 54 41 55 41 56 41 57 48 81 EC ?? ?? ?? ?? 4D 8B F8*/ CEngineAPI_MainLoop = p_CEngineAPI_MainLoop.RCast(); /*E8 ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ?? 84 C0 B9 ?? ?? ?? ??*/ + CEngineAPI_PumpMessages = p_CEngineAPI_PumpMessages.RCast(); v_CEngineAPI_SetStartupInfo = p_CEngineAPI_SetStartupInfo.RCast(); /*48 89 5C 24 ?? 57 48 81 EC ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ?? 48 8B DA*/ PakFile_Init = p_PakFile_Init.RCast(); /*44 88 44 24 ?? 53 55 56 57*/ } diff --git a/r5dev/engine/sys_engine.cpp b/r5dev/engine/sys_engine.cpp index 111fbf62..f27c21dc 100644 --- a/r5dev/engine/sys_engine.cpp +++ b/r5dev/engine/sys_engine.cpp @@ -7,6 +7,7 @@ /////////////////////////////////////////////////////////////////////////////// CEngine* g_pEngine = nullptr; +IEngine::QuitState_t* gsm_Quitting = nullptr; bool CEngine::_Frame(CEngine* thisp) { diff --git a/r5dev/engine/sys_engine.h b/r5dev/engine/sys_engine.h index 15b84a48..8ad38a72 100644 --- a/r5dev/engine/sys_engine.h +++ b/r5dev/engine/sys_engine.h @@ -1,10 +1,20 @@ #pragma once #include +class CEngine; + +/* ==== CENGINE ======================================================================================================================================================= */ +inline CMemory p_CEngine_Frame; +inline bool(*v_CEngine_Frame)(CEngine* thisp); + +extern CEngine* g_pEngine; +extern IEngine::QuitState_t* gsm_Quitting; + class CEngine : public IEngine { public: static bool _Frame(CEngine* thisp); + inline IEngine::QuitState_t GetQuitting() const { return *gsm_Quitting; } private: EngineState_t m_nDLLState; @@ -20,12 +30,6 @@ private: char field_39; }; -/* ==== CENGINE ======================================================================================================================================================= */ -inline CMemory p_CEngine_Frame; -inline bool(*v_CEngine_Frame)(CEngine* thisp); - -extern CEngine* g_pEngine; - /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// @@ -37,6 +41,7 @@ class VEngine : public IDetour { LogFunAdr("CEngine::Frame", p_CEngine_Frame.GetPtr()); LogVarAdr("g_Engine", reinterpret_cast(g_pEngine)); + LogVarAdr("sm_Quitting", reinterpret_cast(gsm_Quitting)); } virtual void GetFun(void) const { @@ -56,6 +61,7 @@ class VEngine : public IDetour #elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3) g_pEngine = g_GameDll.FindPatternSIMD("40 53 48 83 EC 20 80 B9 ?? ?? ?? ?? ?? BB ?? ?? ?? ??").FindPatternSelf("48 8B ?? ?? ?? ?? 01", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x3, 0x7).RCast(); #endif + gsm_Quitting = g_GameDll.FindPatternSIMD("89 15 ?? ?? ?? ?? C3 CC CC CC CC CC CC CC CC CC 83 C1 F4").ResolveRelativeAddressSelf(0x2, 0x6).RCast(); } virtual void GetCon(void) const { } virtual void Attach(void) const; diff --git a/r5dev/public/iengine.h b/r5dev/public/iengine.h index f9fe9c8e..b5216fd1 100644 --- a/r5dev/public/iengine.h +++ b/r5dev/public/iengine.h @@ -20,7 +20,7 @@ abstract_class IEngine { public: - enum + enum QuitState_t { QUIT_NOTQUITTING = 0, QUIT_TODESKTOP,