mirror of
https://github.com/optiscaler/OptiScaler.git
synced 2026-08-24 23:26:50 +00:00
456 lines
11 KiB
C++
456 lines
11 KiB
C++
#pragma once
|
|
#include "upscalers/IFeature.h"
|
|
#include "framegen/IFGFeature_Dx12.h"
|
|
#include <inputs/FG/Streamline_Inputs_Dx12.h>
|
|
#include "misc/Quirks.h"
|
|
|
|
#include <set>
|
|
#include <deque>
|
|
#include <vulkan/vulkan.h>
|
|
#include <ankerl/unordered_dense.h>
|
|
#include <mutex>
|
|
|
|
typedef enum API
|
|
{
|
|
NotSelected = 0,
|
|
DX11,
|
|
DX12,
|
|
Vulkan,
|
|
} API;
|
|
|
|
enum class FGPreset : uint32_t
|
|
{
|
|
NoFG,
|
|
OptiFG,
|
|
Nukems,
|
|
};
|
|
|
|
enum class FrameTimeSource : uint32_t
|
|
{
|
|
Input,
|
|
Opti,
|
|
Zero,
|
|
};
|
|
|
|
enum class FGInput : uint32_t
|
|
{
|
|
NoFG,
|
|
Nukems,
|
|
FSRFG,
|
|
DLSSG, // technically Streamline inputs
|
|
XeFG,
|
|
Upscaler, // OptiFG
|
|
FSRFG30,
|
|
};
|
|
|
|
enum class FGOutput : uint32_t
|
|
{
|
|
NoFG,
|
|
Nukems,
|
|
FSRFG,
|
|
DLSSG,
|
|
XeFG
|
|
};
|
|
|
|
enum class WorkingMode : uint32_t
|
|
{
|
|
Dxgi,
|
|
D3d12,
|
|
Nvngx,
|
|
Other,
|
|
};
|
|
|
|
typedef struct CapturedHudlessInfo
|
|
{
|
|
UINT64 usageCount = 1;
|
|
UINT captureInfo = 0;
|
|
bool enabled = true;
|
|
} captured_hudless_info;
|
|
|
|
class State
|
|
{
|
|
public:
|
|
static State& Instance()
|
|
{
|
|
static State instance;
|
|
return instance;
|
|
}
|
|
|
|
std::string GameName;
|
|
std::string GameExe;
|
|
ankerl::unordered_dense::map<void*, std::string> DeviceAdapterNames;
|
|
|
|
bool NvngxDx11Inited = false;
|
|
bool NvngxDx12Inited = false;
|
|
bool NvngxVkInited = false;
|
|
|
|
flag_set<GameQuirk> gameQuirks;
|
|
bool isOptiPatcherSucceed = false;
|
|
|
|
// Reseting on creation of new feature
|
|
std::optional<bool> AutoExposure;
|
|
|
|
// FG
|
|
UINT64 FGLastFrame = 0;
|
|
|
|
// DLSSG
|
|
bool NukemsFilesAvailable = false;
|
|
bool DLSSGDebugView = false;
|
|
bool DLSSGInterpolatedOnly = false;
|
|
uint32_t delayMenuRenderBy = 0;
|
|
UINT64 DLSSGLastFrame = 0;
|
|
|
|
// FSR Common
|
|
float lastFsrCameraNear = 0.0f;
|
|
float lastFsrCameraFar = 0.0f;
|
|
|
|
// Frame Generation
|
|
FGInput activeFgInput = FGInput::NoFG;
|
|
FGOutput activeFgOutput = FGOutput::NoFG;
|
|
|
|
// Streamline FG inputs
|
|
Sl_Inputs_Dx12 slFGInputs = {};
|
|
|
|
// OptiFG
|
|
bool FGPresentIsCalled = false;
|
|
bool FGonlyGenerated = false;
|
|
bool FGHudlessCompare = false;
|
|
bool FGchanged = false;
|
|
bool SCchanged = false;
|
|
bool skipHeapCapture = false;
|
|
|
|
bool FGcaptureResources = false;
|
|
size_t FGcapturedResourceCount = false;
|
|
bool FGresetCapturedResources = false;
|
|
bool FGonlyUseCapturedResources = false;
|
|
|
|
bool FSRFGFTPchanged = false;
|
|
bool FSRFGInputActive = false;
|
|
|
|
bool FGResizing = false;
|
|
|
|
ankerl::unordered_dense::map<void*, CapturedHudlessInfo> CapturedHudlesses;
|
|
bool ClearCapturedHudlesses = false;
|
|
|
|
// NVNGX init parameters
|
|
uint64_t NVNGX_ApplicationId = 1337;
|
|
std::wstring NVNGX_ApplicationDataPath;
|
|
std::string NVNGX_ProjectId;
|
|
NVSDK_NGX_Version NVNGX_Version {};
|
|
const NVSDK_NGX_FeatureCommonInfo* NVNGX_FeatureInfo = nullptr;
|
|
std::vector<std::wstring> NVNGX_FeatureInfo_Paths;
|
|
NVSDK_NGX_LoggingInfo NVNGX_Logger { nullptr, NVSDK_NGX_LOGGING_LEVEL_OFF, false };
|
|
NVSDK_NGX_EngineType NVNGX_Engine = NVSDK_NGX_ENGINE_TYPE_CUSTOM;
|
|
std::string NVNGX_EngineVersion;
|
|
std::optional<std::wstring> NVNGX_DLSS_Path;
|
|
std::optional<std::wstring> NVNGX_DLSSD_Path;
|
|
std::optional<std::wstring> NVNGX_DLSSG_Path;
|
|
|
|
// NGX OTA
|
|
std::string NGX_OTA_Dlss;
|
|
std::string NGX_OTA_Dlssd;
|
|
|
|
feature_version streamlineVersion = { 0, 0, 0 };
|
|
|
|
API api = API::NotSelected;
|
|
API swapchainApi = API::NotSelected;
|
|
|
|
// Framerate
|
|
bool reflexLimitsFps = false;
|
|
bool reflexShowWarning = false;
|
|
bool rtssReflexInjection = false;
|
|
UINT64 reflexFrameId = 0;
|
|
UINT64 frameCount = 0;
|
|
|
|
// for realtime changes
|
|
ankerl::unordered_dense::map<unsigned int, bool> changeBackend;
|
|
std::string newBackend = "";
|
|
|
|
// XeSS debug stuff
|
|
bool xessDebug = false;
|
|
int xessDebugFrames = 5;
|
|
float lastMipBias = 100.0f;
|
|
float lastMipBiasMax = -100.0f;
|
|
|
|
int xefgMaxInterpolationCount = 1;
|
|
bool WAR_xefgRequestFGToggle = false;
|
|
|
|
// DLSS
|
|
bool dlssPresetsOverriddenExternally = false;
|
|
bool dlssPresetsOverridenByOpti = false;
|
|
uint32_t dlssRenderPresetExternal = 0;
|
|
uint32_t dlssRenderPresetDLAA = 0;
|
|
uint32_t dlssRenderPresetUltraQuality = 0;
|
|
uint32_t dlssRenderPresetQuality = 0;
|
|
uint32_t dlssRenderPresetBalanced = 0;
|
|
uint32_t dlssRenderPresetPerformance = 0;
|
|
uint32_t dlssRenderPresetUltraPerformance = 0;
|
|
|
|
// DLSSD
|
|
bool dlssdPresetsOverriddenExternally = false;
|
|
bool dlssdPresetsOverridenByOpti = false;
|
|
uint32_t dlssdRenderPresetExternal = 0;
|
|
uint32_t dlssdRenderPresetDLAA = 0;
|
|
uint32_t dlssdRenderPresetUltraQuality = 0;
|
|
uint32_t dlssdRenderPresetQuality = 0;
|
|
uint32_t dlssdRenderPresetBalanced = 0;
|
|
uint32_t dlssdRenderPresetPerformance = 0;
|
|
uint32_t dlssdRenderPresetUltraPerformance = 0;
|
|
|
|
// Spoofing
|
|
bool skipSpoofing = false;
|
|
// For DXVK, it calls DXGI which cause softlock
|
|
bool skipDxgiLoadChecks = false;
|
|
bool skipParentWrapping = false;
|
|
|
|
// quirks
|
|
std::vector<std::string> detectedQuirks {};
|
|
|
|
// FFX
|
|
std::vector<const char*> ffxUpscalerVersionNames {};
|
|
std::vector<uint64_t> ffxUpscalerVersionIds {};
|
|
std::vector<const char*> ffxFGVersionNames {};
|
|
std::vector<uint64_t> ffxFGVersionIds {};
|
|
std::optional<uint32_t> currentFsr4Model {};
|
|
|
|
// Linux checks
|
|
bool isRunningOnLinux = false;
|
|
bool isRunningOnDXVK = false;
|
|
|
|
// Other checks
|
|
bool isRunningOnNvidia = false;
|
|
std::optional<bool> isRunningOnRDNA4;
|
|
bool isPascalOrOlder = false;
|
|
WorkingMode workingMode = WorkingMode::Other;
|
|
|
|
// Vulkan stuff
|
|
bool vulkanCreatingSC = false;
|
|
bool creatingD3DDevice = false;
|
|
bool vulkanSkipHooks = false;
|
|
VkInstance VulkanInstance = nullptr;
|
|
|
|
// Framegraph
|
|
std::deque<double> upscaleTimes;
|
|
std::deque<double> frameTimes;
|
|
double lastFGFrameTime = 0.0;
|
|
double presentFrameTime = 0.0;
|
|
std::mutex frameTimeMutex;
|
|
|
|
// Version check
|
|
std::mutex versionCheckMutex;
|
|
bool versionCheckInProgress = false;
|
|
bool versionCheckCompleted = false;
|
|
bool updateAvailable = false;
|
|
std::string latestVersionTag;
|
|
std::string latestVersionUrl;
|
|
std::string versionCheckError;
|
|
|
|
// Swapchain info
|
|
float screenWidth = 800.0;
|
|
float screenHeight = 450.0;
|
|
bool realExclusiveFullscreen = false;
|
|
bool SCExclusiveFullscreen = false;
|
|
bool SCAllowTearing = false;
|
|
UINT SCLastFlags = 0;
|
|
|
|
// HDR
|
|
std::vector<IUnknown*> SCbuffers;
|
|
bool isHdrActive = false;
|
|
|
|
std::string setInputApiName;
|
|
std::string currentInputApiName;
|
|
|
|
bool isShuttingDown = false;
|
|
std::set<PVOID> modulesToFree;
|
|
|
|
// menu warnings
|
|
bool fgSettingsChanged = false;
|
|
bool nvngxIniDetected = false;
|
|
|
|
bool nvngxExists = false;
|
|
std::optional<std::wstring> nvngxReplacement = std::nullopt;
|
|
bool libxessExists = false;
|
|
bool fsrHooks = false;
|
|
|
|
IFeature* currentFeature = nullptr;
|
|
IFGFeature_Dx12* currentFG = nullptr;
|
|
IDXGISwapChain* currentSwapchain = nullptr;
|
|
IDXGISwapChain* currentWrappedSwapchain = nullptr;
|
|
IDXGISwapChain* currentRealSwapchain = nullptr;
|
|
IDXGISwapChain* currentFGSwapchain = nullptr;
|
|
ID3D12Device* currentD3D12Device = nullptr;
|
|
DXGI_ADAPTER_DESC currentD3D12AdepterDesc = {};
|
|
ID3D11Device* currentD3D11Device = nullptr;
|
|
DXGI_ADAPTER_DESC currentD3D11AdepterDesc = {};
|
|
ID3D12CommandQueue* currentCommandQueue = nullptr;
|
|
VkDevice currentVkDevice = nullptr;
|
|
DXGI_SWAP_CHAIN_DESC currentSwapchainDesc {};
|
|
|
|
std::vector<ID3D12Device*> d3d12Devices;
|
|
std::vector<ID3D11Device*> d3d11Devices;
|
|
std::unordered_map<UINT64, std::string> adapterDescs;
|
|
|
|
// Moved checks here to prevent circular includes
|
|
/// <summary>
|
|
/// Enables skipping of LoadLibrary checks
|
|
/// </summary>
|
|
/// <param name="dllName">Lower case dll name without `.dll` at the end. Leave blank for skipping all dll's</param>
|
|
static void DisableChecks(UINT owner, std::string dllName = "")
|
|
{
|
|
if (_skipOwner == 0)
|
|
{
|
|
_skipOwner = owner;
|
|
_skipChecks = true;
|
|
_skipDllName = dllName;
|
|
}
|
|
else
|
|
{
|
|
_skipDllName = ""; // Hack for multiple skip calls
|
|
}
|
|
};
|
|
|
|
static void EnableChecks(UINT owner)
|
|
{
|
|
if (_skipOwner == 0 || _skipOwner == owner)
|
|
{
|
|
_skipChecks = false;
|
|
_skipDllName = "";
|
|
_skipOwner = 0;
|
|
}
|
|
};
|
|
|
|
static void DisableServeOriginal(UINT owner)
|
|
{
|
|
if (_serveOwner == 0 || _serveOwner == owner)
|
|
{
|
|
_serveOriginal = false;
|
|
_skipOwner = 0;
|
|
}
|
|
};
|
|
|
|
static void EnableServeOriginal(UINT owner)
|
|
{
|
|
if (_serveOwner == 0 || _serveOwner == owner)
|
|
{
|
|
_serveOriginal = true;
|
|
_skipOwner = owner;
|
|
}
|
|
};
|
|
|
|
static bool SkipDllChecks() { return _skipChecks; }
|
|
static std::string SkipDllName() { return _skipDllName; }
|
|
static bool ServeOriginal() { return _serveOriginal; }
|
|
|
|
private:
|
|
inline static bool _skipChecks = false;
|
|
inline static std::string _skipDllName = "";
|
|
inline static UINT _skipOwner = 0;
|
|
|
|
inline static bool _serveOriginal = false;
|
|
inline static UINT _serveOwner = 0;
|
|
|
|
State() = default;
|
|
};
|
|
|
|
class ScopedSkipSpoofing
|
|
{
|
|
private:
|
|
bool previousState;
|
|
|
|
public:
|
|
ScopedSkipSpoofing()
|
|
{
|
|
previousState = State::Instance().skipSpoofing;
|
|
State::Instance().skipSpoofing = true;
|
|
}
|
|
|
|
~ScopedSkipSpoofing() { State::Instance().skipSpoofing = previousState; }
|
|
};
|
|
|
|
class ScopedSkipDxgiLoadChecks
|
|
{
|
|
private:
|
|
bool previousState;
|
|
|
|
public:
|
|
ScopedSkipDxgiLoadChecks()
|
|
{
|
|
previousState = State::Instance().skipDxgiLoadChecks;
|
|
State::Instance().skipDxgiLoadChecks = true;
|
|
}
|
|
|
|
~ScopedSkipDxgiLoadChecks() { State::Instance().skipDxgiLoadChecks = previousState; }
|
|
};
|
|
|
|
class ScopedSkipParentWrapping
|
|
{
|
|
private:
|
|
bool previousState;
|
|
|
|
public:
|
|
ScopedSkipParentWrapping()
|
|
{
|
|
previousState = State::Instance().skipParentWrapping;
|
|
State::Instance().skipParentWrapping = true;
|
|
}
|
|
|
|
~ScopedSkipParentWrapping() { State::Instance().skipParentWrapping = previousState; }
|
|
};
|
|
|
|
class ScopedSkipHeapCapture
|
|
{
|
|
private:
|
|
bool previousState;
|
|
|
|
public:
|
|
ScopedSkipHeapCapture()
|
|
{
|
|
previousState = State::Instance().skipHeapCapture;
|
|
State::Instance().skipHeapCapture = true;
|
|
}
|
|
|
|
~ScopedSkipHeapCapture() { State::Instance().skipHeapCapture = previousState; }
|
|
};
|
|
|
|
class ScopedSkipVulkanHooks
|
|
{
|
|
private:
|
|
bool previousState;
|
|
|
|
public:
|
|
ScopedSkipVulkanHooks()
|
|
{
|
|
previousState = State::Instance().vulkanSkipHooks;
|
|
State::Instance().vulkanSkipHooks = true;
|
|
}
|
|
~ScopedSkipVulkanHooks() { State::Instance().vulkanSkipHooks = previousState; }
|
|
};
|
|
|
|
class ScopedVulkanCreatingSC
|
|
{
|
|
private:
|
|
bool previousState;
|
|
|
|
public:
|
|
ScopedVulkanCreatingSC()
|
|
{
|
|
previousState = State::Instance().vulkanCreatingSC;
|
|
State::Instance().vulkanCreatingSC = true;
|
|
}
|
|
~ScopedVulkanCreatingSC() { State::Instance().vulkanCreatingSC = previousState; }
|
|
};
|
|
|
|
class ScopedCreatingD3DDevice
|
|
{
|
|
private:
|
|
bool previousState;
|
|
|
|
public:
|
|
ScopedCreatingD3DDevice()
|
|
{
|
|
previousState = State::Instance().creatingD3DDevice;
|
|
State::Instance().creatingD3DDevice = true;
|
|
}
|
|
~ScopedCreatingD3DDevice() { State::Instance().creatingD3DDevice = previousState; }
|
|
};
|