diff --git a/OptiScaler/dllmain.cpp b/OptiScaler/dllmain.cpp index c3bbc4d1..f1251567 100644 --- a/OptiScaler/dllmain.cpp +++ b/OptiScaler/dllmain.cpp @@ -1298,6 +1298,9 @@ static void printQuirks(flag_set& quirks) if (quirks & GameQuirk::IgnoreValidUntilEvaluateForFG) stringQuirks.push_back("Ignore ValidUntilEvaluate resources for FG"); + if (quirks & GameQuirk::CreateSLOnThe2ndDevice) + stringQuirks.push_back("Create SL on the 2nd device"); + state->detectedQuirks.append_range(stringQuirks); for (auto& stringQuirk : stringQuirks) spdlog::info("Quirk: {}", stringQuirk); diff --git a/OptiScaler/hooks/D3D12_Hooks.cpp b/OptiScaler/hooks/D3D12_Hooks.cpp index 7432949a..e8ed52de 100644 --- a/OptiScaler/hooks/D3D12_Hooks.cpp +++ b/OptiScaler/hooks/D3D12_Hooks.cpp @@ -1426,6 +1426,24 @@ static HRESULT hkD3D12CreateDevice(IUnknown* pAdapter, D3D_FEATURE_LEVEL Minimum // if (Config::Instance()->UESpoofIntelAtomics64.value_or_default()) // UnhookDevice(); + if (State::Instance().gameQuirks & GameQuirk::CreateSLOnThe2ndDevice) + { + static void* lastDevice = nullptr; + + if (lastDevice && lastDevice != *ppDevice && StreamlineProxy::IsD3D12Inited() && + StreamlineProxy::SetD3DDevice()(*ppDevice) == sl::Result::eOk) + { + auto reflexConst = sl::ReflexOptions {}; + reflexConst.mode = sl::ReflexMode::eLowLatency; + reflexConst.useMarkersToOptimize = false; + + auto result = StreamlineProxy::ReflexSetOptions()(reflexConst); + LOG_TRACE("ReflexSetOptions"); + } + + lastDevice = *ppDevice; + } + HookToDevice(State::Instance().currentD3D12Device); _d3d12Captured = true; diff --git a/OptiScaler/misc/Quirks.h b/OptiScaler/misc/Quirks.h index c52732c6..0e3fe3b1 100644 --- a/OptiScaler/misc/Quirks.h +++ b/OptiScaler/misc/Quirks.h @@ -60,6 +60,7 @@ enum class GameQuirk : uint64_t ForceDepthD32S8, PregmataFixDLSSModes, IgnoreValidUntilEvaluateForFG, + CreateSLOnThe2ndDevice, // Don't forget to add the new entry to printQuirks _ }; @@ -359,9 +360,15 @@ static const QuirkEntry quirkTable[] = { QUIRK_ENTRY("u4.exe", GameQuirk::DisableDxgiSpoofing, GameQuirk::DisableHudfix), QUIRK_ENTRY("u4-l.exe", GameQuirk::DisableDxgiSpoofing, GameQuirk::DisableHudfix), + // The Witcher 3 + // SL spoof enough to unlock everything DLSS/No spoof needed for DLSS inputs, + // WAR for our SL having to init on the real device that the game will actually be using + // early in boot it creates a device that it later *needs* to properly destroy + QUIRK_ENTRY("witcher3.exe", GameQuirk::DisableDxgiSpoofing, GameQuirk::CreateSLOnThe2ndDevice), + // SL spoof enough to unlock everything DLSS/No spoof needed for DLSS inputs // - // The Witcher 3, Alan Wake 2, Crysis 3 Remastered, Collection, Warhammer 40,000: Darktide, + // Alan Wake 2, Crysis 3 Remastered, Collection, Warhammer 40,000: Darktide, // Observer: System Redux, Sackboy: A Big Adventure, Hellblade: Senua's Sacrifice, // Pumpkin Jack, Rise of the Ronin, DYNASTY WARRIORS: ORIGINS, Crysis Remastered, // Crysis 2 Remastered, Mortal Shell, Sekiro: Shadows Die Twice (for SekiroTSR mod), @@ -371,7 +378,6 @@ static const QuirkEntry quirkTable[] = { // Assassin's Creed Shadows, Farming Simulator 2025, Nioh 3, // FATAL FRAME II: Crimson Butterfly REMAKE, OUTRIDERS, MOUSE: P.I. For Hire, // Yet Another Zombie Survivors, Voodoo Fishin', Forza Horizon 6 - QUIRK_ENTRY("witcher3.exe", GameQuirk::DisableDxgiSpoofing), QUIRK_ENTRY("crysis3remastered.exe", GameQuirk::DisableDxgiSpoofing), QUIRK_ENTRY("tll.exe", GameQuirk::DisableDxgiSpoofing), QUIRK_ENTRY("tll-l.exe", GameQuirk::DisableDxgiSpoofing), diff --git a/OptiScaler/proxies/Streamline_Proxy.h b/OptiScaler/proxies/Streamline_Proxy.h index 55620ec0..16711179 100644 --- a/OptiScaler/proxies/Streamline_Proxy.h +++ b/OptiScaler/proxies/Streamline_Proxy.h @@ -359,16 +359,23 @@ class StreamlineProxy State::Instance().optiSlReflex = StreamlineProxy::HookStreamlineReflex(); State::Instance().optiSlPCL = StreamlineProxy::HookStreamlinePCL(); - auto result = _slSetD3DDevice(device); - - if (result == sl::Result::eOk) + if (State::Instance().gameQuirks & GameQuirk::CreateSLOnThe2ndDevice) { - auto reflexConst = sl::ReflexOptions {}; - reflexConst.mode = sl::ReflexMode::eOff; - reflexConst.useMarkersToOptimize = false; + // slSetD3DDevice moved to hkD3D12CreateDevice + _isD3D12Inited = true; + } + else + { + auto result = _slSetD3DDevice(device); + if (result == sl::Result::eOk) + { + auto reflexConst = sl::ReflexOptions {}; + reflexConst.mode = sl::ReflexMode::eOff; + reflexConst.useMarkersToOptimize = false; - result = _slReflexSetOptions(reflexConst); - _isD3D12Inited = result == sl::Result::eOk; + result = _slReflexSetOptions(reflexConst); + _isD3D12Inited = result == sl::Result::eOk; + } } }