diff --git a/OptiScaler.ini b/OptiScaler.ini index 432b58b4..3173ff6c 100644 --- a/OptiScaler.ini +++ b/OptiScaler.ini @@ -155,6 +155,11 @@ FPTWaitForSingleObjectOnFence=auto ; ------------------------------------------------------- [XeFG] ; ------------------------------------------------------- +; Skips pre ini checks for XeFG +; Might bad IQ or cause crashes! +; true or false - Default (auto) is false +IgnoreInitChecks=auto + ; XeFG DepthInverted flag ; true or false - Default (auto) is false DepthInverted=auto diff --git a/OptiScaler/Config.cpp b/OptiScaler/Config.cpp index 843a2393..3c121744 100644 --- a/OptiScaler/Config.cpp +++ b/OptiScaler/Config.cpp @@ -163,6 +163,7 @@ bool Config::Reload(std::filesystem::path iniPath) } { + FGXeFGIgnoreInitChecks.set_from_config(readBool("XeFG", "IgnoreInitChecks")); FGXeFGDepthInverted.set_from_config(readBool("XeFG", "DepthInverted")); FGXeFGJitteredMV.set_from_config(readBool("XeFG", "JitteredMV")); FGXeFGHighResMV.set_from_config(readBool("XeFG", "HighResMV")); @@ -728,6 +729,8 @@ bool Config::SaveIni() // XeFG output { + ini.SetValue("XeFG", "IgnoreInitChecks", + GetBoolValue(Instance()->FGXeFGIgnoreInitChecks.value_for_config()).c_str()); ini.SetValue("XeFG", "DepthInverted", GetBoolValue(Instance()->FGXeFGDepthInverted.value_for_config()).c_str()); ini.SetValue("XeFG", "JitteredMV", GetBoolValue(Instance()->FGXeFGJitteredMV.value_for_config()).c_str()); ini.SetValue("XeFG", "HighResMV", GetBoolValue(Instance()->FGXeFGHighResMV.value_for_config()).c_str()); diff --git a/OptiScaler/Config.h b/OptiScaler/Config.h index 03e081c3..094a12a7 100644 --- a/OptiScaler/Config.h +++ b/OptiScaler/Config.h @@ -454,6 +454,7 @@ class Config CustomOptional FSRFGDepthAndVelocityValidNow { false }; // OptiFG - XeFG + CustomOptional FGXeFGIgnoreInitChecks { false }; CustomOptional FGXeFGDepthInverted { false }; CustomOptional FGXeFGJitteredMV { false }; CustomOptional FGXeFGHighResMV { false }; diff --git a/OptiScaler/dllmain.cpp b/OptiScaler/dllmain.cpp index 2dcb6c6b..387829e5 100644 --- a/OptiScaler/dllmain.cpp +++ b/OptiScaler/dllmain.cpp @@ -1060,6 +1060,9 @@ static void CheckQuirks() if (quirks & GameQuirk::AllowedFrameAhead2 && !Config::Instance()->FGAllowedFrameAhead.has_value()) Config::Instance()->FGAllowedFrameAhead.set_volatile_value(2); + if (quirks & GameQuirk::DisableXeFGChecks && !Config::Instance()->FGXeFGIgnoreInitChecks.has_value()) + Config::Instance()->FGXeFGIgnoreInitChecks.set_volatile_value(true); + State::Instance().gameQuirks = quirks; } diff --git a/OptiScaler/framegen/xefg/XeFG_Dx12.cpp b/OptiScaler/framegen/xefg/XeFG_Dx12.cpp index f94bdc55..e705320e 100644 --- a/OptiScaler/framegen/xefg/XeFG_Dx12.cpp +++ b/OptiScaler/framegen/xefg/XeFG_Dx12.cpp @@ -454,7 +454,8 @@ void XeFG_Dx12::Activate() if (State::Instance().activeFgInput == FGInput::Upscaler && currentFeature != nullptr) nativeAA = currentFeature->RenderWidth() == currentFeature->DisplayWidth(); - if (_swapChainContext != nullptr && _fgContext != nullptr && !_isActive && (IsLowResMV() || nativeAA)) + if (_swapChainContext != nullptr && _fgContext != nullptr && !_isActive && + (IsLowResMV() || nativeAA || Config::Instance()->FGXeFGIgnoreInitChecks.value_or_default())) { auto result = XeFGProxy::SetEnabled()(_swapChainContext, true); diff --git a/OptiScaler/menu/menu_common.cpp b/OptiScaler/menu/menu_common.cpp index ca56797f..90acc361 100644 --- a/OptiScaler/menu/menu_common.cpp +++ b/OptiScaler/menu/menu_common.cpp @@ -3409,17 +3409,18 @@ bool MenuCommon::RenderMenu() if (state.activeFgOutput == FGOutput::XeFG && state.activeFgInput != FGInput::NoFG && !state.isWorkingAsNvngx && state.currentFGSwapchain != nullptr) { - if (state.activeFgInput != FGInput::Upscaler || - (currentFeature != nullptr && !currentFeature->IsFrozen()) && XeFGProxy::InitXeFG()) + if (XeFGProxy::InitXeFG() && currentFeature != nullptr && !currentFeature->IsFrozen()) { ImGui::SeparatorText("Frame Generation (XeFG)"); + bool ignoreChecks = config->FGXeFGIgnoreInitChecks.value_or_default(); + bool nativeAA = false; if (state.activeFgInput == FGInput::Upscaler && currentFeature != nullptr) nativeAA = currentFeature->RenderWidth() == currentFeature->DisplayWidth(); auto fgOutput = reinterpret_cast(state.currentFG); - const bool correctMVs = fgOutput && fgOutput->IsLowResMV() || nativeAA; + const bool correctMVs = fgOutput && fgOutput->IsLowResMV() || nativeAA || ignoreChecks; if (!correctMVs || state.realExclusiveFullscreen) { @@ -3445,28 +3446,14 @@ bool MenuCommon::RenderMenu() ImGui::TextColored(ImVec4(1.f, 0.f, 0.f, 1.f), "Requires disabling dilated motion vectors"); - if (state.realExclusiveFullscreen) + if (!ignoreChecks && state.realExclusiveFullscreen) { cantActivate = true; ImGui::TextColored(ImVec4(1.f, 0.f, 0.f, 1.f), "Borderless display mode required"); } - if (state.isHdrActive) + if (!ignoreChecks && state.isHdrActive) { - // DXGI_FORMAT_R32G32B32A32_TYPELESS = 1 - // DXGI_FORMAT_R32G32B32A32_FLOAT - // DXGI_FORMAT_R32G32B32A32_UINT - // DXGI_FORMAT_R32G32B32A32_SINT - // DXGI_FORMAT_R32G32B32_TYPELESS - // DXGI_FORMAT_R32G32B32_FLOAT - // DXGI_FORMAT_R32G32B32_UINT - // DXGI_FORMAT_R32G32B32_SINT - // DXGI_FORMAT_R16G16B16A16_TYPELESS - // DXGI_FORMAT_R16G16B16A16_FLOAT - // DXGI_FORMAT_R16G16B16A16_UNORM - // DXGI_FORMAT_R16G16B16A16_UINT - // DXGI_FORMAT_R16G16B16A16_SNORM - // DXGI_FORMAT_R16G16B16A16_SINT = 14 if (state.currentSwapchainDesc.BufferDesc.Format > 0 && state.currentSwapchainDesc.BufferDesc.Format < 15) { @@ -3476,6 +3463,16 @@ bool MenuCommon::RenderMenu() } } + if (!correctMVs || cantActivate || ignoreChecks) + { + if (ImGui::Checkbox("Ignore Init Checks", &ignoreChecks)) + config->FGXeFGIgnoreInitChecks = ignoreChecks; + + ShowHelpMarker("Ignores all prechecks for XeFG\n" + "Don't this option to skip MV size warning for UE games!" + "It might cause crashes and bad IQ!"); + } + ImGui::BeginDisabled(!correctMVs || cantActivate); bool fgActive = config->FGEnabled.value_or_default(); diff --git a/OptiScaler/misc/Quirks.h b/OptiScaler/misc/Quirks.h index 1528e0bc..5d7e5fa7 100644 --- a/OptiScaler/misc/Quirks.h +++ b/OptiScaler/misc/Quirks.h @@ -28,6 +28,7 @@ enum class GameQuirk : uint64_t UseFSR2PatternMatching, AlwaysCaptureFSRFGSwapchain, AllowedFrameAhead2, + DisableXeFGChecks, // Quirks that are applied deeper in code CyberpunkHudlessStateOverride, @@ -87,6 +88,9 @@ static const QuirkEntry quirkTable[] = { QUIRK_ENTRY("pathofexilesteam.exe", GameQuirk::LoadD3D12Manually), QUIRK_ENTRY("pathofexile_x64steam.exe", GameQuirk::LoadD3D12Manually), + // Where Winds Meet + QUIRK_ENTRY("wwm.exe", GameQuirk::DisableXeFGChecks), + // The Last of Us Part I QUIRK_ENTRY("tlou-i.exe", GameQuirk::AllowedFrameAhead2), QUIRK_ENTRY("tlou-i-l.exe", GameQuirk::AllowedFrameAhead2), @@ -354,6 +358,8 @@ static void printQuirks(flag_set& quirks) spdlog::info("Quirk: Always capture FSR-FG swapchain"); if (quirks & GameQuirk::AllowedFrameAhead2) spdlog::info("Quirk: Allowed Frame Ahead: 2"); + if (quirks & GameQuirk::DisableXeFGChecks) + spdlog::info("Quirk: Skip pre init checks for XeFG"); return; }