diff --git a/OptiScaler/DllNames.h b/OptiScaler/DllNames.h
index a36d59fd..3dceb649 100644
--- a/OptiScaler/DllNames.h
+++ b/OptiScaler/DllNames.h
@@ -145,6 +145,7 @@ DEFINE_NAME_VECTORS(ffxDx12FG, "amd_fidelityfx_framegeneration_dx12");
DEFINE_NAME_VECTORS(ffxDx12Denoiser, "amd_fidelityfx_denoiser_dx12");
DEFINE_NAME_VECTORS(ffxDx12Radiance, "amd_fidelityfx_radiancecache_dx12");
DEFINE_NAME_VECTORS(ffxVk, "amd_fidelityfx_vk");
+DEFINE_NAME_VECTORS(uell, "main");
inline static bool CompareFileName(std::string* first, std::string* second)
{
diff --git a/OptiScaler/OptiScaler.vcxproj b/OptiScaler/OptiScaler.vcxproj
index 6ca7094f..04f84167 100644
--- a/OptiScaler/OptiScaler.vcxproj
+++ b/OptiScaler/OptiScaler.vcxproj
@@ -399,6 +399,7 @@ copy NUL "$(SolutionDir)x64\Release\a\!! EXTRACT ALL FILES TO GAME FOLDER !!" /Y
+
@@ -623,6 +624,7 @@ copy NUL "$(SolutionDir)x64\Release\a\!! EXTRACT ALL FILES TO GAME FOLDER !!" /Y
+
diff --git a/OptiScaler/OptiScaler.vcxproj.filters b/OptiScaler/OptiScaler.vcxproj.filters
index ad0847db..6941a506 100644
--- a/OptiScaler/OptiScaler.vcxproj.filters
+++ b/OptiScaler/OptiScaler.vcxproj.filters
@@ -845,6 +845,18 @@
Header Files
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
@@ -1316,6 +1328,12 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
diff --git a/OptiScaler/State.h b/OptiScaler/State.h
index 7289c9f7..cf663bce 100644
--- a/OptiScaler/State.h
+++ b/OptiScaler/State.h
@@ -169,6 +169,7 @@ class State
bool reflexShowWarning = false;
bool rtssReflexInjection = false;
bool fakenvapiReloadLowLatency = false;
+ bool usingUeLL = false;
UINT64 reflexFrameId = 0;
UINT64 frameCount = 0;
diff --git a/OptiScaler/hooks/LibraryLoad_Hooks.cpp b/OptiScaler/hooks/LibraryLoad_Hooks.cpp
index f8088319..64163e16 100644
--- a/OptiScaler/hooks/LibraryLoad_Hooks.cpp
+++ b/OptiScaler/hooks/LibraryLoad_Hooks.cpp
@@ -30,6 +30,7 @@
#include
#include
+#include
// #define LOG_LIB_OPERATIONS
@@ -524,6 +525,28 @@ HMODULE LibraryLoadHooks::LoadLibraryCheckW(std::wstring libName, LPCWSTR lpLibF
return module;
}
+ // UeLL
+ // This will try to hook all UE4SS dll mods but only our one should be exporting those functions
+ if (CheckDllNameW(&libName, &uellNamesW))
+ {
+ LOG_INFO("{} call!", libNameA);
+
+ auto module = NtdllProxy::LoadLibraryExW_Ldr(libName.c_str(), NULL, NULL);
+
+ auto setTickStartCallback =
+ (PFN_setTickCallback) KernelBaseProxy::GetProcAddress_()(module, "setTickStartCallback");
+ auto setTickEndCallback =
+ (PFN_setTickCallback) KernelBaseProxy::GetProcAddress_()(module, "setTickEndCallback");
+
+ if (setTickStartCallback)
+ setTickStartCallback(UeLowLatency::tickStart);
+
+ if (setTickEndCallback)
+ setTickEndCallback(UeLowLatency::tickEnd);
+
+ return module;
+ }
+
CheckModulesInMemory();
return nullptr;
diff --git a/OptiScaler/hooks/Reflex_Hooks.cpp b/OptiScaler/hooks/Reflex_Hooks.cpp
index f5f4819e..7ae7dbe7 100644
--- a/OptiScaler/hooks/Reflex_Hooks.cpp
+++ b/OptiScaler/hooks/Reflex_Hooks.cpp
@@ -33,6 +33,13 @@ NvAPI_Status ReflexHooks::hkNvAPI_D3D_SetSleepMode(IUnknown* pDev, NV_SET_SLEEP_
if (_minimumIntervalUs != 0)
pSetSleepModeParams->minimumIntervalUs = _minimumIntervalUs;
+ if (State::Instance().usingUeLL)
+ {
+ pSetSleepModeParams->minimumIntervalUs = 0;
+ pSetSleepModeParams->bLowLatencyMode = false;
+ pSetSleepModeParams->bLowLatencyBoost = false;
+ }
+
if (State::Instance().activeFgOutput == FGOutput::XeFG)
return nvapi_calls::NvAPI_D3D_SetSleepMode(pDev, pSetSleepModeParams);
@@ -45,6 +52,11 @@ NvAPI_Status ReflexHooks::hkNvAPI_D3D_Sleep(IUnknown* pDev)
LOG_FUNC();
#endif
+ if (State::Instance().usingUeLL)
+ {
+ return NVAPI_OK;
+ }
+
static bool skip = false;
if ((State::Instance().activeFgOutput == FGOutput::DLSSG ||
State::Instance().activeFgOutput == FGOutput::DLSSGWithNvngx) &&
@@ -64,7 +76,7 @@ NvAPI_Status ReflexHooks::hkNvAPI_D3D_Sleep(IUnknown* pDev)
StreamlineProxy::ReflexSleep()(*frameToken);
skip = false;
- return NvAPI_Status::NVAPI_OK;
+ return NVAPI_OK;
}
else
{
@@ -86,6 +98,11 @@ NvAPI_Status ReflexHooks::hkNvAPI_D3D_GetLatency(IUnknown* pDev, NV_LATENCY_RESU
LOG_FUNC();
#endif
+ if (State::Instance().usingUeLL)
+ {
+ return NVAPI_OK;
+ }
+
if (State::Instance().activeFgOutput == FGOutput::XeFG)
return nvapi_calls::NvAPI_D3D_GetLatency(pDev, pGetLatencyParams);
@@ -120,6 +137,11 @@ NvAPI_Status ReflexHooks::hkNvAPI_D3D_SetLatencyMarker(IUnknown* pDev,
_lastFrameId[pSetLatencyMarkerParams->markerType] = pSetLatencyMarkerParams->frameID;
_lastDev[pSetLatencyMarkerParams->markerType] = pDev;
+ if (State::Instance().usingUeLL)
+ {
+ return NVAPI_OK;
+ }
+
static bool skip[20] = {};
if (pSetLatencyMarkerParams->markerType == SIMULATION_START)
@@ -297,6 +319,11 @@ NvAPI_Status ReflexHooks::hkNvAPI_D3D12_SetAsyncFrameMarker(ID3D12CommandQueue*
_lastAsyncMarkerFrameId = pSetAsyncFrameMarkerParams->frameID;
+ if (State::Instance().usingUeLL)
+ {
+ return NVAPI_OK;
+ }
+
if (pSetAsyncFrameMarkerParams->markerType == OUT_OF_BAND_PRESENT_START &&
State::Instance().streamlineVersion.major < 2)
{
diff --git a/OptiScaler/hooks/Reflex_Hooks.h b/OptiScaler/hooks/Reflex_Hooks.h
index 5cf954e7..0c8e1192 100644
--- a/OptiScaler/hooks/Reflex_Hooks.h
+++ b/OptiScaler/hooks/Reflex_Hooks.h
@@ -90,5 +90,5 @@ class ReflexHooks
static void update(bool optiFg_FgState, bool isVulkan);
// 0 - disables the fps cap
- inline static void setFPSLimit(float fps);
+ static void setFPSLimit(float fps);
};
diff --git a/OptiScaler/misc/UeLowLatency.cpp b/OptiScaler/misc/UeLowLatency.cpp
new file mode 100644
index 00000000..6fd3d7be
--- /dev/null
+++ b/OptiScaler/misc/UeLowLatency.cpp
@@ -0,0 +1,73 @@
+#include "pch.h"
+#include "UeLowLatency.h"
+#include
+
+#include "nvapi/fakenvapi/low_latency_tech/ll_antilag2.h"
+// #include "nvapi/fakenvapi/low_latency_tech/ll_xell.h"
+#include "nvapi/fakenvapi/low_latency_tech/ll_latencyflex.h"
+
+void UeLowLatency::init()
+{
+ if (lowLatencyFeature)
+ return;
+
+ lowLatencyFeature = new AntiLag2();
+
+ // lowLatencyFeature = new LatencyFlex();
+ // Config::Instance()->FN_LatencyFlexMode.set_volatile_value(LFXMode::ReflexIDs);
+
+ bool inited = false;
+
+ if (auto dx11device = State::Instance().currentD3D11Device; dx11device)
+ {
+ inited = lowLatencyFeature->init(dx11device);
+ }
+
+ if (auto dx12device = State::Instance().currentD3D12Device; !inited && dx12device)
+ {
+ inited = lowLatencyFeature->init(dx12device);
+ }
+
+ State::Instance().usingUeLL = inited;
+
+ if (inited)
+ {
+ LOG_DEBUG("Inited UeLowLatency");
+
+ SleepMode mode {};
+ mode.low_latency_enabled = true;
+ lowLatencyFeature->set_sleep_mode(&mode);
+
+ ReflexHooks::setFPSLimit(0);
+ }
+ else
+ {
+ delete lowLatencyFeature;
+ lowLatencyFeature = nullptr;
+ }
+}
+
+void UeLowLatency::tickStart(int64_t frameId, float DeltaSeconds, bool bIdleMode)
+{
+ LOG_FUNC();
+
+ if (!lowLatencyFeature)
+ UeLowLatency::init();
+
+ lowLatencyFeature->sleep();
+
+ MarkerParams marker {};
+ marker.marker_type = MarkerType::SIMULATION_START;
+ marker.frame_id = frameId;
+ lowLatencyFeature->set_marker(State::Instance().currentD3D12Device, &marker);
+}
+
+void UeLowLatency::tickEnd(int64_t frameId, float DeltaSeconds, bool bIdleMode)
+{
+ LOG_FUNC();
+
+ MarkerParams marker {};
+ marker.marker_type = MarkerType::SIMULATION_END;
+ marker.frame_id = frameId;
+ lowLatencyFeature->set_marker(State::Instance().currentD3D12Device, &marker);
+}
diff --git a/OptiScaler/misc/UeLowLatency.h b/OptiScaler/misc/UeLowLatency.h
new file mode 100644
index 00000000..c82a125d
--- /dev/null
+++ b/OptiScaler/misc/UeLowLatency.h
@@ -0,0 +1,16 @@
+#pragma once
+
+#include "nvapi/fakenvapi/low_latency_tech/low_latency_tech.h"
+
+typedef void (*PFN_FLTickExternal)(int64_t frameId, float DeltaSeconds, bool bIdleMode);
+typedef void (*PFN_setTickCallback)(PFN_FLTickExternal callback);
+
+class UeLowLatency
+{
+ inline static LowLatencyTech* lowLatencyFeature = nullptr;
+
+ public:
+ static void init();
+ static void tickEnd(int64_t frameId, float DeltaSeconds, bool bIdleMode);
+ static void tickStart(int64_t frameId, float DeltaSeconds, bool bIdleMode);
+};