diff --git a/OptiScaler/Config.h b/OptiScaler/Config.h
index bf6c2477..f9630db1 100644
--- a/OptiScaler/Config.h
+++ b/OptiScaler/Config.h
@@ -216,7 +216,9 @@ public:
bool IsRunningOnLinux = false;
bool IsRunningOnDXVK = false;
+ // modes
bool IsDxgiMode = false;
+ bool WorkingAsNvngx = false;
// vulkan stuff
bool VulkanCreatingSC = false;
diff --git a/OptiScaler/OptiScaler.vcxproj b/OptiScaler/OptiScaler.vcxproj
index f4be5450..1b4b9c85 100644
--- a/OptiScaler/OptiScaler.vcxproj
+++ b/OptiScaler/OptiScaler.vcxproj
@@ -82,7 +82,7 @@
$(SolutionDir)external\vulkan\include;$(SolutionDir)external\nvngx_dlss_sdk;$(SolutionDir)external\xess\inc\xess;$(SolutionDir)external\FidelityFX-SDK\ffx-api\include\ffx_api;$(SolutionDir)external\simpleini;$(SolutionDir)external\unordered_dense\include;$(SolutionDir)external\spdlog\include;$(ProjectDir);$(IncludePath)
$(ProjectDir)libs\fsr2;$(ProjectDir)libs\fsr2_212;$(ProjectDir)libs\fsr31;$(ProjectDir)libs\vulkan;$(ProjectDir)libs\d3dx;$(ProjectDir)libs\detours;$(SolutionDir)external\xess\lib;$(LibraryPath)
dxgi
- D:\Folders\Games\Banishers Ghosts of New Eden\NWD\Binaries\Win64\
+ E:\Games\Deep Rock Galactic\FSD\Binaries\Win64\
.\x64\Debug
@@ -191,6 +191,9 @@ copy $(SolutionDir)nvngx.ini $(SolutionDir)x64\Release\a\
+
+
+
@@ -269,8 +272,12 @@ copy $(SolutionDir)nvngx.ini $(SolutionDir)x64\Release\a\
+
+
+
+
@@ -337,6 +344,7 @@ copy $(SolutionDir)nvngx.ini $(SolutionDir)x64\Release\a\
+
diff --git a/OptiScaler/WorkingMode.cpp b/OptiScaler/WorkingMode.cpp
new file mode 100644
index 00000000..f4b5fae7
--- /dev/null
+++ b/OptiScaler/WorkingMode.cpp
@@ -0,0 +1,348 @@
+#include "WorkingMode.h"
+
+#include "Util.h"
+#include "Config.h"
+#include "exports/Exports.h"
+
+typedef const char* (CDECL* PFN_wine_get_version)(void);
+
+static bool IsRunningOnWine()
+{
+ LOG_FUNC();
+
+ HMODULE ntdll = GetModuleHandle(L"ntdll.dll");
+
+ if (!ntdll)
+ {
+ LOG_WARN("Not running on NT!?!");
+ return true;
+ }
+
+ auto pWineGetVersion = (PFN_wine_get_version)GetProcAddress(ntdll, "wine_get_version");
+
+ if (pWineGetVersion)
+ {
+ LOG_INFO("Running on Wine {0}!", pWineGetVersion());
+ return true;
+ }
+
+ LOG_WARN("Wine not detected");
+ return false;
+}
+
+bool WorkingMode::Check()
+{
+ LOG_FUNC();
+
+ // Check for Wine
+ Config::Instance()->IsRunningOnLinux = IsRunningOnWine();
+
+ bool modeFound = false;
+
+ filename = Util::DllPath().filename().string();
+ lCaseFilename = filename;
+
+ wchar_t sysFolder[MAX_PATH];
+ GetSystemDirectory(sysFolder, MAX_PATH);
+ std::filesystem::path sysPath(sysFolder);
+ std::filesystem::path pluginPath(Config::Instance()->PluginPath.value_or((Util::DllPath().parent_path() / L"plugins").wstring()));
+
+ for (size_t i = 0; i < lCaseFilename.size(); i++)
+ lCaseFilename[i] = std::tolower(lCaseFilename[i]);
+
+ HMODULE dll = nullptr;
+
+ do
+ {
+ if (lCaseFilename == "nvngx.dll" || lCaseFilename == "_nvngx.dll" || lCaseFilename == "libxess.dll" || lCaseFilename == "dlss-enabler-upscaler.dll")
+ {
+ LOG_INFO("OptiScaler working as native upscaler: {0}", filename);
+
+ dllNames.push_back("OptiScaler_DontLoad.dll");
+ dllNames.push_back("OptiScaler_DontLoad");
+ dllNamesW.push_back(L"OptiScaler_DontLoad.dll");
+ dllNamesW.push_back(L"OptiScaler_DontLoad");
+
+ isNvngxMode = true;
+ isWorkingWithEnabler = lCaseFilename == "dlss-enabler-upscaler.dll";
+
+ if (isWorkingWithEnabler)
+ Config::Instance()->LogToNGX = true;
+
+ modeFound = true;
+ break;
+ }
+
+ // version.dll
+ if (lCaseFilename == "version.dll")
+ {
+ do
+ {
+ auto pluginFilePath = pluginPath / L"version.dll";
+ dll = LoadLibrary(pluginFilePath.wstring().c_str());
+
+ if (dll != nullptr)
+ {
+ LOG_INFO("OptiScaler working as version.dll, original dll loaded from plugin folder");
+ break;
+ }
+
+ dll = LoadLibrary(L"version-original.dll");
+
+ if (dll != nullptr)
+ {
+ LOG_INFO("OptiScaler working as version.dll, version-original.dll loaded");
+ break;
+ }
+
+ auto sysFilePath = sysPath / L"version.dll";
+ dll = LoadLibrary(sysFilePath.wstring().c_str());
+
+ if (dll != nullptr)
+ LOG_INFO("OptiScaler working as version.dll, system dll loaded");
+
+ } while (false);
+
+ if (dll != nullptr)
+ {
+ dllNames.push_back("version.dll");
+ dllNames.push_back("version");
+ dllNamesW.push_back(L"version.dll");
+ dllNamesW.push_back(L"version");
+
+ shared.LoadOriginalLibrary(dll);
+ version.LoadOriginalLibrary(dll);
+
+ modeFound = true;
+ }
+ else
+ {
+ spdlog::error("OptiScaler can't find original version.dll!");
+ }
+
+ break;
+ }
+
+ // winmm.dll
+ if (lCaseFilename == "winmm.dll")
+ {
+ do
+ {
+ auto pluginFilePath = pluginPath / L"winmm.dll";
+ dll = LoadLibrary(pluginFilePath.wstring().c_str());
+
+ if (dll != nullptr)
+ {
+ LOG_INFO("OptiScaler working as winmm.dll, original dll loaded from plugin folder");
+ break;
+ }
+
+ dll = LoadLibrary(L"winmm-original.dll");
+
+ if (dll != nullptr)
+ {
+ LOG_INFO("OptiScaler working as winmm.dll, winmm-original.dll loaded");
+ break;
+ }
+
+ auto sysFilePath = sysPath / L"winmm.dll";
+ dll = LoadLibrary(sysFilePath.wstring().c_str());
+
+ if (dll != nullptr)
+ LOG_INFO("OptiScaler working as winmm.dll, system dll loaded");
+
+ } while (false);
+
+ if (dll != nullptr)
+ {
+ dllNames.push_back("winmm.dll");
+ dllNames.push_back("winmm");
+ dllNamesW.push_back(L"winmm.dll");
+ dllNamesW.push_back(L"winmm");
+
+ shared.LoadOriginalLibrary(dll);
+ winmm.LoadOriginalLibrary(dll);
+ modeFound = true;
+ }
+ else
+ {
+ spdlog::error("OptiScaler can't find original winmm.dll!");
+ }
+
+ break;
+ }
+
+ // wininet.dll
+ if (lCaseFilename == "wininet.dll")
+ {
+ do
+ {
+ auto pluginFilePath = pluginPath / L"wininet.dll";
+ dll = LoadLibrary(pluginFilePath.wstring().c_str());
+
+ if (dll != nullptr)
+ {
+ LOG_INFO("OptiScaler working as wininet.dll, original dll loaded from plugin folder");
+ break;
+ }
+
+ dll = LoadLibrary(L"wininet-original.dll");
+
+ if (dll != nullptr)
+ {
+ LOG_INFO("OptiScaler working as wininet.dll, wininet-original.dll loaded");
+ break;
+ }
+
+ auto sysFilePath = sysPath / L"wininet.dll";
+ dll = LoadLibrary(sysFilePath.wstring().c_str());
+
+ if (dll != nullptr)
+ LOG_INFO("OptiScaler working as wininet.dll, system dll loaded");
+
+ } while (false);
+
+ if (dll != nullptr)
+ {
+ dllNames.push_back("wininet.dll");
+ dllNames.push_back("wininet");
+ dllNamesW.push_back(L"wininet.dll");
+ dllNamesW.push_back(L"wininet");
+
+ shared.LoadOriginalLibrary(dll);
+ wininet.LoadOriginalLibrary(dll);
+ modeFound = true;
+ }
+ else
+ {
+ spdlog::error("OptiScaler can't find original wininet.dll!");
+ }
+
+ break;
+ }
+
+ // optiscaler.dll
+ if (lCaseFilename == "optiscaler.asi")
+ {
+ LOG_INFO("OptiScaler working as OptiScaler.asi");
+
+ // quick hack for testing
+ dll = dllModule;
+
+ dllNames.push_back("optiscaler.asi");
+ dllNames.push_back("optiscaler");
+ dllNamesW.push_back(L"optiscaler.asi");
+ dllNamesW.push_back(L"optiscaler");
+
+ modeFound = true;
+ break;
+ }
+
+ // winhttp.dll
+ if (lCaseFilename == "winhttp.dll")
+ {
+ do
+ {
+ auto pluginFilePath = pluginPath / L"winhttp.dll";
+ dll = LoadLibrary(pluginFilePath.wstring().c_str());
+
+ if (dll != nullptr)
+ {
+ LOG_INFO("OptiScaler working as winhttp.dll, original dll loaded from plugin folder");
+ break;
+ }
+
+ dll = LoadLibrary(L"winhttp-original.dll");
+
+ if (dll != nullptr)
+ {
+ LOG_INFO("OptiScaler working as winhttp.dll, winhttp-original.dll loaded");
+ break;
+ }
+
+ auto sysFilePath = sysPath / L"winhttp.dll";
+ dll = LoadLibrary(sysFilePath.wstring().c_str());
+
+ if (dll != nullptr)
+ LOG_INFO("OptiScaler working as winhttp.dll, system dll loaded");
+
+ } while (false);
+
+ if (dll != nullptr)
+ {
+ dllNames.push_back("winhttp.dll");
+ dllNames.push_back("winhttp");
+ dllNamesW.push_back(L"winhttp.dll");
+ dllNamesW.push_back(L"winhttp");
+
+ shared.LoadOriginalLibrary(dll);
+ winhttp.LoadOriginalLibrary(dll);
+ modeFound = true;
+ }
+ else
+ {
+ spdlog::error("OptiScaler can't find original winhttp.dll!");
+ }
+
+ break;
+ }
+
+ // dxgi.dll
+ if (lCaseFilename == "dxgi.dll")
+ {
+ do
+ {
+ auto pluginFilePath = pluginPath / L"dxgi.dll";
+ dll = LoadLibrary(pluginFilePath.wstring().c_str());
+
+ if (dll != nullptr)
+ {
+ LOG_INFO("OptiScaler working as dxgi.dll, original dll loaded from plugin folder");
+ break;
+ }
+
+ dll = LoadLibrary(L"dxgi-original.dll");
+
+ if (dll != nullptr)
+ {
+ LOG_INFO("OptiScaler working as dxgi.dll, dxgi-original.dll loaded");
+ break;
+ }
+
+ auto sysFilePath = sysPath / L"dxgi.dll";
+ dll = LoadLibrary(sysFilePath.wstring().c_str());
+
+ if (dll != nullptr)
+ LOG_INFO("OptiScaler working as dxgi.dll, system dll loaded");
+
+ } while (false);
+
+ if (dll != nullptr)
+ {
+ dllNames.push_back("dxgi.dll");
+ dllNames.push_back("dxgi");
+ dllNamesW.push_back(L"dxgi.dll");
+ dllNamesW.push_back(L"dxgi");
+
+ dxgi.LoadOriginalLibrary(dll);
+
+ Config::Instance()->IsDxgiMode = true;
+ isDxgiMode = true;
+ modeFound = true;
+ }
+ else
+ {
+ spdlog::error("OptiScaler can't find original dxgi.dll!");
+ }
+
+ break;
+ }
+
+ } while (false);
+
+ if (modeFound)
+ return true;
+
+ LOG_ERROR("Unsupported dll name: {0}", filename);
+ return false;
+}
diff --git a/OptiScaler/WorkingMode.h b/OptiScaler/WorkingMode.h
new file mode 100644
index 00000000..558c0f1b
--- /dev/null
+++ b/OptiScaler/WorkingMode.h
@@ -0,0 +1,26 @@
+#pragma once
+#include "pch.h"
+
+class WorkingMode
+{
+private:
+ inline static std::vector dllNames;
+ inline static std::vector dllNamesW;
+ inline static std::string filename;
+ inline static std::string lCaseFilename;
+ inline static bool isNvngxMode = false;
+ inline static bool isDxgiMode = false;
+ inline static bool isWorkingWithEnabler = false;
+
+
+public:
+ static bool Check();
+
+ static std::string FileName() { return filename; }
+ static std::string FileNameLCase() { return lCaseFilename; }
+ static bool IsNvngxMode() { return isNvngxMode; }
+ static bool IsWorkingWithEnabler() { return isWorkingWithEnabler; }
+ static bool IsDxgiMode() { return isDxgiMode; }
+ static std::vector DllNames() { return dllNames; }
+ static std::vector DllNamesW() { return dllNamesW; }
+};
\ No newline at end of file
diff --git a/OptiScaler/dllmain.cpp b/OptiScaler/dllmain.cpp
index ab4b771c..83dc6e2f 100644
--- a/OptiScaler/dllmain.cpp
+++ b/OptiScaler/dllmain.cpp
@@ -3,50 +3,15 @@
#include "Util.h"
#include "Logger.h"
#include "resource.h"
-#include "exports/Exports.h"
+#include "WorkingMode.h"
#include "proxies/NVNGX_Proxy.h"
+#include "proxies/FfxApi_Proxy.h"
#include "proxies/XeSS_Proxy.h"
#include "menu/imgui_overlay_dx.h"
#include "menu/imgui_overlay_vk.h"
-#include
-
#pragma warning (disable : 4996)
-typedef BOOL(WINAPI* PFN_FreeLibrary)(HMODULE lpLibrary);
-typedef HMODULE(WINAPI* PFN_LoadLibraryA)(LPCSTR lpLibFileName);
-typedef HMODULE(WINAPI* PFN_LoadLibraryW)(LPCWSTR lpLibFileName);
-typedef HMODULE(WINAPI* PFN_LoadLibraryExA)(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
-typedef HMODULE(WINAPI* PFN_LoadLibraryExW)(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
-typedef FARPROC(WINAPI* PFN_GetProcAddress)(HMODULE hModule, LPCSTR lpProcName);
-
-typedef const char* (CDECL* PFN_wine_get_version)(void);
-
-typedef struct VkDummyProps
-{
- VkStructureType sType;
- void* pNext;
-} VkDummyProps;
-
-static PFN_FreeLibrary o_FreeLibrary = nullptr;
-static PFN_LoadLibraryA o_LoadLibraryA = nullptr;
-static PFN_LoadLibraryW o_LoadLibraryW = nullptr;
-static PFN_LoadLibraryExA o_LoadLibraryExA = nullptr;
-static PFN_LoadLibraryExW o_LoadLibraryExW = nullptr;
-static PFN_GetProcAddress o_GetProcAddress = nullptr;
-static PFN_vkGetPhysicalDeviceProperties o_vkGetPhysicalDeviceProperties = nullptr;
-static PFN_vkGetPhysicalDeviceProperties2 o_vkGetPhysicalDeviceProperties2 = nullptr;
-static PFN_vkGetPhysicalDeviceProperties2KHR o_vkGetPhysicalDeviceProperties2KHR = nullptr;
-
-static PFN_vkEnumerateInstanceExtensionProperties o_vkEnumerateInstanceExtensionProperties = nullptr;
-static PFN_vkEnumerateDeviceExtensionProperties o_vkEnumerateDeviceExtensionProperties = nullptr;
-static PFN_vkCreateDevice o_vkCreateDevice = nullptr;
-static PFN_vkCreateInstance o_vkCreateInstance = nullptr;
-
-static uint32_t vkEnumerateInstanceExtensionPropertiesCount = 0;
-static uint32_t vkEnumerateDeviceExtensionPropertiesCount = 0;
-
-
inline std::vector upscalerNames =
{
"nvngx.dll",
@@ -103,154 +68,6 @@ void DetachHooks();
HMODULE LoadNvApi();
HMODULE LoadNvgxDlss(std::wstring originalPath);
-inline static bool CheckDllName(std::string* dllName, std::vector* namesList)
-{
- for (size_t i = 0; i < namesList->size(); i++)
- {
- auto name = namesList->at(i);
- auto pos = dllName->rfind(name);
-
- if (pos != std::string::npos && pos == (dllName->size() - name.size()))
- return true;
- }
-
- return false;
-}
-
-inline static bool CheckDllNameW(std::wstring* dllName, std::vector* namesList)
-{
- auto found = false;
-
- for (size_t i = 0; i < namesList->size(); i++)
- {
- auto name = namesList->at(i);
- auto pos = dllName->rfind(name);
-
- if (pos != std::string::npos && pos == (dllName->size() - name.size()))
- return true;
- }
-
- return false;
-}
-
-inline static HMODULE LoadLibraryCheck(std::string lcaseLibName)
-{
- // If Opti is not loading as nvngx.dll
- if (!isWorkingWithEnabler && !Config::Instance()->upscalerDisableHook)
- {
- // exe path
- auto exePath = Util::ExePath().parent_path().wstring();
-
- for (size_t i = 0; i < exePath.size(); i++)
- exePath[i] = std::tolower(exePath[i]);
-
- auto pos = lcaseLibName.rfind(wstring_to_string(exePath));
-
- if (CheckDllName(&lcaseLibName, &upscalerNames) &&
- (!Config::Instance()->HookOriginalNvngxOnly.value_or(false) || pos == std::string::npos))
- {
- LOG_INFO("nvngx call: {0}, returning this dll!", lcaseLibName);
-
- if (!dontCount)
- loadCount++;
-
- return dllModule;
- }
- }
-
- // NvApi64.dll
- if (!isWorkingWithEnabler && Config::Instance()->OverrideNvapiDll.value_or(false) && CheckDllName(&lcaseLibName, &nvapiNames))
- {
- LOG_INFO("{0} call!", lcaseLibName);
-
- auto nvapi = LoadNvApi();
-
- if (nvapi != nullptr)
- return nvapi;
- }
-
- // nvngx_dlss
- if (Config::Instance()->DLSSEnabled.value_or(true) && Config::Instance()->DLSSLibrary.has_value() && CheckDllName(&lcaseLibName, &nvngxDlss))
- {
- auto nvngxDlss = LoadNvgxDlss(string_to_wstring(lcaseLibName));
-
- if (nvngxDlss != nullptr)
- return nvngxDlss;
- }
-
- if (!isNvngxMode && CheckDllName(&lcaseLibName, &dllNames))
- {
- LOG_INFO("{0} call returning this dll!", lcaseLibName);
-
- if (!dontCount)
- loadCount++;
-
- return dllModule;
- }
-
- return nullptr;
-}
-
-inline static HMODULE LoadLibraryCheckW(std::wstring lcaseLibName)
-{
- auto lcaseLibNameA = wstring_to_string(lcaseLibName);
-
- // If Opti is not loading as nvngx.dll
- if (!isWorkingWithEnabler && !Config::Instance()->upscalerDisableHook)
- {
- // exe path
- auto exePath = Util::ExePath().parent_path().wstring();
-
- for (size_t i = 0; i < exePath.size(); i++)
- exePath[i] = std::tolower(exePath[i]);
-
- auto pos = lcaseLibName.rfind(exePath);
-
- if (CheckDllNameW(&lcaseLibName, &upscalerNamesW) &&
- (!Config::Instance()->HookOriginalNvngxOnly.value_or(false) || pos == std::string::npos))
- {
- LOG_INFO("nvngx call: {0}, returning this dll!", lcaseLibNameA);
-
- if (!dontCount)
- loadCount++;
-
- return dllModule;
- }
- }
-
- // nvngx_dlss
- if (Config::Instance()->DLSSEnabled.value_or(true) && Config::Instance()->DLSSLibrary.has_value() && CheckDllNameW(&lcaseLibName, &nvngxDlssW))
- {
- auto nvngxDlss = LoadNvgxDlss(lcaseLibName);
-
- if (nvngxDlss != nullptr)
- return nvngxDlss;
- }
-
- // NvApi64.dll
- if (!isWorkingWithEnabler && Config::Instance()->OverrideNvapiDll.value_or(false) && CheckDllNameW(&lcaseLibName, &nvapiNamesW))
- {
- LOG_INFO("{0} call!", lcaseLibNameA);
-
- auto nvapi = LoadNvApi();
-
- if (nvapi != nullptr)
- return nvapi;
- }
-
- if (!isNvngxMode && CheckDllNameW(&lcaseLibName, &dllNamesW))
- {
- LOG_INFO("{0} call returning this dll!", lcaseLibNameA);
-
- if (!dontCount)
- loadCount++;
-
- return dllModule;
- }
-
- return nullptr;
-}
-
static HMODULE LoadNvApi()
{
HMODULE nvapi = nullptr;
@@ -325,407 +142,6 @@ static HMODULE LoadNvgxDlss(std::wstring originalPath)
return nullptr;
}
-#pragma region Load & nvngxDlss Library hooks
-
-static FARPROC hkGetProcAddress(HMODULE hModule, LPCSTR lpProcName)
-{
- if (hModule == dllModule)
- LOG_INFO("Trying to get process address of {0}", lpProcName);
-
- return o_GetProcAddress(hModule, lpProcName);
-}
-
-static BOOL hkFreeLibrary(HMODULE lpLibrary)
-{
- if (lpLibrary == nullptr)
- return FALSE;
-
- if (lpLibrary == dllModule)
- {
- if (loadCount > 0)
- loadCount--;
-
- LOG_INFO("Call for this module loadCount: {0}", loadCount);
-
- if (loadCount == 0)
- {
- auto result = o_FreeLibrary(lpLibrary);
- LOG_DEBUG("o_FreeLibrary result: {0:X}", result);
- }
- else
- {
- return TRUE;
- }
- }
-
- return o_FreeLibrary(lpLibrary);
-}
-
-static HMODULE hkLoadLibraryA(LPCSTR lpLibFileName)
-{
- if (lpLibFileName == nullptr)
- return NULL;
-
- std::string libName(lpLibFileName);
- std::string lcaseLibName(libName);
-
- for (size_t i = 0; i < lcaseLibName.size(); i++)
- lcaseLibName[i] = std::tolower(lcaseLibName[i]);
-
-#ifdef _DEBUG
- LOG_TRACE("call: {0}", lcaseLibName);
-#endif // DEBUG
-
- auto moduleHandle = LoadLibraryCheck(lcaseLibName);
-
- if (moduleHandle != nullptr)
- return moduleHandle;
-
- dontCount = true;
- auto result = o_LoadLibraryA(lpLibFileName);
- dontCount = false;
-
- return result;
-}
-
-static HMODULE hkLoadLibraryW(LPCWSTR lpLibFileName)
-{
- if (lpLibFileName == nullptr)
- return NULL;
-
- std::wstring libName(lpLibFileName);
- std::wstring lcaseLibName(libName);
-
- for (size_t i = 0; i < lcaseLibName.size(); i++)
- lcaseLibName[i] = std::tolower(lcaseLibName[i]);
-
-#ifdef _DEBUG
- LOG_TRACE("call: {0}", wstring_to_string(lcaseLibName));
-#endif // DEBUG
-
- auto moduleHandle = LoadLibraryCheckW(lcaseLibName);
-
- if (moduleHandle != nullptr)
- return moduleHandle;
-
- dontCount = true;
- auto result = o_LoadLibraryW(lpLibFileName);
- dontCount = false;
-
- return result;
-}
-
-static HMODULE hkLoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
-{
- if (lpLibFileName == nullptr)
- return NULL;
-
- std::string libName(lpLibFileName);
- std::string lcaseLibName(libName);
-
- for (size_t i = 0; i < lcaseLibName.size(); i++)
- lcaseLibName[i] = std::tolower(lcaseLibName[i]);
-
-#ifdef _DEBUG
- LOG_TRACE("call: {0}", lcaseLibName);
-#endif
-
- auto moduleHandle = LoadLibraryCheck(lcaseLibName);
-
- if (moduleHandle != nullptr)
- return moduleHandle;
-
-
- dontCount = true;
- auto result = o_LoadLibraryExA(lpLibFileName, hFile, dwFlags);
- dontCount = false;
-
- return result;
-}
-
-static HMODULE hkLoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
-{
- if (lpLibFileName == nullptr)
- return NULL;
-
- std::wstring libName(lpLibFileName);
- std::wstring lcaseLibName(libName);
-
- for (size_t i = 0; i < lcaseLibName.size(); i++)
- lcaseLibName[i] = std::tolower(lcaseLibName[i]);
-
-#ifdef _DEBUG
- LOG_TRACE("call: {0}", wstring_to_string(lcaseLibName));
-#endif
-
- auto moduleHandle = LoadLibraryCheckW(lcaseLibName);
-
- if (moduleHandle != nullptr)
- return moduleHandle;
-
- dontCount = true;
- auto result = o_LoadLibraryExW(lpLibFileName, hFile, dwFlags);
- dontCount = false;
-
- return result;
-}
-
-#pragma endregion
-
-#pragma region Vulkan Hooks
-
-static void hkvkGetPhysicalDeviceProperties(VkPhysicalDevice physical_device, VkPhysicalDeviceProperties* properties)
-{
- o_vkGetPhysicalDeviceProperties(physical_device, properties);
-
- if (!Config::Instance()->dxgiSkipSpoofing)
- {
- auto deviceName = wstring_to_string(Config::Instance()->SpoofedGPUName.value_or(L"NVIDIA GeForce RTX 4090"));
- std::strcpy(properties->deviceName, deviceName.c_str());
- properties->vendorID = 0x10de;
- properties->deviceID = 0x2684;
- properties->driverVersion = VK_MAKE_API_VERSION(559, 0, 0, 0);
- }
- else
- {
- LOG_DEBUG("Skipping spoofing");
- }
-}
-
-static void hkvkGetPhysicalDeviceProperties2(VkPhysicalDevice phys_dev, VkPhysicalDeviceProperties2* properties2)
-{
- o_vkGetPhysicalDeviceProperties2(phys_dev, properties2);
-
- if (!Config::Instance()->dxgiSkipSpoofing)
- {
- auto deviceName = wstring_to_string(Config::Instance()->SpoofedGPUName.value_or(L"NVIDIA GeForce RTX 4090"));
- std::strcpy(properties2->properties.deviceName, deviceName.c_str());
- properties2->properties.vendorID = 0x10de;
- properties2->properties.deviceID = 0x2684;
- properties2->properties.driverVersion = VK_MAKE_API_VERSION(559, 0, 0, 0);
-
- auto next = (VkDummyProps*)properties2->pNext;
-
- while (next != nullptr)
- {
- if (next->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES)
- {
- auto ddp = (VkPhysicalDeviceDriverProperties*)(void*)next;
- ddp->driverID = VK_DRIVER_ID_NVIDIA_PROPRIETARY;
- std::strcpy(ddp->driverName, "NVIDIA");
- std::strcpy(ddp->driverInfo, "559.0");
- }
-
- next = (VkDummyProps*)next->pNext;
- }
- }
- else
- {
- LOG_DEBUG("Skipping spoofing");
- }
-}
-
-static void hkvkGetPhysicalDeviceProperties2KHR(VkPhysicalDevice phys_dev, VkPhysicalDeviceProperties2* properties2)
-{
- o_vkGetPhysicalDeviceProperties2KHR(phys_dev, properties2);
-
- if (!Config::Instance()->dxgiSkipSpoofing)
- {
- auto deviceName = wstring_to_string(Config::Instance()->SpoofedGPUName.value_or(L"NVIDIA GeForce RTX 4090"));
- std::strcpy(properties2->properties.deviceName, deviceName.c_str());
- properties2->properties.vendorID = 0x10de;
- properties2->properties.deviceID = 0x2684;
- properties2->properties.driverVersion = VK_MAKE_API_VERSION(559, 0, 0, 0);
-
- auto next = (VkDummyProps*)properties2->pNext;
-
- while (next != nullptr)
- {
- if (next->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES)
- {
- auto ddp = (VkPhysicalDeviceDriverProperties*)(void*)next;
- ddp->driverID = VK_DRIVER_ID_NVIDIA_PROPRIETARY;
- std::strcpy(ddp->driverName, "NVIDIA");
- std::strcpy(ddp->driverInfo, "559.0");
- }
-
- next = (VkDummyProps*)next->pNext;
- }
- }
- else
- {
- LOG_DEBUG("Skipping spoofing");
- }
-}
-
-static VkResult hkvkCreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance)
-{
- LOG_DEBUG("for {0}", pCreateInfo->pApplicationInfo->pApplicationName);
-
- LOG_DEBUG("extensions ({0}):", pCreateInfo->enabledExtensionCount);
- for (size_t i = 0; i < pCreateInfo->enabledExtensionCount; i++)
- LOG_DEBUG(" {0}", pCreateInfo->ppEnabledExtensionNames[i]);
-
- LOG_DEBUG("layers ({0}):", pCreateInfo->enabledLayerCount);
- for (size_t i = 0; i < pCreateInfo->enabledLayerCount; i++)
- LOG_DEBUG(" {0}", pCreateInfo->ppEnabledLayerNames[i]);
-
- // Skip spoofing for Intel Arc
- Config::Instance()->dxgiSkipSpoofing = true;
- auto result = o_vkCreateInstance(pCreateInfo, pAllocator, pInstance);
- Config::Instance()->dxgiSkipSpoofing = false;
-
- LOG_DEBUG("o_vkCreateInstance result: {0:X}", (INT)result);
-
- auto head = (VkBaseInStructure*)pCreateInfo;
-
- while (head->pNext != nullptr)
- {
- head = (VkBaseInStructure*)head->pNext;
- LOG_DEBUG("o_vkCreateInstance type: {0:X}", (UINT)head->sType);
- }
-
- return result;
-}
-
-static VkResult hkvkCreateDevice(VkPhysicalDevice physicalDevice, VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice)
-{
- LOG_FUNC();
-
- if (!Config::Instance()->VulkanExtensionSpoofing.value_or(false))
- {
- LOG_DEBUG("extension spoofing is disabled");
-
- Config::Instance()->dxgiSkipSpoofing = true;
- return o_vkCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
- Config::Instance()->dxgiSkipSpoofing = false;
- }
-
- LOG_DEBUG("layers ({0}):", pCreateInfo->enabledLayerCount);
- for (size_t i = 0; i < pCreateInfo->enabledLayerCount; i++)
- LOG_DEBUG(" {0}", pCreateInfo->ppEnabledLayerNames[i]);
-
- std::vector newExtensionList;
-
- auto bVK_KHR_get_memory_requirements2 = false;
-
- LOG_DEBUG("checking extensions and removing VK_NVX_BINARY_IMPORT & VK_NVX_IMAGE_VIEW_HANDLE from list");
- for (size_t i = 0; i < pCreateInfo->enabledExtensionCount; i++)
- {
- if (std::strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_NVX_BINARY_IMPORT_EXTENSION_NAME) == 0 || std::strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME) == 0)
- {
- LOG_DEBUG("removing {0}", pCreateInfo->ppEnabledExtensionNames[i]);
- }
- else
- {
- LOG_DEBUG("adding {0}", pCreateInfo->ppEnabledExtensionNames[i]);
- newExtensionList.push_back(pCreateInfo->ppEnabledExtensionNames[i]);
-
- if (std::strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME) == 0)
- bVK_KHR_get_memory_requirements2 = true;
- }
- }
-
- if (!bVK_KHR_get_memory_requirements2)
- newExtensionList.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
-
- pCreateInfo->enabledExtensionCount = static_cast(newExtensionList.size());
- pCreateInfo->ppEnabledExtensionNames = newExtensionList.data();
-
- LOG_DEBUG("final extension count: {0}", pCreateInfo->enabledExtensionCount);
- LOG_DEBUG("final extensions:");
-
- for (size_t i = 0; i < pCreateInfo->enabledExtensionCount; i++)
- LOG_DEBUG(" {0}", pCreateInfo->ppEnabledExtensionNames[i]);
-
- // Skip spoofing for Intel Arc
- Config::Instance()->dxgiSkipSpoofing = true;
- auto result = o_vkCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
- Config::Instance()->dxgiSkipSpoofing = false;
-
- LOG_FUNC_RESULT(result);
-
- return result;
-}
-
-static VkResult hkvkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties)
-{
- LOG_FUNC();
-
- auto count = *pPropertyCount;
- auto result = o_vkEnumerateDeviceExtensionProperties(physicalDevice, pLayerName, pPropertyCount, pProperties);
-
- if (result != VK_SUCCESS)
- {
- LOG_ERROR("o_vkEnumerateDeviceExtensionProperties({0}, {1}) result: {2:X}", pLayerName, count, (UINT)result);
- return result;
- }
-
- if (pLayerName == nullptr && pProperties == nullptr && count == 0)
- {
- *pPropertyCount += 2;
- vkEnumerateDeviceExtensionPropertiesCount = *pPropertyCount;
- LOG_TRACE("hkvkEnumerateDeviceExtensionProperties({0}) count: {1}", pLayerName, vkEnumerateDeviceExtensionPropertiesCount);
- return result;
- }
-
- if (pLayerName == nullptr && pProperties != nullptr && *pPropertyCount > 0)
- {
- if (count == vkEnumerateDeviceExtensionPropertiesCount)
- *pPropertyCount = count;
-
- VkExtensionProperties bi{ VK_NVX_BINARY_IMPORT_EXTENSION_NAME, VK_NVX_BINARY_IMPORT_SPEC_VERSION };
- memcpy(&pProperties[*pPropertyCount - 1], &bi, sizeof(VkExtensionProperties));
-
- VkExtensionProperties ivh{ VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME, VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION };
- memcpy(&pProperties[*pPropertyCount - 2], &ivh, sizeof(VkExtensionProperties));
- }
-
- LOG_FUNC_RESULT(result);
-
- return result;
-}
-
-static VkResult hkvkEnumerateInstanceExtensionProperties(const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties)
-{
- LOG_FUNC();
-
- auto count = *pPropertyCount;
- auto result = o_vkEnumerateInstanceExtensionProperties(pLayerName, pPropertyCount, pProperties);
-
- if (result != VK_SUCCESS)
- {
- LOG_ERROR("o_vkEnumerateInstanceExtensionProperties({0}, {1}) result: {2:X}", pLayerName, count, (UINT)result);
- return result;
- }
-
- if (pLayerName == nullptr && pProperties == nullptr && count == 0)
- {
- *pPropertyCount += 2;
- vkEnumerateInstanceExtensionPropertiesCount = *pPropertyCount;
- LOG_TRACE("hkvkEnumerateDeviceExtensionProperties({0}) count: {1}", pLayerName, vkEnumerateDeviceExtensionPropertiesCount);
- return result;
- }
-
- if (pLayerName == nullptr && pProperties != nullptr && *pPropertyCount > 0)
- {
- if (vkEnumerateInstanceExtensionPropertiesCount == count)
- *pPropertyCount = count;
-
- VkExtensionProperties bi{ VK_NVX_BINARY_IMPORT_EXTENSION_NAME, VK_NVX_BINARY_IMPORT_SPEC_VERSION };
- memcpy(&pProperties[*pPropertyCount - 1], &bi, sizeof(VkExtensionProperties));
-
- VkExtensionProperties ivh{ VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME, VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION };
- memcpy(&pProperties[*pPropertyCount - 2], &ivh, sizeof(VkExtensionProperties));
- }
-
- LOG_FUNC_RESULT(result);
-
- return result;
-}
-
-#pragma endregion
-
static void DetachHooks()
{
if (!isNvngxMode)
@@ -818,30 +234,30 @@ static void DetachHooks()
o_vkCreateInstance = nullptr;
}
- if (!Config::Instance()->IsDxgiMode && Config::Instance()->DxgiSpoofing.value_or(true))
- {
- if (dxgi.CreateDxgiFactory != nullptr)
- {
- DetourDetach(&(PVOID&)dxgi.CreateDxgiFactory, _CreateDXGIFactory);
- dxgi.CreateDxgiFactory = nullptr;
- }
+ //if (!Config::Instance()->IsDxgiMode && Config::Instance()->DxgiSpoofing.value_or(true))
+ //{
+ // if (dxgi.CreateDxgiFactory != nullptr)
+ // {
+ // DetourDetach(&(PVOID&)dxgi.CreateDxgiFactory, _CreateDXGIFactory);
+ // dxgi.CreateDxgiFactory = nullptr;
+ // }
- if (dxgi.CreateDxgiFactory1 != nullptr)
- {
- DetourDetach(&(PVOID&)dxgi.CreateDxgiFactory1, _CreateDXGIFactory1);
- dxgi.CreateDxgiFactory1 = nullptr;
- }
+ // if (dxgi.CreateDxgiFactory1 != nullptr)
+ // {
+ // DetourDetach(&(PVOID&)dxgi.CreateDxgiFactory1, _CreateDXGIFactory1);
+ // dxgi.CreateDxgiFactory1 = nullptr;
+ // }
- if (dxgi.CreateDxgiFactory2 != nullptr)
- {
- DetourDetach(&(PVOID&)dxgi.CreateDxgiFactory2, _CreateDXGIFactory2);
- dxgi.CreateDxgiFactory2 = nullptr;
- }
- }
+ // if (dxgi.CreateDxgiFactory2 != nullptr)
+ // {
+ // DetourDetach(&(PVOID&)dxgi.CreateDxgiFactory2, _CreateDXGIFactory2);
+ // dxgi.CreateDxgiFactory2 = nullptr;
+ // }
+ //}
DetourTransactionCommit();
- FreeLibrary(shared.dll);
+ //FreeLibrary(shared.dll);
}
}
@@ -890,438 +306,8 @@ static void AttachHooks()
}
}
- if (!isNvngxMode && Config::Instance()->VulkanSpoofing.value_or(false) && o_vkGetPhysicalDeviceProperties == nullptr)
- {
- o_vkGetPhysicalDeviceProperties = reinterpret_cast(DetourFindFunction("vulkan-1.dll", "vkGetPhysicalDeviceProperties"));
- o_vkGetPhysicalDeviceProperties2 = reinterpret_cast(DetourFindFunction("vulkan-1.dll", "vkGetPhysicalDeviceProperties2"));
- o_vkGetPhysicalDeviceProperties2KHR = reinterpret_cast(DetourFindFunction("vulkan-1.dll", "vkGetPhysicalDeviceProperties2KHR"));
- if (o_vkGetPhysicalDeviceProperties != nullptr)
- {
- LOG_INFO("Attaching Vulkan device spoofing hooks");
- DetourTransactionBegin();
- DetourUpdateThread(GetCurrentThread());
-
- if (o_vkGetPhysicalDeviceProperties)
- DetourAttach(&(PVOID&)o_vkGetPhysicalDeviceProperties, hkvkGetPhysicalDeviceProperties);
-
- if (o_vkGetPhysicalDeviceProperties2)
- DetourAttach(&(PVOID&)o_vkGetPhysicalDeviceProperties2, hkvkGetPhysicalDeviceProperties2);
-
- if (o_vkGetPhysicalDeviceProperties2KHR)
- DetourAttach(&(PVOID&)o_vkGetPhysicalDeviceProperties2KHR, hkvkGetPhysicalDeviceProperties2KHR);
-
- DetourTransactionCommit();
- }
- }
-
- if (!isNvngxMode && Config::Instance()->VulkanExtensionSpoofing.value_or(false) && o_vkEnumerateInstanceExtensionProperties == nullptr)
- {
- o_vkCreateDevice = reinterpret_cast(DetourFindFunction("vulkan-1.dll", "vkCreateDevice"));
- o_vkCreateInstance = reinterpret_cast(DetourFindFunction("vulkan-1.dll", "vkCreateInstance"));
- o_vkEnumerateInstanceExtensionProperties = reinterpret_cast(DetourFindFunction("vulkan-1.dll", "vkEnumerateInstanceExtensionProperties"));
- o_vkEnumerateDeviceExtensionProperties = reinterpret_cast(DetourFindFunction("vulkan-1.dll", "vkEnumerateDeviceExtensionProperties"));
-
- if (o_vkEnumerateInstanceExtensionProperties != nullptr || o_vkEnumerateDeviceExtensionProperties != nullptr)
- {
- LOG_INFO("Attaching Vulkan extensions spoofing hooks");
-
- DetourTransactionBegin();
- DetourUpdateThread(GetCurrentThread());
-
- if (o_vkEnumerateInstanceExtensionProperties)
- DetourAttach(&(PVOID&)o_vkEnumerateInstanceExtensionProperties, hkvkEnumerateInstanceExtensionProperties);
-
- if (o_vkEnumerateDeviceExtensionProperties)
- DetourAttach(&(PVOID&)o_vkEnumerateDeviceExtensionProperties, hkvkEnumerateDeviceExtensionProperties);
-
- if (o_vkCreateDevice)
- DetourAttach(&(PVOID&)o_vkCreateDevice, hkvkCreateDevice);
-
- if (o_vkCreateInstance)
- DetourAttach(&(PVOID&)o_vkCreateInstance, hkvkCreateInstance);
-
- DetourTransactionCommit();
- }
- }
-}
-
-static bool IsRunningOnWine()
-{
- LOG_FUNC();
-
- HMODULE ntdll = GetModuleHandle(L"ntdll.dll");
-
- if (!ntdll)
- {
- LOG_WARN("Not running on NT!?!");
- return true;
- }
-
- auto pWineGetVersion = (PFN_wine_get_version)GetProcAddress(ntdll, "wine_get_version");
-
- if (pWineGetVersion)
- {
- LOG_INFO("Running on Wine {0}!", pWineGetVersion());
- return true;
- }
-
- LOG_WARN("Wine not detected");
- return false;
-}
-
-static void CheckWorkingMode()
-{
- LOG_FUNC();
-
- bool modeFound = false;
- std::string filename = Util::DllPath().filename().string();
- std::string lCaseFilename(filename);
- wchar_t sysFolder[MAX_PATH];
- GetSystemDirectory(sysFolder, MAX_PATH);
- std::filesystem::path sysPath(sysFolder);
- std::filesystem::path pluginPath(Config::Instance()->PluginPath.value_or((Util::DllPath().parent_path() / L"plugins").wstring()));
-
- for (size_t i = 0; i < lCaseFilename.size(); i++)
- lCaseFilename[i] = std::tolower(lCaseFilename[i]);
-
- HMODULE dll = nullptr;
-
- do
- {
- if (lCaseFilename == "nvngx.dll" || lCaseFilename == "_nvngx.dll" || lCaseFilename == "libxess.dll" || lCaseFilename == "dlss-enabler-upscaler.dll")
- {
- LOG_INFO("OptiScaler working as native upscaler: {0}", filename);
-
- dllNames.push_back("OptiScaler_DontLoad.dll");
- dllNames.push_back("OptiScaler_DontLoad");
- dllNamesW.push_back(L"OptiScaler_DontLoad.dll");
- dllNamesW.push_back(L"OptiScaler_DontLoad");
-
- isNvngxMode = true;
- isWorkingWithEnabler = lCaseFilename == "dlss-enabler-upscaler.dll";
-
- if (isWorkingWithEnabler)
- Config::Instance()->LogToNGX = true;
-
- modeFound = true;
- break;
- }
-
- // version.dll
- if (lCaseFilename == "version.dll")
- {
- do
- {
- auto pluginFilePath = pluginPath / L"version.dll";
- dll = LoadLibrary(pluginFilePath.wstring().c_str());
-
- if (dll != nullptr)
- {
- LOG_INFO("OptiScaler working as version.dll, original dll loaded from plugin folder");
- break;
- }
-
- dll = LoadLibrary(L"version-original.dll");
-
- if (dll != nullptr)
- {
- LOG_INFO("OptiScaler working as version.dll, version-original.dll loaded");
- break;
- }
-
- auto sysFilePath = sysPath / L"version.dll";
- dll = LoadLibrary(sysFilePath.wstring().c_str());
-
- if (dll != nullptr)
- LOG_INFO("OptiScaler working as version.dll, system dll loaded");
-
- } while (false);
-
- if (dll != nullptr)
- {
- dllNames.push_back("version.dll");
- dllNames.push_back("version");
- dllNamesW.push_back(L"version.dll");
- dllNamesW.push_back(L"version");
-
- shared.LoadOriginalLibrary(dll);
- version.LoadOriginalLibrary(dll);
-
- modeFound = true;
- }
- else
- {
- spdlog::error("OptiScaler can't find original version.dll!");
- }
-
- break;
- }
-
- // winmm.dll
- if (lCaseFilename == "winmm.dll")
- {
- do
- {
- auto pluginFilePath = pluginPath / L"winmm.dll";
- dll = LoadLibrary(pluginFilePath.wstring().c_str());
-
- if (dll != nullptr)
- {
- LOG_INFO("OptiScaler working as winmm.dll, original dll loaded from plugin folder");
- break;
- }
-
- dll = LoadLibrary(L"winmm-original.dll");
-
- if (dll != nullptr)
- {
- LOG_INFO("OptiScaler working as winmm.dll, winmm-original.dll loaded");
- break;
- }
-
- auto sysFilePath = sysPath / L"winmm.dll";
- dll = LoadLibrary(sysFilePath.wstring().c_str());
-
- if (dll != nullptr)
- LOG_INFO("OptiScaler working as winmm.dll, system dll loaded");
-
- } while (false);
-
- if (dll != nullptr)
- {
- dllNames.push_back("winmm.dll");
- dllNames.push_back("winmm");
- dllNamesW.push_back(L"winmm.dll");
- dllNamesW.push_back(L"winmm");
-
- shared.LoadOriginalLibrary(dll);
- winmm.LoadOriginalLibrary(dll);
- modeFound = true;
- }
- else
- {
- spdlog::error("OptiScaler can't find original winmm.dll!");
- }
-
- break;
- }
-
- // wininet.dll
- if (lCaseFilename == "wininet.dll")
- {
- do
- {
- auto pluginFilePath = pluginPath / L"wininet.dll";
- dll = LoadLibrary(pluginFilePath.wstring().c_str());
-
- if (dll != nullptr)
- {
- LOG_INFO("OptiScaler working as wininet.dll, original dll loaded from plugin folder");
- break;
- }
-
- dll = LoadLibrary(L"wininet-original.dll");
-
- if (dll != nullptr)
- {
- LOG_INFO("OptiScaler working as wininet.dll, wininet-original.dll loaded");
- break;
- }
-
- auto sysFilePath = sysPath / L"wininet.dll";
- dll = LoadLibrary(sysFilePath.wstring().c_str());
-
- if (dll != nullptr)
- LOG_INFO("OptiScaler working as wininet.dll, system dll loaded");
-
- } while (false);
-
- if (dll != nullptr)
- {
- dllNames.push_back("wininet.dll");
- dllNames.push_back("wininet");
- dllNamesW.push_back(L"wininet.dll");
- dllNamesW.push_back(L"wininet");
-
- shared.LoadOriginalLibrary(dll);
- wininet.LoadOriginalLibrary(dll);
- modeFound = true;
- }
- else
- {
- spdlog::error("OptiScaler can't find original wininet.dll!");
- }
-
- break;
- }
-
- // optiscaler.dll
- if (lCaseFilename == "optiscaler.asi")
- {
- LOG_INFO("OptiScaler working as OptiScaler.asi");
-
- // quick hack for testing
- dll = dllModule;
-
- dllNames.push_back("optiscaler.asi");
- dllNames.push_back("optiscaler");
- dllNamesW.push_back(L"optiscaler.asi");
- dllNamesW.push_back(L"optiscaler");
-
- modeFound = true;
- break;
- }
-
- // winhttp.dll
- if (lCaseFilename == "winhttp.dll")
- {
- do
- {
- auto pluginFilePath = pluginPath / L"winhttp.dll";
- dll = LoadLibrary(pluginFilePath.wstring().c_str());
-
- if (dll != nullptr)
- {
- LOG_INFO("OptiScaler working as winhttp.dll, original dll loaded from plugin folder");
- break;
- }
-
- dll = LoadLibrary(L"winhttp-original.dll");
-
- if (dll != nullptr)
- {
- LOG_INFO("OptiScaler working as winhttp.dll, winhttp-original.dll loaded");
- break;
- }
-
- auto sysFilePath = sysPath / L"winhttp.dll";
- dll = LoadLibrary(sysFilePath.wstring().c_str());
-
- if (dll != nullptr)
- LOG_INFO("OptiScaler working as winhttp.dll, system dll loaded");
-
- } while (false);
-
- if (dll != nullptr)
- {
- dllNames.push_back("winhttp.dll");
- dllNames.push_back("winhttp");
- dllNamesW.push_back(L"winhttp.dll");
- dllNamesW.push_back(L"winhttp");
-
- shared.LoadOriginalLibrary(dll);
- winhttp.LoadOriginalLibrary(dll);
- modeFound = true;
- }
- else
- {
- spdlog::error("OptiScaler can't find original winhttp.dll!");
- }
-
- break;
- }
-
- // dxgi.dll
- if (lCaseFilename == "dxgi.dll")
- {
- do
- {
- auto pluginFilePath = pluginPath / L"dxgi.dll";
- dll = LoadLibrary(pluginFilePath.wstring().c_str());
-
- if (dll != nullptr)
- {
- LOG_INFO("OptiScaler working as dxgi.dll, original dll loaded from plugin folder");
- break;
- }
-
- dll = LoadLibrary(L"dxgi-original.dll");
-
- if (dll != nullptr)
- {
- LOG_INFO("OptiScaler working as dxgi.dll, dxgi-original.dll loaded");
- break;
- }
-
- auto sysFilePath = sysPath / L"dxgi.dll";
- dll = LoadLibrary(sysFilePath.wstring().c_str());
-
- if (dll != nullptr)
- LOG_INFO("OptiScaler working as dxgi.dll, system dll loaded");
-
- } while (false);
-
- if (dll != nullptr)
- {
- dllNames.push_back("dxgi.dll");
- dllNames.push_back("dxgi");
- dllNamesW.push_back(L"dxgi.dll");
- dllNamesW.push_back(L"dxgi");
-
- shared.LoadOriginalLibrary(dll);
- dxgi.LoadOriginalLibrary(dll);
-
- Config::Instance()->IsDxgiMode = true;
- modeFound = true;
- }
- else
- {
- spdlog::error("OptiScaler can't find original dxgi.dll!");
- }
-
- break;
- }
-
- } while (false);
-
- // hook dxgi when not working as dxgi.dll
- if (!isWorkingWithEnabler && !Config::Instance()->IsDxgiMode && Config::Instance()->DxgiSpoofing.value_or(true))
- {
- LOG_INFO("DxgiSpoofing is enabled loading dxgi.dll");
-
- dxgi.CreateDxgiFactory = (PFN_CREATE_DXGI_FACTORY)DetourFindFunction("dxgi.dll", "CreateDXGIFactory");
- dxgi.CreateDxgiFactory1 = (PFN_CREATE_DXGI_FACTORY)DetourFindFunction("dxgi.dll", "CreateDXGIFactory1");
- dxgi.CreateDxgiFactory2 = (PFN_CREATE_DXGI_FACTORY_2)DetourFindFunction("dxgi.dll", "CreateDXGIFactory2");
-
- if (dxgi.CreateDxgiFactory != nullptr || dxgi.CreateDxgiFactory1 != nullptr || dxgi.CreateDxgiFactory2 != nullptr)
- {
- LOG_INFO("dxgi.dll found, hooking CreateDxgiFactory methods");
-
- DetourTransactionBegin();
- DetourUpdateThread(GetCurrentThread());
-
- if (dxgi.CreateDxgiFactory != nullptr)
- DetourAttach(&(PVOID&)dxgi.CreateDxgiFactory, _CreateDXGIFactory);
-
- if (dxgi.CreateDxgiFactory1 != nullptr)
- DetourAttach(&(PVOID&)dxgi.CreateDxgiFactory1, _CreateDXGIFactory1);
-
- if (dxgi.CreateDxgiFactory2 != nullptr)
- DetourAttach(&(PVOID&)dxgi.CreateDxgiFactory2, _CreateDXGIFactory2);
-
- DetourTransactionCommit();
- }
- }
-
- if (modeFound)
- {
- AttachHooks();
-
- Config::Instance()->OverlayMenu = (!isNvngxMode || isWorkingWithEnabler) && Config::Instance()->OverlayMenu.value_or(true);
- if (Config::Instance()->OverlayMenu.value())
- {
- if (!Config::Instance()->IsRunningOnLinux && !Config::Instance()->IsRunningOnDXVK)
- ImGuiOverlayDx::HookDx();
-
- ImGuiOverlayVk::HookVk();
- }
-
- return;
- }
-
- LOG_ERROR("Unsupported dll name: {0}", filename);
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
@@ -1363,9 +349,6 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
spdlog::warn("");
spdlog::warn("LogLevel: {0}", Config::Instance()->LogLevel.value_or(2));
- // Check for Wine
- Config::Instance()->IsRunningOnLinux = IsRunningOnWine();
-
// Check if real DLSS available
if (Config::Instance()->DLSSEnabled.value_or(true))
{
@@ -1396,16 +379,24 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
}
}
- //NVNGXLocalProxy::InitNVNGX();
- //if (NVNGXLocalProxy::NVNGXModule() == nullptr)
- // LOG_WARN("Can't init local NVNGX!");
-
+ // Init XeSS proxy
if (!XeSSProxy::InitXeSS())
- LOG_WARN("Can't init XeSS!");
+ spdlog::warn("Can't init XeSS!");
+
+ // Init FfxApi Dx12 proxy
+ if (!FfxApiProxy::InitFfxDx12())
+ spdlog::warn("Can't init Dx12 FfxApi!");
+
+ // Init FfxApi Vulkan proxy
+ if (!FfxApiProxy::InitFfxVk())
+ spdlog::warn("Can't init Vulkan FfxApi!");
// Check for working mode and attach hooks
spdlog::info("");
- CheckWorkingMode();
+
+ if (WorkingMode::Check())
+ AttachHooks();
+
spdlog::info("");
for (size_t i = 0; i < 300; i++)
diff --git a/OptiScaler/hooks/Hooks.cpp b/OptiScaler/hooks/Hooks.cpp
new file mode 100644
index 00000000..fa8704b5
--- /dev/null
+++ b/OptiScaler/hooks/Hooks.cpp
@@ -0,0 +1,6 @@
+#include "Hooks.h"
+
+void Hooks::Attach()
+{
+
+}
diff --git a/OptiScaler/hooks/Hooks.h b/OptiScaler/hooks/Hooks.h
new file mode 100644
index 00000000..beeef7f3
--- /dev/null
+++ b/OptiScaler/hooks/Hooks.h
@@ -0,0 +1,8 @@
+#pragma once
+#include
+
+class Hooks
+{
+public:
+ void Attach();
+};
\ No newline at end of file
diff --git a/OptiScaler/hooks/LoadLibrary.cpp b/OptiScaler/hooks/LoadLibrary.cpp
new file mode 100644
index 00000000..467b6b27
--- /dev/null
+++ b/OptiScaler/hooks/LoadLibrary.cpp
@@ -0,0 +1,634 @@
+#include "LoadLibrary.h"
+
+#include
+#include
+#include "Vulkan.h"
+#include
+
+#include
+
+typedef BOOL(*PFN_FreeLibrary)(HMODULE lpLibrary);
+typedef HMODULE(*PFN_LoadLibraryA)(LPCSTR lpLibFileName);
+typedef HMODULE(*PFN_LoadLibraryW)(LPCWSTR lpLibFileName);
+typedef HMODULE(*PFN_LoadLibraryExA)(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
+typedef HMODULE(*PFN_LoadLibraryExW)(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
+typedef FARPROC(*PFN_GetProcAddress)(HMODULE hModule, LPCSTR lpProcName);
+
+static PFN_FreeLibrary o_FreeLibrary = nullptr;
+static PFN_LoadLibraryA o_LoadLibraryA = nullptr;
+static PFN_LoadLibraryW o_LoadLibraryW = nullptr;
+static PFN_LoadLibraryExA o_LoadLibraryExA = nullptr;
+static PFN_LoadLibraryExW o_LoadLibraryExW = nullptr;
+static PFN_GetProcAddress o_GetProcAddress = nullptr;
+
+static std::vector upscalerNames =
+{
+ "nvngx.dll",
+ "nvngx",
+ "libxess.dll",
+ "libxess"
+};
+
+static std::vector nvngxDlss =
+{
+ "nvngx_dlss.dll",
+ "nvngx_dlss",
+};
+
+static std::vector nvapiNames =
+{
+ "nvapi64.dll",
+ "nvapi64",
+};
+
+static std::vector upscalerNamesW =
+{
+ L"nvngx.dll",
+ L"nvngx",
+ L"libxess.dll",
+ L"libxess"
+};
+
+static std::vector nvngxDlssW =
+{
+ L"nvngx_dlss.dll",
+ L"nvngx_dlss",
+};
+
+static std::vector nvapiNamesW =
+{
+ L"nvapi64.dll",
+ L"nvapi64",
+};
+
+static std::vector dx11NamesW =
+{
+ L"d3d11.dll",
+ L"d3d11",
+};
+
+static std::vector dx11Names =
+{
+ "d3d11.dll",
+ "d3d11",
+};
+
+static std::vector dx12NamesW =
+{
+ L"d3d12.dll",
+ L"d3d12",
+};
+
+static std::vector dx12Names =
+{
+ "d3d12.dll",
+ "d3d12",
+};
+
+inline std::vector dxgiNamesW =
+{
+ L"dxgi.dll",
+ L"dxgi",
+};
+
+static std::vector dxgiNames =
+{
+ "dxgi.dll",
+ "dxgi",
+};
+
+static std::vector vkNamesW =
+{
+ L"vulkan-1.dll",
+ L"vulkan-1",
+};
+
+static std::vector vkNames =
+{
+ "vulkan-1.dll",
+ "vulkan-1",
+};
+
+static bool dontCount = false;
+static bool skipLoadChecks = false;
+static UINT loadCount = 0;
+
+inline static bool CheckDllName(std::string* dllName, std::vector* namesList)
+{
+ for (size_t i = 0; i < namesList->size(); i++)
+ {
+ auto name = namesList->at(i);
+ auto pos = dllName->rfind(name);
+
+ if (pos != std::string::npos && pos == (dllName->size() - name.size()))
+ return true;
+ }
+
+ return false;
+}
+
+inline static bool CheckDllNameW(std::wstring* dllName, std::vector* namesList)
+{
+ auto found = false;
+
+ for (size_t i = 0; i < namesList->size(); i++)
+ {
+ auto name = namesList->at(i);
+ auto pos = dllName->rfind(name);
+
+ if (pos != std::string::npos && pos == (dllName->size() - name.size()))
+ return true;
+ }
+
+ return false;
+}
+
+inline static HMODULE LoadLibraryCheck(std::string lcaseLibName)
+{
+ // If Opti is not loading as nvngx.dll
+ if (!WorkingMode::IsWorkingWithEnabler() && !Config::Instance()->upscalerDisableHook)
+ {
+ // exe path
+ auto exePath = Util::ExePath().parent_path().wstring();
+
+ for (size_t i = 0; i < exePath.size(); i++)
+ exePath[i] = std::tolower(exePath[i]);
+
+ auto pos = lcaseLibName.rfind(wstring_to_string(exePath));
+
+ if (CheckDllName(&lcaseLibName, &upscalerNames) &&
+ (!Config::Instance()->HookOriginalNvngxOnly.value_or(false) || pos == std::string::npos))
+ {
+ LOG_INFO("nvngx call: {0}, returning this dll!", lcaseLibName);
+
+ if (!dontCount)
+ loadCount++;
+
+ return dllModule;
+ }
+ }
+
+ // NvApi64.dll
+ if (CheckDllName(&lcaseLibName, &nvapiNames)) {
+ if (!WorkingMode::IsWorkingWithEnabler() && Config::Instance()->OverrideNvapiDll.value_or(false))
+ {
+ LOG_INFO("{0} call!", lcaseLibName);
+
+ LoadNvApi();
+ auto nvapi = GetModuleHandleA(lcaseLibName.c_str());
+
+ // Nvapihooks intentionally won't load nvapi so have to make sure it's loaded
+ if (nvapi != nullptr) {
+ NvApiHooks::Hook(nvapi);
+ return nvapi;
+ }
+ }
+ else
+ {
+ auto nvapi = GetModuleHandleA(lcaseLibName.c_str());
+
+ // Try to load nvapi only from system32, like the original call would
+ if (nvapi == nullptr)
+ nvapi = o_LoadLibraryExA(lcaseLibName.c_str(), NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
+
+ if (nvapi != nullptr)
+ NvApiHooks::Hook(nvapi);
+
+ // AMD without nvapi override should fall through
+ }
+ }
+
+ // nvngx_dlss
+ if (Config::Instance()->DLSSEnabled.value_or(true) && Config::Instance()->DLSSLibrary.has_value() && CheckDllName(&lcaseLibName, &nvngxDlss))
+ {
+ auto nvngxDlss = LoadNvgxDlss(string_to_wstring(lcaseLibName));
+
+ if (nvngxDlss != nullptr)
+ return nvngxDlss;
+ }
+
+ // Hooks
+ skipLoadChecks = true;
+
+ if (CheckDllName(&lcaseLibName, &dx11Names) && Config::Instance()->OverlayMenu.value_or(true))
+ HooksDx::HookDx11();
+
+ if (CheckDllName(&lcaseLibName, &dx12Names) && Config::Instance()->OverlayMenu.value_or(true))
+ HooksDx::HookDx12();
+
+ if (CheckDllName(&lcaseLibName, &dxgiNames))
+ {
+ HookForDxgiSpoofing();
+
+ if (Config::Instance()->OverlayMenu.value_or(true))
+ HooksDx::HookDxgi();
+ }
+
+ if (CheckDllName(&lcaseLibName, &vkNames))
+ {
+ VulkanHooks::Hook();
+ VulkanHooks::HookExtension();
+
+ if (Config::Instance()->OverlayMenu.value_or(true))
+ HooksVk::HookVk();
+ }
+
+ skipLoadChecks = false;
+
+ if (!WorkingMode::IsNvngxMode() && CheckDllName(&lcaseLibName, &WorkingMode::DllNames()))
+ {
+ LOG_INFO("{0} call returning this dll!", lcaseLibName);
+
+ if (!dontCount)
+ loadCount++;
+
+ return dllModule;
+ }
+
+ return nullptr;
+}
+
+inline static HMODULE LoadLibraryCheckW(std::wstring lcaseLibName)
+{
+ auto lcaseLibNameA = wstring_to_string(lcaseLibName);
+
+ // If Opti is not loading as nvngx.dll
+ if (!WorkingMode::IsWorkingWithEnabler() && !Config::Instance()->upscalerDisableHook)
+ {
+ // exe path
+ auto exePath = Util::ExePath().parent_path().wstring();
+
+ for (size_t i = 0; i < exePath.size(); i++)
+ exePath[i] = std::tolower(exePath[i]);
+
+ auto pos = lcaseLibName.rfind(exePath);
+
+ if (CheckDllNameW(&lcaseLibName, &upscalerNamesW) &&
+ (!Config::Instance()->HookOriginalNvngxOnly.value_or(false) || pos == std::string::npos))
+ {
+ LOG_INFO("nvngx call: {0}, returning this dll!", lcaseLibNameA);
+
+ if (!dontCount)
+ loadCount++;
+
+ return dllModule;
+ }
+ }
+
+ // nvngx_dlss
+ if (Config::Instance()->DLSSEnabled.value_or(true) && Config::Instance()->DLSSLibrary.has_value() && CheckDllNameW(&lcaseLibName, &nvngxDlssW))
+ {
+ auto nvngxDlss = LoadNvgxDlss(lcaseLibName);
+
+ if (nvngxDlss != nullptr)
+ return nvngxDlss;
+ }
+
+ // NvApi64.dll
+ if (CheckDllNameW(&lcaseLibName, &nvapiNamesW)) {
+ if (!WorkingMode::IsWorkingWithEnabler() && Config::Instance()->OverrideNvapiDll.value_or(false))
+ {
+ LOG_INFO("{0} call!", lcaseLibNameA);
+
+ LoadNvApi();
+ auto nvapi = GetModuleHandleW(lcaseLibName.c_str());
+
+ // Nvapihooks intentionally won't load nvapi so have to make sure it's loaded
+ if (nvapi != nullptr) {
+ NvApiHooks::Hook(nvapi);
+ return nvapi;
+ }
+ }
+ else
+ {
+ auto nvapi = GetModuleHandleW(lcaseLibName.c_str());
+
+ // Try to load nvapi only from system32, like the original call would
+ if (nvapi == nullptr)
+ nvapi = o_LoadLibraryExW(lcaseLibName.c_str(), NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
+
+ if (nvapi != nullptr)
+ NvApiHooks::Hook(nvapi);
+
+ // AMD without nvapi override should fall through
+ }
+ }
+
+ // Hooks
+ skipLoadChecks = true;
+
+ if (CheckDllNameW(&lcaseLibName, &dx11NamesW) && Config::Instance()->OverlayMenu.value_or(true))
+ HooksDx::HookDx11();
+
+ if (CheckDllNameW(&lcaseLibName, &dx12NamesW) && Config::Instance()->OverlayMenu.value_or(true))
+ HooksDx::HookDx12();
+
+ if (CheckDllNameW(&lcaseLibName, &dxgiNamesW))
+ {
+ HookForDxgiSpoofing();
+
+ if (Config::Instance()->OverlayMenu.value_or(true))
+ HooksDx::HookDxgi();
+ }
+
+ if (CheckDllNameW(&lcaseLibName, &vkNamesW))
+ {
+ VulkanHooks::Hook();
+ VulkanHooks::HookExtension();
+
+ if (Config::Instance()->OverlayMenu.value_or(true))
+ HooksVk::HookVk();
+ }
+
+ skipLoadChecks = false;
+
+ if (!WorkingMode::IsNvngxMode() && CheckDllNameW(&lcaseLibName, &WorkingMode::DllNamesW()))
+ {
+ LOG_INFO("{0} call returning this dll!", lcaseLibNameA);
+
+ if (!dontCount)
+ loadCount++;
+
+ return dllModule;
+ }
+
+ return nullptr;
+}
+
+static HMODULE LoadNvApi()
+{
+ HMODULE nvapi = nullptr;
+
+ if (Config::Instance()->NvapiDllPath.has_value())
+ {
+ nvapi = o_LoadLibraryW(Config::Instance()->NvapiDllPath->c_str());
+
+ if (nvapi != nullptr)
+ {
+ LOG_INFO("nvapi64.dll loaded from {0}", wstring_to_string(Config::Instance()->NvapiDllPath.value()));
+ return nvapi;
+ }
+ }
+
+ if (nvapi == nullptr)
+ {
+ auto localPath = Util::DllPath().parent_path() / L"nvapi64.dll";
+ nvapi = o_LoadLibraryW(localPath.wstring().c_str());
+
+ if (nvapi != nullptr)
+ {
+ LOG_INFO("nvapi64.dll loaded from {0}", wstring_to_string(localPath.wstring()));
+ return nvapi;
+ }
+ }
+
+ if (nvapi == nullptr)
+ {
+ nvapi = o_LoadLibraryW(L"nvapi64.dll");
+
+ if (nvapi != nullptr)
+ {
+ LOG_WARN("nvapi64.dll loaded from system!");
+ return nvapi;
+ }
+ }
+
+ return nullptr;
+}
+
+static HMODULE LoadNvgxDlss(std::wstring originalPath)
+{
+ HMODULE nvngxDlss = nullptr;
+
+ if (Config::Instance()->NVNGX_DLSS_Library.has_value())
+ {
+ nvngxDlss = o_LoadLibraryW(Config::Instance()->NVNGX_DLSS_Library.value().c_str());
+
+ if (nvngxDlss != nullptr)
+ {
+ LOG_INFO("nvngx_dlss.dll loaded from {0}", wstring_to_string(Config::Instance()->NVNGX_DLSS_Library.value()));
+ return nvngxDlss;
+ }
+ else
+ {
+ LOG_WARN("nvngx_dlss.dll can't found at {0}", wstring_to_string(Config::Instance()->NVNGX_DLSS_Library.value()));
+ }
+ }
+
+ if (nvngxDlss == nullptr)
+ {
+ nvngxDlss = o_LoadLibraryW(originalPath.c_str());
+
+ if (nvngxDlss != nullptr)
+ {
+ LOG_INFO("nvngx_dlss.dll loaded from {0}", wstring_to_string(originalPath));
+ return nvngxDlss;
+ }
+ }
+
+ return nullptr;
+}
+
+static FARPROC hkGetProcAddress(HMODULE hModule, LPCSTR lpProcName)
+{
+ if (hModule == dllModule)
+ LOG_DEBUG("Trying to get process address of {0}", lpProcName);
+
+ return o_GetProcAddress(hModule, lpProcName);
+}
+
+static BOOL hkFreeLibrary(HMODULE lpLibrary)
+{
+ if (lpLibrary == nullptr)
+ return FALSE;
+
+ if (lpLibrary == dllModule)
+ {
+ if (loadCount > 0)
+ loadCount--;
+
+ LOG_INFO("Call for this module loadCount: {0}", loadCount);
+
+ if (loadCount == 0)
+ {
+ auto result = o_FreeLibrary(lpLibrary);
+ LOG_DEBUG("o_FreeLibrary result: {0:X}", result);
+ }
+ else
+ {
+ return TRUE;
+ }
+ }
+
+ return o_FreeLibrary(lpLibrary);
+}
+
+static HMODULE hkLoadLibraryA(LPCSTR lpLibFileName)
+{
+ if (lpLibFileName == nullptr)
+ return NULL;
+
+ if (skipLoadChecks)
+ return o_LoadLibraryA(lpLibFileName);;
+
+ std::string libName(lpLibFileName);
+ std::string lcaseLibName(libName);
+
+ for (size_t i = 0; i < lcaseLibName.size(); i++)
+ lcaseLibName[i] = std::tolower(lcaseLibName[i]);
+
+#ifdef _DEBUG
+ LOG_TRACE("call: {0}", lcaseLibName);
+#endif // DEBUG
+
+ auto moduleHandle = LoadLibraryCheck(lcaseLibName);
+
+ if (moduleHandle != nullptr)
+ return moduleHandle;
+
+ dontCount = true;
+ auto result = o_LoadLibraryA(lpLibFileName);
+ dontCount = false;
+
+ return result;
+}
+
+static HMODULE hkLoadLibraryW(LPCWSTR lpLibFileName)
+{
+ if (lpLibFileName == nullptr)
+ return NULL;
+
+ if (skipLoadChecks)
+ return o_LoadLibraryW(lpLibFileName);;
+
+ std::wstring libName(lpLibFileName);
+ std::wstring lcaseLibName(libName);
+
+ for (size_t i = 0; i < lcaseLibName.size(); i++)
+ lcaseLibName[i] = std::tolower(lcaseLibName[i]);
+
+#ifdef _DEBUG
+ LOG_TRACE("call: {0}", wstring_to_string(lcaseLibName));
+#endif // DEBUG
+
+ auto moduleHandle = LoadLibraryCheckW(lcaseLibName);
+
+ if (moduleHandle != nullptr)
+ return moduleHandle;
+
+ dontCount = true;
+ auto result = o_LoadLibraryW(lpLibFileName);
+ dontCount = false;
+
+ return result;
+}
+
+static HMODULE hkLoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
+{
+ if (lpLibFileName == nullptr)
+ return NULL;
+
+ if (skipLoadChecks)
+ return o_LoadLibraryExA(lpLibFileName, hFile, dwFlags);
+
+ std::string libName(lpLibFileName);
+ std::string lcaseLibName(libName);
+
+ for (size_t i = 0; i < lcaseLibName.size(); i++)
+ lcaseLibName[i] = std::tolower(lcaseLibName[i]);
+
+#ifdef _DEBUG
+ LOG_TRACE("call: {0}", lcaseLibName);
+#endif
+
+ auto moduleHandle = LoadLibraryCheck(lcaseLibName);
+
+ if (moduleHandle != nullptr)
+ return moduleHandle;
+
+
+ dontCount = true;
+ auto result = o_LoadLibraryExA(lpLibFileName, hFile, dwFlags);
+ dontCount = false;
+
+ return result;
+}
+
+static HMODULE hkLoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
+{
+ if (lpLibFileName == nullptr)
+ return NULL;
+
+ if (skipLoadChecks)
+ return o_LoadLibraryExW(lpLibFileName, hFile, dwFlags);
+
+ std::wstring libName(lpLibFileName);
+ std::wstring lcaseLibName(libName);
+
+ for (size_t i = 0; i < lcaseLibName.size(); i++)
+ lcaseLibName[i] = std::tolower(lcaseLibName[i]);
+
+#ifdef _DEBUG
+ LOG_TRACE("call: {0}", wstring_to_string(lcaseLibName));
+#endif
+
+ auto moduleHandle = LoadLibraryCheckW(lcaseLibName);
+
+ if (moduleHandle != nullptr)
+ return moduleHandle;
+
+ dontCount = true;
+ auto result = o_LoadLibraryExW(lpLibFileName, hFile, dwFlags);
+ dontCount = false;
+
+ return result;
+}
+
+void LoadLibraryHooks::Hook()
+{
+ LOG_FUNC();
+
+ if (o_LoadLibraryA == nullptr || o_LoadLibraryW == nullptr)
+ {
+ // Detour the functions
+ o_FreeLibrary = reinterpret_cast(DetourFindFunction("kernel32.dll", "FreeLibrary"));
+
+ o_LoadLibraryA = reinterpret_cast(DetourFindFunction("kernel32.dll", "LoadLibraryA"));
+ o_LoadLibraryW = reinterpret_cast(DetourFindFunction("kernel32.dll", "LoadLibraryW"));
+ o_LoadLibraryExA = reinterpret_cast(DetourFindFunction("kernel32.dll", "LoadLibraryExA"));
+ o_LoadLibraryExW = reinterpret_cast(DetourFindFunction("kernel32.dll", "LoadLibraryExW"));
+
+#ifdef _DEBUG
+ //o_GetProcAddress = reinterpret_cast(DetourFindFunction("kernel32.dll", "GetProcAddress"));
+#endif // DEBUG
+
+ if (o_LoadLibraryA != nullptr || o_LoadLibraryW != nullptr || o_LoadLibraryExA != nullptr || o_LoadLibraryExW != nullptr)
+ {
+ LOG_INFO("Attaching LoadLibrary hooks");
+
+ DetourTransactionBegin();
+ DetourUpdateThread(GetCurrentThread());
+
+ if (o_FreeLibrary)
+ DetourAttach(&(PVOID&)o_FreeLibrary, hkFreeLibrary);
+
+ if (o_LoadLibraryA)
+ DetourAttach(&(PVOID&)o_LoadLibraryA, hkLoadLibraryA);
+
+ if (o_LoadLibraryW)
+ DetourAttach(&(PVOID&)o_LoadLibraryW, hkLoadLibraryW);
+
+ if (o_LoadLibraryExA)
+ DetourAttach(&(PVOID&)o_LoadLibraryExA, hkLoadLibraryExA);
+
+ if (o_LoadLibraryExW)
+ DetourAttach(&(PVOID&)o_LoadLibraryExW, hkLoadLibraryExW);
+
+ if (o_GetProcAddress)
+ DetourAttach(&(PVOID&)o_GetProcAddress, hkGetProcAddress);
+
+ DetourTransactionCommit();
+ }
+ }
+}
+
\ No newline at end of file
diff --git a/OptiScaler/hooks/LoadLibrary.h b/OptiScaler/hooks/LoadLibrary.h
new file mode 100644
index 00000000..6399615c
--- /dev/null
+++ b/OptiScaler/hooks/LoadLibrary.h
@@ -0,0 +1,10 @@
+#pragma once
+#include
+
+class LoadLibraryHooks
+{
+private:
+public:
+ void Hook();
+ void Unhook();
+};
diff --git a/OptiScaler/hooks/Vulkan.cpp b/OptiScaler/hooks/Vulkan.cpp
new file mode 100644
index 00000000..5e5620bc
--- /dev/null
+++ b/OptiScaler/hooks/Vulkan.cpp
@@ -0,0 +1,403 @@
+#include "Vulkan.h"
+
+#include
+#include
+#include
+
+#include
+
+typedef struct VkDummyProps
+{
+ VkStructureType sType;
+ void* pNext;
+} VkDummyProps;
+
+static PFN_vkGetPhysicalDeviceProperties o_vkGetPhysicalDeviceProperties = nullptr;
+static PFN_vkGetPhysicalDeviceProperties2 o_vkGetPhysicalDeviceProperties2 = nullptr;
+static PFN_vkGetPhysicalDeviceProperties2KHR o_vkGetPhysicalDeviceProperties2KHR = nullptr;
+
+static PFN_vkEnumerateInstanceExtensionProperties o_vkEnumerateInstanceExtensionProperties = nullptr;
+static PFN_vkEnumerateDeviceExtensionProperties o_vkEnumerateDeviceExtensionProperties = nullptr;
+static PFN_vkCreateDevice o_vkCreateDevice = nullptr;
+static PFN_vkCreateInstance o_vkCreateInstance = nullptr;
+
+static uint32_t vkEnumerateInstanceExtensionPropertiesCount = 0;
+static uint32_t vkEnumerateDeviceExtensionPropertiesCount = 0;
+
+static void hkvkGetPhysicalDeviceProperties(VkPhysicalDevice physical_device, VkPhysicalDeviceProperties* properties)
+{
+ o_vkGetPhysicalDeviceProperties(physical_device, properties);
+
+ if (!Config::Instance()->dxgiSkipSpoofing)
+ {
+ auto deviceName = wstring_to_string(Config::Instance()->SpoofedGPUName.value_or(L"NVIDIA GeForce RTX 4090"));
+ std::strcpy(properties->deviceName, deviceName.c_str());
+ properties->vendorID = 0x10de;
+ properties->deviceID = 0x2684;
+ properties->driverVersion = VK_MAKE_API_VERSION(559, 0, 0, 0);
+ }
+ else
+ {
+ LOG_DEBUG("Skipping spoofing");
+ }
+}
+
+static void hkvkGetPhysicalDeviceProperties2(VkPhysicalDevice phys_dev, VkPhysicalDeviceProperties2* properties2)
+{
+ o_vkGetPhysicalDeviceProperties2(phys_dev, properties2);
+
+ if (!Config::Instance()->dxgiSkipSpoofing)
+ {
+ auto deviceName = wstring_to_string(Config::Instance()->SpoofedGPUName.value_or(L"NVIDIA GeForce RTX 4090"));
+ std::strcpy(properties2->properties.deviceName, deviceName.c_str());
+ properties2->properties.vendorID = 0x10de;
+ properties2->properties.deviceID = 0x2684;
+ properties2->properties.driverVersion = VK_MAKE_API_VERSION(559, 0, 0, 0);
+
+ auto next = (VkDummyProps*)properties2->pNext;
+
+ while (next != nullptr)
+ {
+ if (next->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES)
+ {
+ auto ddp = (VkPhysicalDeviceDriverProperties*)(void*)next;
+ ddp->driverID = VK_DRIVER_ID_NVIDIA_PROPRIETARY;
+ std::strcpy(ddp->driverName, "NVIDIA");
+ std::strcpy(ddp->driverInfo, "559.0");
+ }
+
+ next = (VkDummyProps*)next->pNext;
+ }
+ }
+ else
+ {
+ LOG_DEBUG("Skipping spoofing");
+ }
+}
+
+static void hkvkGetPhysicalDeviceProperties2KHR(VkPhysicalDevice phys_dev, VkPhysicalDeviceProperties2* properties2)
+{
+ o_vkGetPhysicalDeviceProperties2KHR(phys_dev, properties2);
+
+ if (!Config::Instance()->dxgiSkipSpoofing)
+ {
+ auto deviceName = wstring_to_string(Config::Instance()->SpoofedGPUName.value_or(L"NVIDIA GeForce RTX 4090"));
+ std::strcpy(properties2->properties.deviceName, deviceName.c_str());
+ properties2->properties.vendorID = 0x10de;
+ properties2->properties.deviceID = 0x2684;
+ properties2->properties.driverVersion = VK_MAKE_API_VERSION(559, 0, 0, 0);
+
+ auto next = (VkDummyProps*)properties2->pNext;
+
+ while (next != nullptr)
+ {
+ if (next->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES)
+ {
+ auto ddp = (VkPhysicalDeviceDriverProperties*)(void*)next;
+ ddp->driverID = VK_DRIVER_ID_NVIDIA_PROPRIETARY;
+ std::strcpy(ddp->driverName, "NVIDIA");
+ std::strcpy(ddp->driverInfo, "559.0");
+ }
+
+ next = (VkDummyProps*)next->pNext;
+ }
+ }
+ else
+ {
+ LOG_DEBUG("Skipping spoofing");
+ }
+}
+
+static VkResult hkvkCreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance)
+{
+ LOG_DEBUG("for {0}", pCreateInfo->pApplicationInfo->pApplicationName);
+
+ LOG_DEBUG("extensions ({0}):", pCreateInfo->enabledExtensionCount);
+ for (size_t i = 0; i < pCreateInfo->enabledExtensionCount; i++)
+ LOG_DEBUG(" {0}", pCreateInfo->ppEnabledExtensionNames[i]);
+
+ LOG_DEBUG("layers ({0}):", pCreateInfo->enabledLayerCount);
+ for (size_t i = 0; i < pCreateInfo->enabledLayerCount; i++)
+ LOG_DEBUG(" {0}", pCreateInfo->ppEnabledLayerNames[i]);
+
+ // Skip spoofing for Intel Arc
+ Config::Instance()->dxgiSkipSpoofing = true;
+ auto result = o_vkCreateInstance(pCreateInfo, pAllocator, pInstance);
+ Config::Instance()->dxgiSkipSpoofing = false;
+
+ LOG_DEBUG("o_vkCreateInstance result: {0:X}", (INT)result);
+
+ auto head = (VkBaseInStructure*)pCreateInfo;
+
+ while (head->pNext != nullptr)
+ {
+ head = (VkBaseInStructure*)head->pNext;
+ LOG_DEBUG("o_vkCreateInstance type: {0:X}", (UINT)head->sType);
+ }
+
+ return result;
+}
+
+static VkResult hkvkCreateDevice(VkPhysicalDevice physicalDevice, VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice)
+{
+ LOG_FUNC();
+
+ if (!Config::Instance()->VulkanExtensionSpoofing.value_or(false))
+ {
+ LOG_DEBUG("extension spoofing is disabled");
+
+ Config::Instance()->dxgiSkipSpoofing = true;
+ return o_vkCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
+ Config::Instance()->dxgiSkipSpoofing = false;
+ }
+
+ LOG_DEBUG("layers ({0}):", pCreateInfo->enabledLayerCount);
+ for (size_t i = 0; i < pCreateInfo->enabledLayerCount; i++)
+ LOG_DEBUG(" {0}", pCreateInfo->ppEnabledLayerNames[i]);
+
+ std::vector newExtensionList;
+
+ auto bVK_KHR_get_memory_requirements2 = false;
+
+ LOG_DEBUG("checking extensions and removing VK_NVX_BINARY_IMPORT & VK_NVX_IMAGE_VIEW_HANDLE from list");
+ for (size_t i = 0; i < pCreateInfo->enabledExtensionCount; i++)
+ {
+ if (std::strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_NVX_BINARY_IMPORT_EXTENSION_NAME) == 0 || std::strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME) == 0)
+ {
+ LOG_DEBUG("removing {0}", pCreateInfo->ppEnabledExtensionNames[i]);
+ }
+ else
+ {
+ LOG_DEBUG("adding {0}", pCreateInfo->ppEnabledExtensionNames[i]);
+ newExtensionList.push_back(pCreateInfo->ppEnabledExtensionNames[i]);
+
+ if (std::strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME) == 0)
+ bVK_KHR_get_memory_requirements2 = true;
+ }
+ }
+
+ if (!bVK_KHR_get_memory_requirements2)
+ newExtensionList.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
+
+ pCreateInfo->enabledExtensionCount = static_cast(newExtensionList.size());
+ pCreateInfo->ppEnabledExtensionNames = newExtensionList.data();
+
+ LOG_DEBUG("final extension count: {0}", pCreateInfo->enabledExtensionCount);
+ LOG_DEBUG("final extensions:");
+
+ for (size_t i = 0; i < pCreateInfo->enabledExtensionCount; i++)
+ LOG_DEBUG(" {0}", pCreateInfo->ppEnabledExtensionNames[i]);
+
+ // Skip spoofing for Intel Arc
+ Config::Instance()->dxgiSkipSpoofing = true;
+ auto result = o_vkCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
+ Config::Instance()->dxgiSkipSpoofing = false;
+
+ LOG_FUNC_RESULT(result);
+
+ return result;
+}
+
+static VkResult hkvkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties)
+{
+ LOG_FUNC();
+
+ auto count = *pPropertyCount;
+ auto result = o_vkEnumerateDeviceExtensionProperties(physicalDevice, pLayerName, pPropertyCount, pProperties);
+
+ if (result != VK_SUCCESS)
+ {
+ LOG_ERROR("o_vkEnumerateDeviceExtensionProperties({0}, {1}) result: {2:X}", pLayerName, count, (UINT)result);
+ return result;
+ }
+
+ if (pLayerName == nullptr && pProperties == nullptr && count == 0)
+ {
+ *pPropertyCount += 2;
+ vkEnumerateDeviceExtensionPropertiesCount = *pPropertyCount;
+ LOG_TRACE("hkvkEnumerateDeviceExtensionProperties({0}) count: {1}", pLayerName, vkEnumerateDeviceExtensionPropertiesCount);
+ return result;
+ }
+
+ if (pLayerName == nullptr && pProperties != nullptr && *pPropertyCount > 0)
+ {
+ if (count == vkEnumerateDeviceExtensionPropertiesCount)
+ *pPropertyCount = count;
+
+ VkExtensionProperties bi{ VK_NVX_BINARY_IMPORT_EXTENSION_NAME, VK_NVX_BINARY_IMPORT_SPEC_VERSION };
+ memcpy(&pProperties[*pPropertyCount - 1], &bi, sizeof(VkExtensionProperties));
+
+ VkExtensionProperties ivh{ VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME, VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION };
+ memcpy(&pProperties[*pPropertyCount - 2], &ivh, sizeof(VkExtensionProperties));
+ }
+
+ LOG_FUNC_RESULT(result);
+
+ return result;
+}
+
+static VkResult hkvkEnumerateInstanceExtensionProperties(const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties)
+{
+ LOG_FUNC();
+
+ auto count = *pPropertyCount;
+ auto result = o_vkEnumerateInstanceExtensionProperties(pLayerName, pPropertyCount, pProperties);
+
+ if (result != VK_SUCCESS)
+ {
+ LOG_ERROR("o_vkEnumerateInstanceExtensionProperties({0}, {1}) result: {2:X}", pLayerName, count, (UINT)result);
+ return result;
+ }
+
+ if (pLayerName == nullptr && pProperties == nullptr && count == 0)
+ {
+ *pPropertyCount += 2;
+ vkEnumerateInstanceExtensionPropertiesCount = *pPropertyCount;
+ LOG_TRACE("hkvkEnumerateDeviceExtensionProperties({0}) count: {1}", pLayerName, vkEnumerateDeviceExtensionPropertiesCount);
+ return result;
+ }
+
+ if (pLayerName == nullptr && pProperties != nullptr && *pPropertyCount > 0)
+ {
+ if (vkEnumerateInstanceExtensionPropertiesCount == count)
+ *pPropertyCount = count;
+
+ VkExtensionProperties bi{ VK_NVX_BINARY_IMPORT_EXTENSION_NAME, VK_NVX_BINARY_IMPORT_SPEC_VERSION };
+ memcpy(&pProperties[*pPropertyCount - 1], &bi, sizeof(VkExtensionProperties));
+
+ VkExtensionProperties ivh{ VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME, VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION };
+ memcpy(&pProperties[*pPropertyCount - 2], &ivh, sizeof(VkExtensionProperties));
+ }
+
+ LOG_FUNC_RESULT(result);
+
+ return result;
+}
+
+void VulkanHooks::Hook()
+{
+ if (!WorkingMode::IsNvngxMode() && Config::Instance()->VulkanSpoofing.value_or(false) && o_vkGetPhysicalDeviceProperties == nullptr)
+ {
+ o_vkGetPhysicalDeviceProperties = reinterpret_cast(DetourFindFunction("vulkan-1.dll", "vkGetPhysicalDeviceProperties"));
+ o_vkGetPhysicalDeviceProperties2 = reinterpret_cast(DetourFindFunction("vulkan-1.dll", "vkGetPhysicalDeviceProperties2"));
+ o_vkGetPhysicalDeviceProperties2KHR = reinterpret_cast(DetourFindFunction("vulkan-1.dll", "vkGetPhysicalDeviceProperties2KHR"));
+
+ if (o_vkGetPhysicalDeviceProperties != nullptr)
+ {
+ LOG_INFO("Attaching Vulkan device spoofing hooks");
+
+ DetourTransactionBegin();
+ DetourUpdateThread(GetCurrentThread());
+
+ if (o_vkGetPhysicalDeviceProperties)
+ DetourAttach(&(PVOID&)o_vkGetPhysicalDeviceProperties, hkvkGetPhysicalDeviceProperties);
+
+ if (o_vkGetPhysicalDeviceProperties2)
+ DetourAttach(&(PVOID&)o_vkGetPhysicalDeviceProperties2, hkvkGetPhysicalDeviceProperties2);
+
+ if (o_vkGetPhysicalDeviceProperties2KHR)
+ DetourAttach(&(PVOID&)o_vkGetPhysicalDeviceProperties2KHR, hkvkGetPhysicalDeviceProperties2KHR);
+
+ DetourTransactionCommit();
+ }
+ }
+}
+
+void VulkanHooks::HookExtension()
+{
+ if (!WorkingMode::IsNvngxMode() && Config::Instance()->VulkanExtensionSpoofing.value_or(false) && o_vkEnumerateInstanceExtensionProperties == nullptr)
+ {
+ o_vkCreateDevice = reinterpret_cast(DetourFindFunction("vulkan-1.dll", "vkCreateDevice"));
+ o_vkCreateInstance = reinterpret_cast(DetourFindFunction("vulkan-1.dll", "vkCreateInstance"));
+ o_vkEnumerateInstanceExtensionProperties = reinterpret_cast(DetourFindFunction("vulkan-1.dll", "vkEnumerateInstanceExtensionProperties"));
+ o_vkEnumerateDeviceExtensionProperties = reinterpret_cast(DetourFindFunction("vulkan-1.dll", "vkEnumerateDeviceExtensionProperties"));
+
+ if (o_vkEnumerateInstanceExtensionProperties != nullptr || o_vkEnumerateDeviceExtensionProperties != nullptr)
+ {
+ LOG_INFO("Attaching Vulkan extensions spoofing hooks");
+
+ DetourTransactionBegin();
+ DetourUpdateThread(GetCurrentThread());
+
+ if (o_vkEnumerateInstanceExtensionProperties)
+ DetourAttach(&(PVOID&)o_vkEnumerateInstanceExtensionProperties, hkvkEnumerateInstanceExtensionProperties);
+
+ if (o_vkEnumerateDeviceExtensionProperties)
+ DetourAttach(&(PVOID&)o_vkEnumerateDeviceExtensionProperties, hkvkEnumerateDeviceExtensionProperties);
+
+ if (o_vkCreateDevice)
+ DetourAttach(&(PVOID&)o_vkCreateDevice, hkvkCreateDevice);
+
+ if (o_vkCreateInstance)
+ DetourAttach(&(PVOID&)o_vkCreateInstance, hkvkCreateInstance);
+
+ DetourTransactionCommit();
+ }
+ }
+}
+
+void VulkanHooks::Unhook()
+{
+ if (o_vkGetPhysicalDeviceProperties != nullptr)
+ {
+ DetourTransactionBegin();
+
+ DetourUpdateThread(GetCurrentThread());
+
+ if (o_vkGetPhysicalDeviceProperties)
+ {
+ DetourDetach(&(PVOID&)o_vkGetPhysicalDeviceProperties, hkvkGetPhysicalDeviceProperties);
+ o_vkGetPhysicalDeviceProperties = nullptr;
+ }
+
+ if (o_vkGetPhysicalDeviceProperties2)
+ {
+ DetourDetach(&(PVOID&)o_vkGetPhysicalDeviceProperties2, hkvkGetPhysicalDeviceProperties2);
+ o_vkGetPhysicalDeviceProperties2 = nullptr;
+ }
+
+ if (o_vkGetPhysicalDeviceProperties2KHR)
+ {
+ DetourDetach(&(PVOID&)o_vkGetPhysicalDeviceProperties2KHR, hkvkGetPhysicalDeviceProperties2KHR);
+ o_vkGetPhysicalDeviceProperties2KHR = nullptr;
+ }
+
+ DetourTransactionCommit();
+ }
+}
+
+void VulkanHooks::UnhookExtension()
+{
+ if (o_vkGetPhysicalDeviceProperties != nullptr)
+ {
+ DetourTransactionBegin();
+
+ DetourUpdateThread(GetCurrentThread());
+
+ if (o_vkEnumerateInstanceExtensionProperties)
+ {
+ DetourDetach(&(PVOID&)o_vkEnumerateInstanceExtensionProperties, hkvkEnumerateInstanceExtensionProperties);
+ o_vkEnumerateInstanceExtensionProperties = nullptr;
+ }
+
+ if (o_vkEnumerateDeviceExtensionProperties)
+ {
+ DetourDetach(&(PVOID&)o_vkEnumerateDeviceExtensionProperties, hkvkEnumerateDeviceExtensionProperties);
+ o_vkEnumerateDeviceExtensionProperties = nullptr;
+ }
+
+ if (o_vkCreateDevice)
+ {
+ DetourDetach(&(PVOID&)o_vkCreateDevice, hkvkCreateDevice);
+ o_vkCreateDevice = nullptr;
+ }
+
+ if (o_vkCreateInstance)
+ {
+ DetourDetach(&(PVOID&)o_vkCreateInstance, hkvkCreateInstance);
+ o_vkCreateInstance = nullptr;
+ }
+
+ DetourTransactionCommit();
+ }
+}
diff --git a/OptiScaler/hooks/Vulkan.h b/OptiScaler/hooks/Vulkan.h
new file mode 100644
index 00000000..2fec977b
--- /dev/null
+++ b/OptiScaler/hooks/Vulkan.h
@@ -0,0 +1,12 @@
+#pragma once
+#include
+
+class VulkanHooks
+{
+private:
+public:
+ static void Hook();
+ static void HookExtension();
+ static void Unhook();
+ static void UnhookExtension();
+};
\ No newline at end of file
diff --git a/external/FidelityFX-SDK b/external/FidelityFX-SDK
index cb85ce28..0efa96cb 160000
--- a/external/FidelityFX-SDK
+++ b/external/FidelityFX-SDK
@@ -1 +1 @@
-Subproject commit cb85ce28befec2aaaa50e93fcef155c32ba7c920
+Subproject commit 0efa96cbc291dc1d506d0b20d4b538edd5ef03e9