Add SL spoofing to Opti's instance of sl.dlss_g

This commit is contained in:
FakeMichau
2026-04-02 20:09:36 +02:00
parent c3919c54f8
commit d8586fac2e
4 changed files with 151 additions and 21 deletions
+7 -4
View File
@@ -167,14 +167,17 @@ HMODULE LibraryLoadHooks::LoadLibraryCheckW(std::wstring libName, LPCWSTR lpLibF
}
// sl.dlss_g.dll
if (hookOptiDlls && (CheckDllNameW(&libName, &slDlssgNamesW) ||
(normalizedPath.contains(L"\\versions\\") && normalizedPath.contains(L"\\sl_dlss_g_"))))
if ((CheckDllNameW(&libName, &slDlssgNamesW) ||
(normalizedPath.contains(L"\\versions\\") && normalizedPath.contains(L"\\sl_dlss_g_"))))
{
auto dlssgModule = NtdllProxy::LoadLibraryExW_Ldr(lpLibFullPath, NULL, 0);
if (dlssgModule != nullptr && dlssgModule != State::Instance().optiSlDLSSG)
if (dlssgModule != nullptr)
{
StreamlineHooks::hookDlssg(dlssgModule);
if (!normalizedPath.contains(L"\\opti_dlls") && dlssgModule != State::Instance().optiSlDLSSG)
StreamlineHooks::hookDlssg(dlssgModule);
else
StreamlineHooks::hookLocalDlssg(dlssgModule);
}
else
{
+129 -14
View File
@@ -48,6 +48,10 @@ StreamlineHooks::PFN_slOnPluginLoad StreamlineHooks::o_dlssg_slOnPluginLoad = nu
decltype(&slDLSSGSetOptions) StreamlineHooks::o_slDLSSGSetOptions = nullptr;
decltype(&slDLSSGGetState) StreamlineHooks::o_slDLSSGGetState = nullptr;
// Local DLSSG
StreamlineHooks::PFN_slGetPluginFunction StreamlineHooks::o_local_dlssg_slGetPluginFunction = nullptr;
StreamlineHooks::PFN_slOnPluginLoad StreamlineHooks::o_local_dlssg_slOnPluginLoad = nullptr;
// Reflex
StreamlineHooks::PFN_slGetPluginFunction StreamlineHooks::o_reflex_slGetPluginFunction = nullptr;
StreamlineHooks::PFN_slSetConstants_sl1 StreamlineHooks::o_reflex_slSetConstants_sl1 = nullptr;
@@ -409,7 +413,7 @@ void StreamlineHooks::hookSystemCaps(sl::param::IParameters* params)
}
}
uint32_t StreamlineHooks::getSystemCapsArch()
uint32_t StreamlineHooks::getSystemCapsArch(SystemCaps* altSystemCaps)
{
uint32_t highestArch = 0;
@@ -418,9 +422,10 @@ uint32_t StreamlineHooks::getSystemCapsArch()
{
if (State::Instance().streamlineVersion.major > 1)
{
if (systemCaps)
auto caps = altSystemCaps != nullptr ? altSystemCaps : systemCaps;
if (caps)
{
for (auto& adapter : systemCaps->adapters)
for (auto& adapter : caps->adapters)
{
if (adapter.architecture > highestArch)
highestArch = adapter.architecture;
@@ -448,23 +453,25 @@ uint32_t StreamlineHooks::getSystemCapsArch()
return highestArch;
}
void StreamlineHooks::setArch(uint32_t arch)
void StreamlineHooks::setArch(uint32_t arch, SystemCaps* altSystemCaps)
{
static auto primaryGpu = IdentifyGpu::getPrimaryGpu();
if (State::Instance().streamlineVersion.major > 1)
{
if (systemCaps)
// Assumes that altCaps are always for SL2+
auto caps = altSystemCaps != nullptr ? altSystemCaps : systemCaps;
if (caps)
{
for (uint32_t i = 0; i < systemCaps->gpuCount; i++)
for (uint32_t i = 0; i < caps->gpuCount; i++)
{
systemCaps->adapters[i].architecture = arch;
systemCaps->adapters[i].vendor = VendorId::Nvidia;
caps->adapters[i].architecture = arch;
caps->adapters[i].vendor = VendorId::Nvidia;
}
if (fakenvapi::isUsingAsMainNvapi() || primaryGpu.vendorId != VendorId::Nvidia)
systemCaps->driverVersionMajor = 999;
caps->driverVersionMajor = 999;
systemCaps->hwsSupported = true;
caps->hwsSupported = true;
}
}
else if (State::Instance().streamlineVersion.major == 1)
@@ -483,7 +490,7 @@ void StreamlineHooks::setArch(uint32_t arch)
}
// Spoof arch based on feature and current arch
void StreamlineHooks::spoofArch(uint32_t currentArch, sl::Feature feature)
void StreamlineHooks::spoofArch(uint32_t currentArch, sl::Feature feature, SystemCaps* altSystemCaps)
{
constexpr uint32_t maxArch = 0xFFFFFFFF;
@@ -491,7 +498,7 @@ void StreamlineHooks::spoofArch(uint32_t currentArch, sl::Feature feature)
if (feature == sl::kFeatureDLSS)
{
if (currentArch < NV_GPU_ARCHITECTURE_TU100)
return setArch(maxArch);
return setArch(maxArch, altSystemCaps);
}
// Don't spoof DLSSD at all
@@ -504,13 +511,13 @@ void StreamlineHooks::spoofArch(uint32_t currentArch, sl::Feature feature)
else if (feature == sl::kFeatureDLSS_G)
{
if (currentArch < NV_GPU_ARCHITECTURE_AD100)
return setArch(maxArch);
return setArch(maxArch, altSystemCaps);
}
else if (feature == sl::kFeatureReflex || feature == sl::kFeaturePCL)
{
if (fakenvapi::isUsingAsMainNvapi())
return setArch(maxArch);
return setArch(maxArch, altSystemCaps);
}
}
@@ -643,6 +650,55 @@ bool StreamlineHooks::hkdlssg_slOnPluginLoad(sl::param::IParameters* params, con
return result;
}
bool StreamlineHooks::hklocal_dlssg_slOnPluginLoad(sl::param::IParameters* params, const char* loaderJSON,
const char** pluginJSON)
{
LOG_FUNC();
// TODO: do it better than "static" and hoping for the best
static std::string config;
bool shouldSpoofArch = Config::Instance()->StreamlineSpoofing.value_or_default();
uint32_t currentArch = 0;
SystemCaps* localSystemCaps = nullptr;
if (shouldSpoofArch)
{
sl::param::getPointerParam(params, sl::param::common::kSystemCaps, &localSystemCaps);
if (localSystemCaps)
{
currentArch = getSystemCapsArch(localSystemCaps);
spoofArch(currentArch, sl::kFeatureDLSS_G, localSystemCaps);
}
}
auto result = o_local_dlssg_slOnPluginLoad(params, loaderJSON, pluginJSON);
if (shouldSpoofArch && localSystemCaps)
setArch(currentArch, localSystemCaps);
nlohmann::json configJson = nlohmann::json::parse(*pluginJSON);
if (configJson.contains("/external/hws/required"_json_pointer))
configJson["external"]["hws"]["required"] = false; // disable eHardwareSchedulingRequired
if (Config::Instance()->VulkanExtensionSpoofing.value_or_default())
{
if (configJson.contains("/external/vk/instance/extensions"_json_pointer))
configJson["external"]["vk"]["instance"]["extensions"].clear();
if (configJson.contains("/external/vk/device/extensions"_json_pointer))
configJson["external"]["vk"]["device"]["extensions"].clear();
}
config = configJson.dump();
*pluginJSON = config.c_str();
return result;
}
sl::Result StreamlineHooks::hkslSetConstants(const sl::Constants& values, const sl::FrameToken& frame,
const sl::ViewportHandle& viewport)
{
@@ -941,6 +997,19 @@ void* StreamlineHooks::hkdlssg_slGetPluginFunction(const char* functionName)
return o_dlssg_slGetPluginFunction(functionName);
}
void* StreamlineHooks::hklocal_dlssg_slGetPluginFunction(const char* functionName)
{
// LOG_DEBUG("{}", functionName);
if (strcmp(functionName, "slOnPluginLoad") == 0 && Config::Instance()->FGOutput == FGOutput::DLSSGWithNukems)
{
o_local_dlssg_slOnPluginLoad = (PFN_slOnPluginLoad) o_local_dlssg_slGetPluginFunction(functionName);
return &hklocal_dlssg_slOnPluginLoad;
}
return o_local_dlssg_slGetPluginFunction(functionName);
}
bool StreamlineHooks::hkreflex_slSetConstants_sl1(const void* data, uint32_t frameIndex, uint32_t id)
{
// Streamline v1's version of slReflexSetOptions + slPCLSetMarker
@@ -1404,6 +1473,52 @@ void StreamlineHooks::hookDlssg(HMODULE slDlssg)
}
}
// Local SL DLSSG
void StreamlineHooks::unhookLocalDlssg()
{
LOG_FUNC();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
if (o_local_dlssg_slGetPluginFunction)
{
DetourDetach(&(PVOID&) o_local_dlssg_slGetPluginFunction, hklocal_dlssg_slGetPluginFunction);
o_local_dlssg_slGetPluginFunction = nullptr;
}
DetourTransactionCommit();
}
void StreamlineHooks::hookLocalDlssg(HMODULE slDlssg)
{
LOG_FUNC();
if (!slDlssg)
{
LOG_WARN("Dlssg module in NULL");
return;
}
if (o_local_dlssg_slGetPluginFunction)
unhookLocalDlssg();
o_local_dlssg_slGetPluginFunction =
reinterpret_cast<PFN_slGetPluginFunction>(KernelBaseProxy::GetProcAddress_()(slDlssg, "slGetPluginFunction"));
if (o_local_dlssg_slGetPluginFunction != nullptr)
{
LOG_TRACE("Hooking slGetPluginFunction in local sl.dlssg");
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&) o_local_dlssg_slGetPluginFunction, hklocal_dlssg_slGetPluginFunction);
DetourTransactionCommit();
}
}
// SL REFLEX
void StreamlineHooks::unhookReflex()
+14 -3
View File
@@ -148,6 +148,9 @@ class StreamlineHooks
static void unhookDlssg();
static void hookDlssg(HMODULE slDlssg);
static void unhookLocalDlssg();
static void hookLocalDlssg(HMODULE slDlssg);
static void unhookReflex();
static void hookReflex(HMODULE slReflex);
@@ -172,9 +175,9 @@ class StreamlineHooks
static SystemCaps* systemCaps;
static SystemCapsSl15* systemCapsSl15;
static void hookSystemCaps(sl::param::IParameters* params);
static uint32_t getSystemCapsArch();
static void setArch(uint32_t arch);
static void spoofArch(uint32_t currentArch, sl::Feature feature);
static uint32_t getSystemCapsArch(SystemCaps* altSystemCaps = nullptr);
static void setArch(uint32_t arch, SystemCaps* altSystemCaps = nullptr);
static void spoofArch(uint32_t currentArch, sl::Feature feature, SystemCaps* altSystemCaps = nullptr);
// Interposer
static decltype(&slInit) o_slInit;
@@ -233,6 +236,14 @@ class StreamlineHooks
const sl::DLSSGOptions* options);
static void* hkdlssg_slGetPluginFunction(const char* functionName);
// Local DLSSG
static PFN_slGetPluginFunction o_local_dlssg_slGetPluginFunction;
static PFN_slOnPluginLoad o_local_dlssg_slOnPluginLoad;
static bool hklocal_dlssg_slOnPluginLoad(sl::param::IParameters* params, const char* loaderJSON,
const char** pluginJSON);
static void* hklocal_dlssg_slGetPluginFunction(const char* functionName);
// Reflex
static sl::ReflexMode reflexGamesLastMode;
static PFN_slGetPluginFunction o_reflex_slGetPluginFunction;
+1
View File
@@ -7,6 +7,7 @@
#include <proxies/Ntdll_Proxy.h>
#include <proxies/KernelBase_Proxy.h>
#include <hooks/Streamline_Hooks.h>
#include <sl.h>
#include <sl_pcl.h>