When possible use game's XeLL instance instead of Fallback for FPS limit

This commit is contained in:
FakeMichau
2026-04-27 15:19:04 +02:00
parent b1b8e3640e
commit db00ade552
6 changed files with 51 additions and 5 deletions
+2
View File
@@ -1584,6 +1584,8 @@ void CheckMemoryForProxies()
XeFGProxy::InitXeFG();
XeLLProxy::InitXeLL();
XellHooks::Hook();
NVNGXProxy::InitNVNGX();
}
+1 -1
View File
@@ -1175,7 +1175,7 @@ HRESULT FGHooks::FGPresent(IDXGISwapChain* This, UINT SyncInterval, UINT Flags,
Hudfix_Dx12::PresentEnd();
if (willPresent && !State::Instance().reflexLimitsFps && State::Instance().activeFgOutput != FGOutput::NoFG &&
!IdentifyGpu::getPrimaryGpu().usesDxvk)
!IdentifyGpu::getPrimaryGpu().usesDxvk && !XellHooks::canLimit())
{
FrameLimit::sleep(fg != nullptr ? fg->IsActive() && !fg->IsPaused() : false);
}
+33 -1
View File
@@ -52,12 +52,44 @@ void XellHooks::blockExternalContexts(bool state) { blockExternal = state; }
// Use context to determine blocking, otherwise just block calls from exe
bool XellHooks::shouldBlock(xell_context_handle_t context)
{
if (context && ourContext != context && gamesContext != context)
gamesContext = context;
if (!blockExternal)
return false;
if (context)
return blockExternal && ourContext != context;
return ourContext != context;
else
return GetModuleHandle(nullptr) == Util::GetCallerModule(_ReturnAddress());
}
bool XellHooks::canLimit() { return gamesContextCanLimitFps; }
// only DX12
bool XellHooks::update()
{
if (!o_xellGetSleepMode || !o_xellSetSleepMode || blockExternal || gamesContext == nullptr)
return false;
xell_sleep_params_t currentParams;
o_xellGetSleepMode(gamesContext, &currentParams);
if (!currentParams.bLowLatencyMode)
return false;
gamesContextCanLimitFps = true;
float fpsLimit = Config::Instance()->FramerateLimit.value_or_default();
if (fpsLimit < 0.0f)
fpsLimit = 0.0f;
currentParams.minimumIntervalUs = static_cast<uint32_t>(std::round(1'000'000 / fpsLimit));
return o_xellSetSleepMode(gamesContext, &currentParams) == XELL_RESULT_SUCCESS;
}
xell_result_t XellHooks::hkxellDestroyContext(xell_context_handle_t context)
{
if (shouldBlock(context))
+5
View File
@@ -21,6 +21,8 @@ typedef decltype(&xellD3D12CreateContext) PFN_xellD3D12CreateContext;
class XellHooks
{
inline static xell_context_handle_t ourContext = nullptr;
inline static xell_context_handle_t gamesContext = nullptr;
inline static bool gamesContextCanLimitFps = false;
inline static bool blockExternal = false;
inline static PFN_xellDestroyContext o_xellDestroyContext = nullptr;
@@ -39,6 +41,9 @@ class XellHooks
static void blockExternalContexts(bool state);
static bool shouldBlock(xell_context_handle_t context);
static bool canLimit();
static bool update();
static xell_result_t hkxellDestroyContext(xell_context_handle_t context);
static xell_result_t hkxellSetSleepMode(xell_context_handle_t context, const xell_sleep_params_t* param);
static xell_result_t hkxellGetSleepMode(xell_context_handle_t context, xell_sleep_params_t* param);
+5 -1
View File
@@ -26,6 +26,7 @@
#include <array>
#include <chrono>
#include <misc/IdentifyGpu.h>
#include <hooks/Xell_Hooks.h>
#define MARK_ALL_BACKENDS_CHANGED() \
for (auto& singleChangeBackend : State::Instance().changeBackend) \
@@ -4621,7 +4622,10 @@ bool MenuCommon::RenderMenu()
}
else
{
currentMethod = "Fallback";
if (XellHooks::canLimit())
currentMethod = "Game's XeLL";
else
currentMethod = "Fallback";
}
if (state.rtssReflexInjection)
+5 -2
View File
@@ -17,6 +17,7 @@
#include <d3d11.h>
#include <d3d12.h>
#include <misc/IdentifyGpu.h>
#include <hooks/Xell_Hooks.h>
#pragma intrinsic(_ReturnAddress)
@@ -123,6 +124,8 @@ static HRESULT LocalPresent(IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT
else
ReflexHooks::update(false, false);
XellHooks::update();
// Upscaler GPU time computation
if (willPresent && (fg == nullptr || !fg->IsActive() || fg->IsPaused()))
{
@@ -470,7 +473,7 @@ HRESULT STDMETHODCALLTYPE WrappedIDXGISwapChain4::Present(UINT SyncInterval, UIN
// When Reflex can't be used to limit, sleep in present
if (!State::Instance().reflexLimitsFps && State::Instance().activeFgOutput == FGOutput::NoFG &&
!IdentifyGpu::getPrimaryGpu().usesDxvk)
!IdentifyGpu::getPrimaryGpu().usesDxvk && !XellHooks::canLimit())
FrameLimit::sleep(false);
}
else
@@ -760,7 +763,7 @@ HRESULT STDMETHODCALLTYPE WrappedIDXGISwapChain4::Present1(UINT SyncInterval, UI
// When Reflex can't be used to limit, sleep in present
if (!State::Instance().reflexLimitsFps && State::Instance().activeFgOutput == FGOutput::NoFG &&
!IdentifyGpu::getPrimaryGpu().usesDxvk)
!IdentifyGpu::getPrimaryGpu().usesDxvk && !XellHooks::canLimit())
FrameLimit::sleep(false);
}
else