This commit is contained in:
cdozdil
2024-11-10 00:34:44 +03:00
parent c7274d764f
commit 69b2d62938
22 changed files with 2179 additions and 777 deletions
+8 -6
View File
@@ -191,9 +191,11 @@ copy $(SolutionDir)nvngx.ini $(SolutionDir)x64\Release\a\</Command>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="ag\pag_common.h" />
<ClInclude Include="hooks\Hooks.h" />
<ClInclude Include="hooks\Dxgi.h" />
<ClInclude Include="hooks\LoadLibrary.h" />
<ClInclude Include="hooks\Vulkan.h" />
<ClInclude Include="menu\MenuDx11.h" />
<ClInclude Include="menu\MenuDx12.h" />
<ClInclude Include="nvapi\fakenvapi.h" />
<ClInclude Include="nvapi\NvApiHooks.h" />
<ClInclude Include="nvapi\NvApiTypes.h" />
@@ -260,9 +262,8 @@ copy $(SolutionDir)nvngx.ini $(SolutionDir)x64\Release\a\</Command>
<ClInclude Include="menu\OldMenuDx11.h" />
<ClInclude Include="menu\OldMenuDx12.h" />
<ClInclude Include="menu\MenuBase.h" />
<ClInclude Include="menu\MenuDx.h" />
<ClInclude Include="menu\MenuVulkan.h" />
<ClInclude Include="menu\wrapped_swapchain.h" />
<ClInclude Include="objects\WrappedSwapChain.h" />
<ClInclude Include="Logger.h" />
<ClInclude Include="apis\NVNGX_Parameter.h" />
<ClInclude Include="proxies\NVNGX_Proxy.h" />
@@ -279,9 +280,11 @@ copy $(SolutionDir)nvngx.ini $(SolutionDir)x64\Release\a\</Command>
<ClInclude Include="WorkingMode.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="hooks\Hooks.cpp" />
<ClCompile Include="hooks\Dxgi.cpp" />
<ClCompile Include="hooks\LoadLibrary.cpp" />
<ClCompile Include="hooks\Vulkan.cpp" />
<ClCompile Include="menu\MenuDx11.cpp" />
<ClCompile Include="menu\MenuDx12.cpp" />
<ClCompile Include="upscalers\dlssd\DLSSDFeature.cpp" />
<ClCompile Include="upscalers\dlssd\DLSSDFeature_Dx11.cpp" />
<ClCompile Include="upscalers\dlssd\DLSSDFeature_Dx12.cpp" />
@@ -327,9 +330,8 @@ copy $(SolutionDir)nvngx.ini $(SolutionDir)x64\Release\a\</Command>
<ClCompile Include="menu\OldMenuDx11.cpp" />
<ClCompile Include="menu\OldMenuDx12.cpp" />
<ClCompile Include="menu\MenuBase.cpp" />
<ClCompile Include="menu\MenuDx.cpp" />
<ClCompile Include="menu\MenuVulkan.cpp" />
<ClCompile Include="menu\wrapped_swapchain.cpp" />
<ClCompile Include="objects\WrappedSwapChain.cpp" />
<ClCompile Include="Logger.cpp" />
<ClCompile Include="apis\NVNGX.cpp" />
<ClCompile Include="apis\NVNGX_DLSS_Dx11.cpp" />
+25 -25
View File
@@ -1,18 +1,18 @@
#include "pch.h"
#include <pch.h>
#include "Util.h"
#include "Config.h"
#include <Util.h>
#include <Config.h>
#include <menu/MenuDx.h>
#include "NVNGX_Parameter.h"
#include "proxies/NVNGX_Proxy.h"
#include "menu/imgui_overlay_dx.h"
#include "upscalers/dlss/DLSSFeature_Dx11.h"
#include "upscalers/dlssd/DLSSDFeature_Dx11.h"
#include "upscalers/fsr2/FSR2Feature_Dx11.h"
#include "upscalers/fsr2/FSR2Feature_Dx11On12.h"
#include "upscalers/fsr2_212/FSR2Feature_Dx11On12_212.h"
#include "upscalers/fsr31/FSR31Feature_Dx11.h"
#include "upscalers/fsr31/FSR31Feature_Dx11On12.h"
#include "upscalers/xess/XeSSFeature_Dx11.h"
#include <proxies/NVNGX_Proxy.h>
#include <upscalers/dlss/DLSSFeature_Dx11.h>
#include <upscalers/dlssd/DLSSDFeature_Dx11.h>
#include <upscalers/fsr2/FSR2Feature_Dx11.h>
#include <upscalers/fsr2/FSR2Feature_Dx11On12.h>
#include <upscalers/fsr2_212/FSR2Feature_Dx11On12_212.h>
#include <upscalers/fsr31/FSR31Feature_Dx11.h>
#include <upscalers/fsr31/FSR31Feature_Dx11On12.h>
#include <upscalers/xess/XeSSFeature_Dx11.h>
#include <ankerl/unordered_dense.h>
@@ -90,11 +90,11 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D11_Init_Ext(unsigned long long InApp
D3D11_QUERY_DESC timestampQueryDesc = {};
timestampQueryDesc.Query = D3D11_QUERY_TIMESTAMP;
for (int i = 0; i < ImGuiOverlayDx::QUERY_BUFFER_COUNT; i++)
for (int i = 0; i < MenuDx::QUERY_BUFFER_COUNT; i++)
{
InDevice->CreateQuery(&disjointQueryDesc, &ImGuiOverlayDx::disjointQueries[i]);
InDevice->CreateQuery(&timestampQueryDesc, &ImGuiOverlayDx::startQueries[i]);
InDevice->CreateQuery(&timestampQueryDesc, &ImGuiOverlayDx::endQueries[i]);
InDevice->CreateQuery(&disjointQueryDesc, &MenuDx::disjointQueries[i]);
InDevice->CreateQuery(&timestampQueryDesc, &MenuDx::startQueries[i]);
InDevice->CreateQuery(&timestampQueryDesc, &MenuDx::endQueries[i]);
}
return NVSDK_NGX_Result_Success;
@@ -208,7 +208,7 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D11_Shutdown()
// Unhooking and cleaning stuff causing issues during shutdown.
// Disabled for now to check if it cause any issues
//ImGuiOverlayDx::UnHookDx();
//MenuDx::UnHookDx();
shutdown = false;
@@ -831,12 +831,12 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D11_EvaluateFeature(ID3D11DeviceConte
}
// In the render loop:
ImGuiOverlayDx::previousFrameIndex = (ImGuiOverlayDx::currentFrameIndex + ImGuiOverlayDx::QUERY_BUFFER_COUNT - 2) % ImGuiOverlayDx::QUERY_BUFFER_COUNT;
int nextFrameIndex = ImGuiOverlayDx::currentFrameIndex;
MenuDx::previousFrameIndex = (MenuDx::currentFrameIndex + MenuDx::QUERY_BUFFER_COUNT - 2) % MenuDx::QUERY_BUFFER_COUNT;
int nextFrameIndex = MenuDx::currentFrameIndex;
// Record the queries in the current frame
InDevCtx->Begin(ImGuiOverlayDx::disjointQueries[nextFrameIndex]);
InDevCtx->End(ImGuiOverlayDx::startQueries[nextFrameIndex]);
InDevCtx->Begin(MenuDx::disjointQueries[nextFrameIndex]);
InDevCtx->End(MenuDx::startQueries[nextFrameIndex]);
if (!deviceContext->Evaluate(InDevCtx, InParameters) && !deviceContext->IsInited() && (deviceContext->Name() == "XeSS" || deviceContext->Name() == "DLSS" || deviceContext->Name() == "FSR3 w/Dx12"))
{
@@ -844,10 +844,10 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D11_EvaluateFeature(ID3D11DeviceConte
Config::Instance()->changeBackend = true;
}
InDevCtx->End(ImGuiOverlayDx::endQueries[nextFrameIndex]);
InDevCtx->End(ImGuiOverlayDx::disjointQueries[nextFrameIndex]);
InDevCtx->End(MenuDx::endQueries[nextFrameIndex]);
InDevCtx->End(MenuDx::disjointQueries[nextFrameIndex]);
ImGuiOverlayDx::dx11UpscaleTrig[nextFrameIndex] = true;
MenuDx::dx11UpscaleTrig[nextFrameIndex] = true;
return NVSDK_NGX_Result_Success;
}
+4 -17
View File
@@ -50,6 +50,8 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_VULKAN_Init_Ext(unsigned long long InAp
}
}
MenuVulkan::PrepareTimeObjects(InInstance, InPD, InDevice);
return NVSDK_NGX_VULKAN_Init_Ext2(InApplicationId, InApplicationDataPath, InInstance, InPD, InDevice, vkGetInstanceProcAddr, vkGetDeviceProcAddr, InSDKVersion, InFeatureInfo);
}
@@ -156,16 +158,6 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_VULKAN_Init_Ext2(unsigned long long InA
Config::Instance()->Api = NVNGX_VULKAN;
VkQueryPoolCreateInfo queryPoolInfo = {};
queryPoolInfo.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
queryPoolInfo.queryType = VK_QUERY_TYPE_TIMESTAMP;
queryPoolInfo.queryCount = 2; // Start and End timestamps
vkCreateQueryPool(InDevice, &queryPoolInfo, nullptr, &ImGuiOverlayVk::queryPool);
VkPhysicalDeviceProperties deviceProperties;
vkGetPhysicalDeviceProperties(InPD, &deviceProperties);
ImGuiOverlayVk::timeStampPeriod = deviceProperties.limits.timestampPeriod;
return NVSDK_NGX_Result_Success;
}
@@ -957,14 +949,9 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_VULKAN_EvaluateFeature(VkCommandBuffer
Config::Instance()->RenderMenu = true;
// Record the first timestamp (before FSR2)
vkCmdWriteTimestamp(InCmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, ImGuiOverlayVk::queryPool, 0);
MenuVulkan::BeforeUpscale(InCmdBuffer);
auto upscaleResult = deviceContext->Evaluate(InCmdBuffer, InParameters);
// Record the second timestamp (after FSR2)
vkCmdWriteTimestamp(InCmdBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, ImGuiOverlayVk::queryPool, 1);
ImGuiOverlayVk::vkUpscaleTrig = true;
MenuVulkan::AfterUpscale(InCmdBuffer);
return upscaleResult ? NVSDK_NGX_Result_Success : NVSDK_NGX_Result_Fail;
}
-1
View File
@@ -6,7 +6,6 @@
#include "NVNGX_Parameter.h"
#include "xess_d3d12_debug.h"
#include "proxies/XeSS_Proxy.h"
#include "menu/imgui_overlay_dx.h"
typedef struct MotionScale
{
+6 -112
View File
@@ -4,107 +4,27 @@
#include "Logger.h"
#include "resource.h"
#include "WorkingMode.h"
#include "hooks/LoadLibrary.h"
#include "proxies/NVNGX_Proxy.h"
#include "proxies/FfxApi_Proxy.h"
#include "proxies/XeSS_Proxy.h"
void AttachHooks();
void DetachHooks();
HMODULE LoadNvApi();
HMODULE LoadNvgxDlss(std::wstring originalPath);
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;
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
if (loadCount > 1)
if (LoadLibraryHooks::LoadCount() > 1)
{
LOG_INFO("DLL_PROCESS_ATTACH from module: {0:X}, count: {1}", (UINT64)hModule, loadCount);
LOG_INFO("DLL_PROCESS_ATTACH from module: {0:X}, count: {1}", (UINT64)hModule, LoadLibraryHooks::LoadCount());
return TRUE;
}
dllModule = hModule;
processId = GetCurrentProcessId();
DisableThreadLibraryCalls(hModule);
loadCount++;
LoadLibraryHooks::AddLoad();
#ifdef VER_PRE_RELEASE
// Enable file logging for pre builds
@@ -128,34 +48,8 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
// Check if real DLSS available
if (Config::Instance()->DLSSEnabled.value_or(true))
{
spdlog::info("");
NVNGXProxy::InitNVNGX();
if (NVNGXProxy::NVNGXModule() == nullptr)
{
spdlog::info("Can't load nvngx.dll, disabling DLSS");
Config::Instance()->DLSSEnabled = false;
}
else
{
spdlog::info("nvngx.dll loaded, setting DLSS as default upscaler and disabling spoofing options set to auto");
Config::Instance()->DLSSEnabled = true;
if (!Config::Instance()->DxgiSpoofing.has_value())
Config::Instance()->DxgiSpoofing = false;
if (!Config::Instance()->VulkanSpoofing.has_value())
Config::Instance()->VulkanSpoofing = false;
if (!Config::Instance()->VulkanExtensionSpoofing.has_value())
Config::Instance()->VulkanExtensionSpoofing = false;
isNvngxAvailable = true;
}
}
// Init XeSS proxy
if (!XeSSProxy::InitXeSS())
spdlog::warn("Can't init XeSS!");
@@ -172,7 +66,7 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
spdlog::info("");
if (WorkingMode::Check())
AttachHooks();
LoadLibraryHooks::Hook();
spdlog::info("");
@@ -187,7 +81,7 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
case DLL_PROCESS_DETACH:
// Unhooking and cleaning stuff causing issues during shutdown.
// Disabled for now to check if it cause any issues
//DetachHooks();
//LoadLibraryHooks::Unhook();
if (skHandle != nullptr)
FreeLibrary(skHandle);
+59 -48
View File
@@ -7,16 +7,15 @@
#include <DbgHelp.h>
#include <include/detours/detours.h>
typedef HRESULT(*PFN_GetDesc)(IDXGIAdapter* This, DXGI_ADAPTER_DESC* pDesc);
typedef HRESULT(*PFN_GetDesc1)(IDXGIAdapter1* This, DXGI_ADAPTER_DESC1* pDesc);
typedef HRESULT(*PFN_GetDesc2)(IDXGIAdapter2* This, DXGI_ADAPTER_DESC2* pDesc);
typedef HRESULT(*PFN_GetDesc3)(IDXGIAdapter4* This, DXGI_ADAPTER_DESC3* pDesc);
typedef HRESULT(WINAPI* PFN_GetDesc)(IDXGIAdapter* This, DXGI_ADAPTER_DESC* pDesc);
typedef HRESULT(WINAPI* PFN_GetDesc1)(IDXGIAdapter1* This, DXGI_ADAPTER_DESC1* pDesc);
typedef HRESULT(WINAPI* PFN_GetDesc2)(IDXGIAdapter2* This, DXGI_ADAPTER_DESC2* pDesc);
typedef HRESULT(WINAPI* PFN_GetDesc3)(IDXGIAdapter4* This, DXGI_ADAPTER_DESC3* pDesc);
typedef HRESULT(WINAPI* PFN_EnumAdapterByGpuPreference)(IDXGIFactory6* This, UINT Adapter, DXGI_GPU_PREFERENCE GpuPreference, REFIID riid, void** ppvAdapter);
typedef HRESULT(WINAPI* PFN_EnumAdapterByLuid)(IDXGIFactory4* This, LUID AdapterLuid, REFIID riid, void** ppvAdapter);
typedef HRESULT(WINAPI* PFN_EnumAdapters1)(IDXGIFactory1* This, UINT Adapter, IDXGIAdapter1** ppAdapter);
typedef HRESULT(WINAPI* PFN_EnumAdapters)(IDXGIFactory* This, UINT Adapter, IDXGIAdapter** ppAdapter);
typedef HRESULT(*PFN_EnumAdapterByGpuPreference)(IDXGIFactory6* This, UINT Adapter, DXGI_GPU_PREFERENCE GpuPreference, REFIID riid, IDXGIAdapter** ppvAdapter);
typedef HRESULT(*PFN_EnumAdapterByLuid)(IDXGIFactory4* This, LUID AdapterLuid, REFIID riid, IDXGIAdapter** ppvAdapter);
typedef HRESULT(*PFN_EnumAdapters1)(IDXGIFactory1* This, UINT Adapter, IDXGIAdapter1** ppAdapter);
typedef HRESULT(*PFN_EnumAdapters)(IDXGIFactory* This, UINT Adapter, IDXGIAdapter** ppAdapter);
static PFN_GetDesc o_GetDesc = nullptr;
static PFN_GetDesc1 o_GetDesc1 = nullptr;
@@ -33,9 +32,35 @@ void AttachToFactory(IUnknown* unkFactory);
#pragma region DXGI Adapter methods
static void CheckAdapter(IUnknown* unkAdapter)
{
if (Config::Instance()->IsRunningOnDXVK)
return;
//DXVK VkInterface GUID
const GUID guid = { 0x907bf281,0xea3c,0x43b4,{0xa8,0xe4,0x9f,0x23,0x11,0x07,0xb4,0xff} };
IDXGIAdapter* adapter = nullptr;
bool adapterOk = unkAdapter->QueryInterface(IID_PPV_ARGS(&adapter)) == S_OK;
void* dxvkAdapter = nullptr;
if (adapterOk && adapter->QueryInterface(guid, &dxvkAdapter) == S_OK)
{
Config::Instance()->IsRunningOnDXVK = dxvkAdapter != nullptr;
((IDXGIAdapter*)dxvkAdapter)->Release();
}
if (adapterOk)
adapter->Release();
if (Config::Instance()->IsRunningOnDXVK)
LOG_INFO("DXVK adapter detected");
}
bool SkipSpoofing()
{
auto skip = !Config::Instance()->DxgiSpoofing.value_or(true) || Config::Instance()->dxgiSkipSpoofing || Config::Instance()->IsRunningOnLinux;
auto skip = !Config::Instance()->DxgiSpoofing.value_or(true) || Config::Instance()->dxgiSkipSpoofing;
if (skip)
LOG_TRACE("DxgiSpoofing: {}, dxgiSkipSpoofing: {}, skipping spoofing",
@@ -202,33 +227,31 @@ static HRESULT hkGetDesc(IDXGIAdapter* This, DXGI_ADAPTER_DESC* pDesc)
#pragma region DXGI Factory methods
static HRESULT WINAPI hkEnumAdapterByGpuPreference(IDXGIFactory6* This, UINT Adapter, DXGI_GPU_PREFERENCE GpuPreference, REFIID riid, void** ppvAdapter)
static HRESULT WINAPI hkEnumAdapterByGpuPreference(IDXGIFactory6* This, UINT Adapter, DXGI_GPU_PREFERENCE GpuPreference, REFIID riid, IDXGIAdapter** ppvAdapter)
{
AttachToFactory(This);
IDXGIAdapter* adapter = nullptr;
auto result = o_EnumAdapterByGpuPreference(This, Adapter, GpuPreference, riid, (void**)&adapter);
auto result = o_EnumAdapterByGpuPreference(This, Adapter, GpuPreference, riid, ppvAdapter);
if (result == S_OK)
{
AttachToAdapter(adapter);
*ppvAdapter = adapter;
CheckAdapter(*ppvAdapter);
AttachToAdapter(*ppvAdapter);
}
return result;
}
static HRESULT WINAPI hkEnumAdapterByLuid(IDXGIFactory4* This, LUID AdapterLuid, REFIID riid, void** ppvAdapter)
static HRESULT WINAPI hkEnumAdapterByLuid(IDXGIFactory4* This, LUID AdapterLuid, REFIID riid, IDXGIAdapter** ppvAdapter)
{
AttachToFactory(This);
IDXGIAdapter* adapter = nullptr;
auto result = o_EnumAdapterByLuid(This, AdapterLuid, riid, (void**)&adapter);
auto result = o_EnumAdapterByLuid(This, AdapterLuid, riid, ppvAdapter);
if (result == S_OK)
{
AttachToAdapter(adapter);
*ppvAdapter = adapter;
CheckAdapter(*ppvAdapter);
AttachToAdapter(*ppvAdapter);
}
return result;
@@ -238,13 +261,12 @@ static HRESULT WINAPI hkEnumAdapters1(IDXGIFactory1* This, UINT Adapter, IDXGIAd
{
AttachToFactory(This);
IDXGIAdapter1* adapter = nullptr;
auto result = o_EnumAdapters1(This, Adapter, &adapter);
auto result = o_EnumAdapters1(This, Adapter, ppAdapter);
if (result == S_OK)
{
AttachToAdapter(adapter);
*ppAdapter = adapter;
CheckAdapter(*ppAdapter);
AttachToAdapter(*ppAdapter);
}
return result;
@@ -254,13 +276,12 @@ static HRESULT WINAPI hkEnumAdapters(IDXGIFactory* This, UINT Adapter, IDXGIAdap
{
AttachToFactory(This);
IDXGIAdapter* adapter = nullptr;
auto result = o_EnumAdapters(This, Adapter, &adapter);
auto result = o_EnumAdapters(This, Adapter, ppAdapter);
if (result == S_OK)
{
AttachToAdapter(adapter);
*ppAdapter = adapter;
CheckAdapter(*ppAdapter);
AttachToAdapter(*ppAdapter);
}
return result;
@@ -358,7 +379,7 @@ static void AttachToFactory(IUnknown* unkFactory)
DetourTransactionCommit();
}
factory->Release();
IDXGIFactory1* factory1;
@@ -411,41 +432,32 @@ static void AttachToFactory(IUnknown* unkFactory)
#pragma region DXGI methods
HRESULT _CreateDXGIFactory(REFIID riid, _COM_Outptr_ void** ppFactory)
HRESULT _CreateDXGIFactory(REFIID riid, _COM_Outptr_ IDXGIFactory** ppFactory)
{
IDXGIFactory* factory;
HRESULT result = dxgi.CreateDxgiFactory(riid, (void**)&factory);
HRESULT result = dxgi.CreateDxgiFactory(riid, ppFactory);
if (result == S_OK)
AttachToFactory(factory);
*ppFactory = factory;
AttachToFactory(*ppFactory);
return result;
}
HRESULT _CreateDXGIFactory1(REFIID riid, _COM_Outptr_ void** ppFactory)
HRESULT _CreateDXGIFactory1(REFIID riid, _COM_Outptr_ IDXGIFactory1** ppFactory)
{
IDXGIFactory1* factory1;
HRESULT result = dxgi.CreateDxgiFactory1(riid, (void**)&factory1);
HRESULT result = dxgi.CreateDxgiFactory1(riid, ppFactory);
if (result == S_OK)
AttachToFactory(factory1);
*ppFactory = factory1;
AttachToFactory(*ppFactory);
return result;
}
HRESULT _CreateDXGIFactory2(UINT Flags, REFIID riid, _COM_Outptr_ void** ppFactory)
HRESULT _CreateDXGIFactory2(UINT Flags, REFIID riid, _COM_Outptr_ IDXGIFactory2** ppFactory)
{
IDXGIFactory* factory;
HRESULT result = dxgi.CreateDxgiFactory2(Flags, riid, (void**)&factory);
HRESULT result = dxgi.CreateDxgiFactory2(Flags, riid, ppFactory);
if (result == S_OK)
AttachToFactory(factory);
*ppFactory = factory;
AttachToFactory(*ppFactory);
return result;
}
@@ -552,6 +564,5 @@ void _UpdateHMDEmulationStatus()
dxgi.UpdateHMDEmulationStatus();
}
#pragma endregion
+8 -7
View File
@@ -4,15 +4,16 @@
#include <dxgi1_6.h>
typedef HRESULT(WINAPI* PFN_CREATE_DXGI_FACTORY)(REFIID riid, _COM_Outptr_ void** ppFactory);
typedef HRESULT(WINAPI* PFN_CREATE_DXGI_FACTORY_2)(UINT Flags, REFIID riid, _COM_Outptr_ void** ppFactory);
typedef HRESULT(*PFN_CREATE_DXGI_FACTORY)(REFIID riid, IDXGIFactory** ppFactory);
typedef HRESULT(*PFN_CREATE_DXGI_FACTORY_1)(REFIID riid, IDXGIFactory1** ppFactory);
typedef HRESULT(*PFN_CREATE_DXGI_FACTORY_2)(UINT Flags, REFIID riid, IDXGIFactory2** ppFactory);
inline struct dxgi_dll
{
HMODULE dll = nullptr;
PFN_CREATE_DXGI_FACTORY CreateDxgiFactory;
PFN_CREATE_DXGI_FACTORY CreateDxgiFactory1;
PFN_CREATE_DXGI_FACTORY_1 CreateDxgiFactory1;
PFN_CREATE_DXGI_FACTORY_2 CreateDxgiFactory2;
FARPROC DeclareAdapterRemovalSupport;
@@ -38,7 +39,7 @@ inline struct dxgi_dll
dll = module;
CreateDxgiFactory = (PFN_CREATE_DXGI_FACTORY)GetProcAddress(module, "CreateDXGIFactory");
CreateDxgiFactory1 = (PFN_CREATE_DXGI_FACTORY)GetProcAddress(module, "CreateDXGIFactory1");
CreateDxgiFactory1 = (PFN_CREATE_DXGI_FACTORY_1)GetProcAddress(module, "CreateDXGIFactory1");
CreateDxgiFactory2 = (PFN_CREATE_DXGI_FACTORY_2)GetProcAddress(module, "CreateDXGIFactory2");
DeclareAdapterRemovalSupport = GetProcAddress(module, "DXGIDeclareAdapterRemovalSupport");
@@ -61,9 +62,9 @@ inline struct dxgi_dll
}
} dxgi;
HRESULT _CreateDXGIFactory(REFIID riid, _COM_Outptr_ void** ppFactory);
HRESULT _CreateDXGIFactory1(REFIID riid, _COM_Outptr_ void** ppFactory);
HRESULT _CreateDXGIFactory2(UINT Flags, REFIID riid, _COM_Outptr_ void** ppFactory);
HRESULT _CreateDXGIFactory(REFIID riid, IDXGIFactory** ppFactory);
HRESULT _CreateDXGIFactory1(REFIID riid, IDXGIFactory1** ppFactory);
HRESULT _CreateDXGIFactory2(UINT Flags, REFIID riid, IDXGIFactory2** ppFactory);
void _DXGIDeclareAdapterRemovalSupport();
void _DXGIGetDebugInterface1();
+532
View File
@@ -0,0 +1,532 @@
#include "Dxgi.h"
#include <Util.h>
#include <Config.h>
#include <WorkingMode.h>
#include <exports/Dxgi.h>
#include <objects/WrappedSwapChain.h>
#include <d3d12.h>
#include <d3d11_4.h>
#include <include/detours/detours.h>
typedef HRESULT(*PFN_CreateSwapChain)(IDXGIFactory*, IUnknown*, DXGI_SWAP_CHAIN_DESC*, IDXGISwapChain**);
typedef HRESULT(*PFN_CreateSwapChainForHwnd)(IDXGIFactory*, IUnknown*, HWND, const DXGI_SWAP_CHAIN_DESC1*, const DXGI_SWAP_CHAIN_FULLSCREEN_DESC*, IDXGIOutput*, IDXGISwapChain1**);
static PFN_CreateSwapChain o_CreateSwapChain = nullptr;
static PFN_CreateSwapChainForHwnd o_CreateSwapChainForHwnd = nullptr;
static bool dx11Device = false;
static bool dx12Device = false;
static void CleanupRenderTarget(bool clearQueue, HWND hWnd)
{
LOG_FUNC();
if (clearQueue)
currentSCCommandQueue = nullptr;
if (dx11Device)
CleanupRenderTargetDx11(false);
else
CleanupRenderTargetDx12(clearQueue);
// Releasing RTSS D3D11on12 device
if (clearQueue && GetModuleHandle(L"RTSSHooks64.dll") != nullptr)
{
LOG_DEBUG("Releasing D3d11on12 device");
d3d11on12Device = nullptr;
}
}
static HRESULT Present(IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags, const DXGI_PRESENT_PARAMETERS* pPresentParameters, IUnknown* pDevice, HWND hWnd)
{
LOG_FUNC();
HRESULT presentResult;
if (hWnd != Util::GetProcessWindow())
{
if (pPresentParameters == nullptr)
presentResult = pSwapChain->Present(SyncInterval, Flags);
else
presentResult = ((IDXGISwapChain1*)pSwapChain)->Present1(SyncInterval, Flags, pPresentParameters);
LOG_FUNC_RESULT(presentResult);
return presentResult;
}
ID3D12CommandQueue* cq = nullptr;
ID3D11Device* device = nullptr;
ID3D12Device* device12 = nullptr;
// try to obtain directx objects and find the path
if (pDevice->QueryInterface(IID_PPV_ARGS(&device)) == S_OK)
{
if (!dx11Device)
LOG_DEBUG("D3D11Device captured");
dx11Device = true;
}
else if (pDevice->QueryInterface(IID_PPV_ARGS(&cq)) == S_OK)
{
if (!dx12Device)
LOG_DEBUG("D3D12CommandQueue captured");
currentSCCommandQueue = pDevice;
MenuDx::GameCommandQueue = (ID3D12CommandQueue*)pDevice;
if (cq->GetDevice(IID_PPV_ARGS(&device12)) == S_OK)
{
if (!dx12Device)
LOG_DEBUG("D3D12Device captured");
dx12Device = true;
}
}
// Upscaler GPU time computation
if (MenuDx::dx12UpscaleTrig && MenuDx::readbackBuffer != nullptr && MenuDx::queryHeap != nullptr && cq != nullptr)
{
if (MenuBase::IsInited() && MenuBase::IsVisible())
{
UINT64* timestampData;
MenuDx::readbackBuffer->Map(0, nullptr, reinterpret_cast<void**>(&timestampData));
// Get the GPU timestamp frequency (ticks per second)
UINT64 gpuFrequency;
cq->GetTimestampFrequency(&gpuFrequency);
// Calculate elapsed time in milliseconds
UINT64 startTime = timestampData[0];
UINT64 endTime = timestampData[1];
double elapsedTimeMs = (endTime - startTime) / static_cast<double>(gpuFrequency) * 1000.0;
Config::Instance()->upscaleTimes.push_back(elapsedTimeMs);
Config::Instance()->upscaleTimes.pop_front();
// Unmap the buffer
MenuDx::readbackBuffer->Unmap(0, nullptr);
}
MenuDx::dx12UpscaleTrig = false;
}
else if (MenuDx::dx11UpscaleTrig[MenuDx::currentFrameIndex] && device != nullptr && MenuDx::disjointQueries[0] != nullptr &&
MenuDx::startQueries[0] != nullptr && MenuDx::endQueries[0] != nullptr)
{
if (g_pd3dDeviceContext == nullptr)
device->GetImmediateContext(&g_pd3dDeviceContext);
if (MenuBase::IsInited() && MenuBase::IsVisible())
{
// Retrieve the results from the previous frame
D3D11_QUERY_DATA_TIMESTAMP_DISJOINT disjointData;
if (g_pd3dDeviceContext->GetData(MenuDx::disjointQueries[MenuDx::previousFrameIndex], &disjointData, sizeof(disjointData), 0) == S_OK)
{
if (!disjointData.Disjoint && disjointData.Frequency > 0)
{
UINT64 startTime = 0, endTime = 0;
if (g_pd3dDeviceContext->GetData(MenuDx::startQueries[MenuDx::previousFrameIndex], &startTime, sizeof(UINT64), 0) == S_OK &&
g_pd3dDeviceContext->GetData(MenuDx::endQueries[MenuDx::previousFrameIndex], &endTime, sizeof(UINT64), 0) == S_OK)
{
double elapsedTimeMs = (endTime - startTime) / static_cast<double>(disjointData.Frequency) * 1000.0;
Config::Instance()->upscaleTimes.push_back(elapsedTimeMs);
Config::Instance()->upscaleTimes.pop_front();
}
}
}
}
MenuDx::dx11UpscaleTrig[MenuDx::currentFrameIndex] = false;
MenuDx::currentFrameIndex = (MenuDx::currentFrameIndex + 1) % MenuDx::QUERY_BUFFER_COUNT;
}
// DXVK check, it's here because of upscaler time calculations
if (Config::Instance()->IsRunningOnDXVK)
{
if (cq != nullptr)
cq->Release();
if (device != nullptr)
device->Release();
if (device12 != nullptr)
device12->Release();
if (pPresentParameters == nullptr)
presentResult = pSwapChain->Present(SyncInterval, Flags);
else
presentResult = ((IDXGISwapChain1*)pSwapChain)->Present1(SyncInterval, Flags, pPresentParameters);
LOG_FUNC_RESULT(presentResult);
return presentResult;
}
// Process window handle changed, update base
if (MenuBase::Handle() != hWnd)
{
LOG_DEBUG("Handle changed");
if (MenuBase::IsInited())
MenuBase::Shutdown();
MenuBase::Init(hWnd);
_isInited = false;
}
// Init
if (!_isInited)
{
if (dx11Device)
{
CleanupRenderTargetDx11(false);
g_pd3dDevice = device;
g_pd3dDevice->AddRef();
CreateRenderTargetDx11(pSwapChain);
MenuBase::Dx11Ready();
_isInited = true;
}
else if (dx12Device && (g_pd3dDeviceParam != nullptr || device12 != nullptr))
{
if (g_pd3dDeviceParam != nullptr && device12 == nullptr)
device12 = g_pd3dDeviceParam;
CleanupRenderTargetDx12(true);
g_pd3dCommandQueue = cq;
g_pd3dDeviceParam = device12;
g_pd3dCommandQueue->AddRef();
g_pd3dDeviceParam->AddRef();
MenuBase::Dx12Ready();
_isInited = true;
}
}
// dx11 multi thread safety
ID3D11Multithread* dx11MultiThread = nullptr;
ID3D11DeviceContext* dx11Context = nullptr;
bool mtState = false;
if (dx11Device)
{
ID3D11Device* dx11Device = g_pd3dDevice;
if (dx11Device == nullptr)
dx11Device = d3d11Device;
if (dx11Device == nullptr)
dx11Device = d3d11on12Device;
if (dx11Device != nullptr)
{
dx11Device->GetImmediateContext(&dx11Context);
if (dx11Context != nullptr && dx11Context->QueryInterface(IID_PPV_ARGS(&dx11MultiThread)) == S_OK && dx11MultiThread != nullptr)
{
mtState = dx11MultiThread->GetMultithreadProtected();
dx11MultiThread->SetMultithreadProtected(TRUE);
dx11MultiThread->Enter();
}
}
}
// Render menu
if (dx11Device)
RenderImGui_DX11(pSwapChain);
else if (dx12Device)
RenderImGui_DX12(pSwapChain);
// swapchain present
if (pPresentParameters == nullptr)
presentResult = pSwapChain->Present(SyncInterval, Flags);
else
presentResult = ((IDXGISwapChain1*)pSwapChain)->Present1(SyncInterval, Flags, pPresentParameters);
// dx11 multi thread safety
if (dx11Device && dx11MultiThread != nullptr)
{
dx11MultiThread->Leave();
dx11MultiThread->SetMultithreadProtected(mtState);
dx11MultiThread->Release();
dx11Context->Release();
}
// release used objects
if (cq != nullptr)
cq->Release();
if (device != nullptr)
device->Release();
if (device12 != nullptr)
device12->Release();
return presentResult;
}
static HRESULT hkCreateSwapChain(IDXGIFactory* pFactory, IUnknown* pDevice, DXGI_SWAP_CHAIN_DESC* pDesc, IDXGISwapChain** ppSwapChain)
{
LOG_FUNC();
*ppSwapChain = nullptr;
if (Config::Instance()->VulkanCreatingSC)
{
LOG_WARN("Vulkan is creating swapchain!");
if (pDesc != nullptr)
LOG_DEBUG("Width: {0}, Height: {1}, Format: {2:X}, Count: {3}, Windowed: {4}", pDesc->BufferDesc.Width, pDesc->BufferDesc.Height, (UINT)pDesc->BufferDesc.Format, pDesc->BufferCount, pDesc->Windowed);
return o_CreateSwapChain(pFactory, pDevice, pDesc, ppSwapChain);
}
if (pDevice == nullptr)
{
LOG_WARN("pDevice is nullptr!");
return o_CreateSwapChain(pFactory, pDevice, pDesc, ppSwapChain);
}
auto result = o_CreateSwapChain(pFactory, pDevice, pDesc, ppSwapChain);
if (result == S_OK)
{
LOG_DEBUG("Width: {0}, Height: {1}, Format: {2:X}, Count: {3}, Windowed: {4}", pDesc->BufferDesc.Width, pDesc->BufferDesc.Height, (UINT)pDesc->BufferDesc.Format, pDesc->BufferCount, pDesc->Windowed);
if (Util::GetProcessWindow() == pDesc->OutputWindow)
{
Config::Instance()->ScreenWidth = pDesc->BufferDesc.Width;
Config::Instance()->ScreenHeight = pDesc->BufferDesc.Height;
}
if (Config::Instance()->OverlayMenu.value_or(true))
{
LOG_DEBUG("created new swapchain: {0:X}, hWnd: {1:X}", (UINT64)*ppSwapChain, (UINT64)pDesc->OutputWindow);
*ppSwapChain = new WrappedSwapChain(*ppSwapChain, pDevice, pDesc->OutputWindow, Present, CleanupRenderTarget);
LOG_DEBUG("created new WrappedSwapChain: {0:X}, pDevice: {1:X}", (UINT64)*ppSwapChain, (UINT64)pDevice);
}
}
return result;
}
static HRESULT hkCreateSwapChainForHwnd(IDXGIFactory* pCommandQueue, IUnknown* pDevice, HWND hWnd, const DXGI_SWAP_CHAIN_DESC1* pDesc,
const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc, IDXGIOutput* pRestrictToOutput, IDXGISwapChain1** ppSwapChain)
{
LOG_FUNC();
*ppSwapChain = nullptr;
if (Config::Instance()->VulkanCreatingSC)
{
LOG_WARN("Vulkan is creating swapchain!");
if (pDesc != nullptr)
LOG_DEBUG("Width: {0}, Height: {1}, Format: {2:X}, Count: {3}, Flags: {4:X}", pDesc->Width, pDesc->Height, (UINT)pDesc->Format, pDesc->BufferCount, pDesc->Flags);
return o_CreateSwapChainForHwnd(pCommandQueue, pDevice, hWnd, pDesc, pFullscreenDesc, pRestrictToOutput, ppSwapChain);
}
if (pDevice == nullptr)
{
LOG_WARN("pDevice is nullptr!");
return o_CreateSwapChainForHwnd(pCommandQueue, pDevice, hWnd, pDesc, pFullscreenDesc, pRestrictToOutput, ppSwapChain);
}
auto result = o_CreateSwapChainForHwnd(pCommandQueue, pDevice, hWnd, pDesc, pFullscreenDesc, pRestrictToOutput, ppSwapChain);
if (result == S_OK)
{
LOG_DEBUG("Width: {0}, Height: {1}, Format: {2:X}, Count: {3}, Flags: {4:X}", pDesc->Width, pDesc->Height, (UINT)pDesc->Format, pDesc->BufferCount, pDesc->Flags);
if (Util::GetProcessWindow() == hWnd)
{
Config::Instance()->ScreenWidth = pDesc->Width;
Config::Instance()->ScreenHeight = pDesc->Height;
}
if (Config::Instance()->OverlayMenu.value_or(true))
{
LOG_DEBUG("created new swapchain: {0:X}, hWnd: {1:X}", (UINT64)*ppSwapChain, (UINT64)hWnd);
*ppSwapChain = new WrappedSwapChain(*ppSwapChain, pDevice, hWnd, Present, CleanupRenderTarget);
LOG_DEBUG("created new WrappedSwapChain: {0:X}, pDevice: {1:X}", (UINT64)*ppSwapChain, (UINT64)pDevice);
}
}
return result;
}
static HRESULT hkCreateDXGIFactory(REFIID riid, IDXGIFactory** ppFactory)
{
HRESULT result;
if (Config::Instance()->DxgiSpoofing.value_or(true))
result = _CreateDXGIFactory(riid, ppFactory);
else
result = dxgi.CreateDxgiFactory(riid, ppFactory);
if (result == S_OK && o_CreateSwapChain == nullptr)
{
void** pFactoryVTable = *reinterpret_cast<void***>(*ppFactory);
o_CreateSwapChain = (PFN_CreateSwapChain)pFactoryVTable[10];
if (o_CreateSwapChain != nullptr)
{
LOG_INFO("Hooking native DXGIFactory");
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)o_CreateSwapChain, hkCreateSwapChain);
DetourTransactionCommit();
}
}
return result;
}
static HRESULT hkCreateDXGIFactory1(REFIID riid, IDXGIFactory1** ppFactory)
{
HRESULT result;
if (Config::Instance()->DxgiSpoofing.value_or(true))
result = _CreateDXGIFactory1(riid, ppFactory);
else
result = dxgi.CreateDxgiFactory1(riid, ppFactory);
if (result == S_OK && o_CreateSwapChainForHwnd == nullptr)
{
IDXGIFactory2* factory2 = nullptr;
if ((*ppFactory)->QueryInterface(IID_PPV_ARGS(&factory2)) == S_OK && factory2 != nullptr)
{
void** pFactoryVTable = *reinterpret_cast<void***>(factory2);
bool skip = false;
if (o_CreateSwapChain == nullptr)
o_CreateSwapChain = (PFN_CreateSwapChain)pFactoryVTable[10];
else
skip = true;
o_CreateSwapChainForHwnd = (PFN_CreateSwapChainForHwnd)pFactoryVTable[15];
if (o_CreateSwapChainForHwnd != nullptr)
{
LOG_INFO("Hooking native DXGIFactory");
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
if (!skip)
DetourAttach(&(PVOID&)o_CreateSwapChain, hkCreateSwapChain);
DetourAttach(&(PVOID&)o_CreateSwapChainForHwnd, hkCreateSwapChainForHwnd);
DetourTransactionCommit();
}
factory2->Release();
factory2 = nullptr;
}
}
return result;
}
static HRESULT hkCreateDXGIFactory2(UINT Flags, REFIID riid, IDXGIFactory2** ppFactory)
{
HRESULT result;
if (Config::Instance()->DxgiSpoofing.value_or(true))
result = _CreateDXGIFactory2(Flags, riid, ppFactory);
else
result = dxgi.CreateDxgiFactory2(Flags, riid, ppFactory);
if (result == S_OK && o_CreateSwapChainForHwnd == nullptr)
{
IDXGIFactory2* factory2 = nullptr;
if ((*ppFactory)->QueryInterface(IID_PPV_ARGS(&factory2)) == S_OK && factory2 != nullptr)
{
void** pFactoryVTable = *reinterpret_cast<void***>(factory2);
bool skip = false;
if (o_CreateSwapChain == nullptr)
o_CreateSwapChain = (PFN_CreateSwapChain)pFactoryVTable[10];
else
skip = true;
o_CreateSwapChainForHwnd = (PFN_CreateSwapChainForHwnd)pFactoryVTable[15];
if (o_CreateSwapChainForHwnd != nullptr)
{
LOG_INFO("Hooking native DXGIFactory");
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
if (!skip)
DetourAttach(&(PVOID&)o_CreateSwapChain, hkCreateSwapChain);
DetourAttach(&(PVOID&)o_CreateSwapChainForHwnd, hkCreateSwapChainForHwnd);
DetourTransactionCommit();
}
factory2->Release();
factory2 = nullptr;
}
}
return result;
}
inline static void HookForDxgiSpoofing()
{
// hook dxgi when not working as dxgi.dll
if (dxgi.CreateDxgiFactory == nullptr && !WorkingMode::IsWorkingWithEnabler() && !Config::Instance()->IsDxgiMode)
{
LOG_INFO("DxgiSpoofing is enabled loading dxgi.dll");
dxgi.CreateDxgiFactory = (PFN_CREATE_DXGI_FACTORY)DetourFindFunction("dxgi.dll", "CreateDXGIFactory");
dxgi.CreateDxgiFactory1 = (PFN_CREATE_DXGI_FACTORY_1)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, hkCreateDXGIFactory);
if (dxgi.CreateDxgiFactory1 != nullptr)
DetourAttach(&(PVOID&)dxgi.CreateDxgiFactory1, hkCreateDXGIFactory1);
if (dxgi.CreateDxgiFactory2 != nullptr)
DetourAttach(&(PVOID&)dxgi.CreateDxgiFactory2, hkCreateDXGIFactory2);
DetourTransactionCommit();
}
}
}
void DxgiHooks::Hook()
{
HookForDxgiSpoofing();
}
void DxgiHooks::Unhook()
{
}
+10
View File
@@ -0,0 +1,10 @@
#pragma once
#include <pch.h>
class DxgiHooks
{
private:
public:
static void Hook();
static void Unhook();
};
-6
View File
@@ -1,6 +0,0 @@
#include "Hooks.h"
void Hooks::Attach()
{
}
-8
View File
@@ -1,8 +0,0 @@
#pragma once
#include <pch.h>
class Hooks
{
public:
void Attach();
};
+78 -90
View File
@@ -1,5 +1,6 @@
#include "LoadLibrary.h"
#include "Dxgi.h"
#include <Util.h>
#include <Config.h>
#include "Vulkan.h"
@@ -41,6 +42,80 @@ static bool dontCount = false;
static bool skipLoadChecks = false;
static UINT loadCount = 0;
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;
}
inline static bool CheckDllName(std::string* dllName, std::vector<std::string>* namesList)
{
for (size_t i = 0; i < namesList->size(); i++)
@@ -145,12 +220,7 @@ inline static HMODULE LoadLibraryCheck(std::string lcaseLibName)
HooksDx::HookDx12();
if (CheckDllName(&lcaseLibName, &dxgiNames))
{
HookForDxgiSpoofing();
if (Config::Instance()->OverlayMenu.value_or(true))
HooksDx::HookDxgi();
}
DxgiHooks::Hook();
if (CheckDllName(&lcaseLibName, &vkNames))
{
@@ -250,12 +320,7 @@ inline static HMODULE LoadLibraryCheckW(std::wstring lcaseLibName)
HooksDx::HookDx12();
if (CheckDllNameW(&lcaseLibName, &dxgiNamesW))
{
HookForDxgiSpoofing();
if (Config::Instance()->OverlayMenu.value_or(true))
HooksDx::HookDxgi();
}
DxgiHooks::Hook();
if (CheckDllNameW(&lcaseLibName, &vkNamesW))
{
@@ -279,80 +344,6 @@ inline static HMODULE LoadLibraryCheckW(std::wstring lcaseLibName)
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)
@@ -557,7 +548,7 @@ void LoadLibraryHooks::Hook()
if (dxgiModule != nullptr)
{
LOG_DEBUG("dxgi.dll already in memory");
HookForDxgiSpoofing();
DxgiHooks::Hook();
}
HMODULE vulkanModule = nullptr;
@@ -593,9 +584,6 @@ void LoadLibraryHooks::Hook()
LOG_DEBUG("d3d12.dll already in memory");
HooksDx::HookDx12();
}
if (Config::Instance()->OverlayMenu.value() && dxgiModule != nullptr)
HooksDx::HookDxgi();
}
void LoadLibraryHooks::Unhook()
File diff suppressed because it is too large Load Diff
+25
View File
@@ -0,0 +1,25 @@
#pragma once
#include <pch.h>
#include <d3d12.h>
#include <d3d11_4.h>
class MenuDx11
{
private:
inline static const int QUERY_BUFFER_COUNT = 3;
inline static ID3D11Query* disjointQueries[QUERY_BUFFER_COUNT] = { nullptr, nullptr, nullptr };
inline static ID3D11Query* startQueries[QUERY_BUFFER_COUNT] = { nullptr, nullptr, nullptr };
inline static ID3D11Query* endQueries[QUERY_BUFFER_COUNT] = { nullptr, nullptr, nullptr };
inline static bool dx11UpscaleTrig[QUERY_BUFFER_COUNT] = { false, false, false };
inline static int currentFrameIndex = 0;
inline static int previousFrameIndex = 0;
public:
static void PrepareTimeObjects(VkInstance InInstance, VkPhysicalDevice InPD, VkDevice InDevice);
static void BeforeUpscale(VkCommandBuffer InCmdBuffer);
static void AfterUpscale(VkCommandBuffer InCmdBuffer);
};
@@ -3,7 +3,6 @@
#include <Util.h>
#include <Logger.h>
#include <Config.h>
#include "wrapped_swapchain.h"
#include "MenuBase.h"
#include <dxgi1_6.h>
@@ -16,12 +15,12 @@
// dxgi stuff
typedef HRESULT(*PFN_CreateDXGIFactory)(REFIID riid, IDXGIFactory** ppFactory);
typedef HRESULT(*PFN_CreateDXGIFactory1)(REFIID riid, IDXGIFactory1** ppFactory);
typedef HRESULT(*PFN_CreateDXGIFactory2)(UINT Flags, REFIID riid, _COM_Outptr_ IDXGIFactory2** ppFactory);
typedef HRESULT(*PFN_CreateDXGIFactory2)(UINT Flags, REFIID riid, IDXGIFactory2** ppFactory);
typedef HRESULT(WINAPI* PFN_EnumAdapterByGpuPreference2)(IDXGIFactory6* This, UINT Adapter, DXGI_GPU_PREFERENCE GpuPreference, REFIID riid, IUnknown** ppvAdapter);
typedef HRESULT(WINAPI* PFN_EnumAdapterByLuid2)(IDXGIFactory4* This, LUID AdapterLuid, REFIID riid, IUnknown** ppvAdapter);
typedef HRESULT(WINAPI* PFN_EnumAdapters12)(IDXGIFactory1* This, UINT Adapter, IUnknown** ppAdapter);
typedef HRESULT(WINAPI* PFN_EnumAdapters2)(IDXGIFactory* This, UINT Adapter, IUnknown** ppAdapter);
typedef HRESULT(*PFN_EnumAdapterByGpuPreference2)(IDXGIFactory6* This, UINT Adapter, DXGI_GPU_PREFERENCE GpuPreference, REFIID riid, IUnknown** ppvAdapter);
typedef HRESULT(*PFN_EnumAdapterByLuid2)(IDXGIFactory4* This, LUID AdapterLuid, REFIID riid, IUnknown** ppvAdapter);
typedef HRESULT(*PFN_EnumAdapters12)(IDXGIFactory1* This, UINT Adapter, IUnknown** ppAdapter);
typedef HRESULT(*PFN_EnumAdapters2)(IDXGIFactory* This, UINT Adapter, IUnknown** ppAdapter);
static PFN_CreateDXGIFactory o_CreateDXGIFactory = nullptr;
static PFN_CreateDXGIFactory1 o_CreateDXGIFactory1 = nullptr;
@@ -31,18 +30,16 @@ inline static PFN_EnumAdapters2 ptrEnumAdapters = nullptr;
inline static PFN_EnumAdapters12 ptrEnumAdapters1 = nullptr;
inline static PFN_EnumAdapterByLuid2 ptrEnumAdapterByLuid = nullptr;
inline static PFN_EnumAdapterByGpuPreference2 ptrEnumAdapterByGpuPreference = nullptr;
inline static PFN_Present o_Present = nullptr;
inline static PFN_Present1 o_Present1 = nullptr;
static PFN_CreateSwapChain oCreateSwapChain = nullptr;
static PFN_CreateSwapChainForHwnd oCreateSwapChainForHwnd = nullptr;
// MipMap hooks
// DirectX
typedef void(*PFN_CreateSampler)(ID3D12Device* device, const D3D12_SAMPLER_DESC* pDesc, D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor);
typedef HRESULT(*PFN_CreateSamplerState)(ID3D11Device* This, const D3D11_SAMPLER_DESC* pSamplerDesc, ID3D11SamplerState** ppSamplerState);
// MipMap hooks
static PFN_D3D12_CREATE_DEVICE o_D3D12CreateDevice = nullptr;
static PFN_CreateSampler o_CreateSampler = nullptr;
@@ -86,7 +83,6 @@ static bool _showRenderImGuiDebugOnce = true;
static std::mutex _dx11CleanMutex;
static std::mutex _dx12CleanMutex;
static void RenderImGui_DX11(IDXGISwapChain* pSwapChain);
static void RenderImGui_DX12(IDXGISwapChain* pSwapChain);
static void DeatachAllHooks();
@@ -608,294 +604,7 @@ static void AttachToFactory(IUnknown* unkFactory)
}
}
static HRESULT hkCreateSwapChain(IDXGIFactory* pFactory, IUnknown* pDevice, DXGI_SWAP_CHAIN_DESC* pDesc, IDXGISwapChain** ppSwapChain)
{
LOG_FUNC();
*ppSwapChain = nullptr;
if (Config::Instance()->VulkanCreatingSC)
{
LOG_WARN("Vulkan is creating swapchain!");
if(pDesc != nullptr)
LOG_DEBUG("Width: {0}, Height: {1}, Format: {2:X}, Count: {3}, Windowed: {4}", pDesc->BufferDesc.Width, pDesc->BufferDesc.Height, (UINT)pDesc->BufferDesc.Format, pDesc->BufferCount, pDesc->Windowed);
return oCreateSwapChain(pFactory, pDevice, pDesc, ppSwapChain);
}
if (pDevice == nullptr)
{
LOG_WARN("pDevice is nullptr!");
return oCreateSwapChain(pFactory, pDevice, pDesc, ppSwapChain);
}
auto result = oCreateSwapChain(pFactory, pDevice, pDesc, ppSwapChain);
if (result == S_OK)
{
// check for SL proxy
IID riid;
IDXGISwapChain* real = nullptr;
auto iidResult = IIDFromString(L"{ADEC44E2-61F0-45C3-AD9F-1B37379284FF}", &riid);
if (iidResult == S_OK)
{
auto qResult = (*ppSwapChain)->QueryInterface(riid, (void**)&real);
if (qResult == S_OK && real != nullptr)
{
LOG_INFO("Streamline proxy found");
real->Release();
}
else
{
LOG_DEBUG("Streamline proxy not found");
}
}
LOG_DEBUG("Width: {0}, Height: {1}, Format: {2:X}, Count: {3}, Windowed: {4}", pDesc->BufferDesc.Width, pDesc->BufferDesc.Height, (UINT)pDesc->BufferDesc.Format, pDesc->BufferCount, pDesc->Windowed);
if (Util::GetProcessWindow() == pDesc->OutputWindow)
{
Config::Instance()->ScreenWidth = pDesc->BufferDesc.Width;
Config::Instance()->ScreenHeight = pDesc->BufferDesc.Height;
}
LOG_DEBUG("created new swapchain: {0:X}, hWnd: {1:X}", (UINT64)*ppSwapChain, (UINT64)pDesc->OutputWindow);
*ppSwapChain = new WrappedIDXGISwapChain4(real == nullptr ? *ppSwapChain : real, pDevice, pDesc->OutputWindow, Present, CleanupRenderTarget);
LOG_DEBUG("created new WrappedIDXGISwapChain4: {0:X}, pDevice: {1:X}", (UINT64)*ppSwapChain, (UINT64)pDevice);
}
return result;
}
static HRESULT hkCreateSwapChainForHwnd(IDXGIFactory* pCommandQueue, IUnknown* pDevice, HWND hWnd, const DXGI_SWAP_CHAIN_DESC1* pDesc,
const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc, IDXGIOutput* pRestrictToOutput, IDXGISwapChain1** ppSwapChain)
{
LOG_FUNC();
*ppSwapChain = nullptr;
if (Config::Instance()->VulkanCreatingSC)
{
LOG_WARN("Vulkan is creating swapchain!");
if (pDesc != nullptr)
LOG_DEBUG("Width: {0}, Height: {1}, Format: {2:X}, Count: {3}, Flags: {4:X}", pDesc->Width, pDesc->Height, (UINT)pDesc->Format, pDesc->BufferCount, pDesc->Flags);
return oCreateSwapChainForHwnd(pCommandQueue, pDevice, hWnd, pDesc, pFullscreenDesc, pRestrictToOutput, ppSwapChain);
}
if (pDevice == nullptr)
{
LOG_WARN("pDevice is nullptr!");
return oCreateSwapChainForHwnd(pCommandQueue, pDevice, hWnd, pDesc, pFullscreenDesc, pRestrictToOutput, ppSwapChain);
}
auto result = oCreateSwapChainForHwnd(pCommandQueue, pDevice, hWnd, pDesc, pFullscreenDesc, pRestrictToOutput, ppSwapChain);
if (result == S_OK)
{
// check for SL proxy
IID riid;
IDXGISwapChain1* real = nullptr;
auto iidResult = IIDFromString(L"{ADEC44E2-61F0-45C3-AD9F-1B37379284FF}", &riid);
if (iidResult == S_OK)
{
IUnknown* real = nullptr;
auto qResult = (*ppSwapChain)->QueryInterface(riid, (void**)&real);
if (qResult == S_OK && real != nullptr)
{
LOG_INFO("Streamline proxy found");
real->Release();
}
else
{
LOG_DEBUG("Streamline proxy not found");
}
}
LOG_DEBUG("Width: {0}, Height: {1}, Format: {2:X}, Count: {3}, Flags: {4:X}", pDesc->Width, pDesc->Height, (UINT)pDesc->Format, pDesc->BufferCount, pDesc->Flags);
if (Util::GetProcessWindow() == hWnd)
{
Config::Instance()->ScreenWidth = pDesc->Width;
Config::Instance()->ScreenHeight = pDesc->Height;
}
LOG_DEBUG("created new swapchain: {0:X}, hWnd: {1:X}", (UINT64)*ppSwapChain, (UINT64)hWnd);
*ppSwapChain = new WrappedIDXGISwapChain4(real == nullptr ? *ppSwapChain : real, pDevice, hWnd, Present, CleanupRenderTarget);
LOG_DEBUG("created new WrappedIDXGISwapChain4: {0:X}, pDevice: {1:X}", (UINT64)*ppSwapChain, (UINT64)pDevice);
}
return result;
}
static HRESULT hkCreateDXGIFactory(REFIID riid, IDXGIFactory** ppFactory)
{
auto result = o_CreateDXGIFactory(riid, ppFactory);
if (result == S_OK)
AttachToFactory(*ppFactory);
if (result == S_OK && oCreateSwapChain == nullptr)
{
void** pFactoryVTable = *reinterpret_cast<void***>(*ppFactory);
oCreateSwapChain = (PFN_CreateSwapChain)pFactoryVTable[10];
if (oCreateSwapChain != nullptr)
{
LOG_INFO("Hooking native DXGIFactory");
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)oCreateSwapChain, hkCreateSwapChain);
DetourTransactionCommit();
}
}
return result;
}
static HRESULT hkCreateDXGIFactory1(REFIID riid, IDXGIFactory1** ppFactory)
{
auto result = o_CreateDXGIFactory1(riid, ppFactory);
if (result == S_OK)
AttachToFactory(*ppFactory);
if (result == S_OK && oCreateSwapChainForHwnd == nullptr)
{
IDXGIFactory2* factory2 = nullptr;
if ((*ppFactory)->QueryInterface(IID_PPV_ARGS(&factory2)) == S_OK && factory2 != nullptr)
{
void** pFactoryVTable = *reinterpret_cast<void***>(factory2);
bool skip = false;
if (oCreateSwapChain == nullptr)
oCreateSwapChain = (PFN_CreateSwapChain)pFactoryVTable[10];
else
skip = true;
oCreateSwapChainForHwnd = (PFN_CreateSwapChainForHwnd)pFactoryVTable[15];
if (oCreateSwapChainForHwnd != nullptr)
{
LOG_INFO("Hooking native DXGIFactory");
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
if (!skip)
DetourAttach(&(PVOID&)oCreateSwapChain, hkCreateSwapChain);
DetourAttach(&(PVOID&)oCreateSwapChainForHwnd, hkCreateSwapChainForHwnd);
DetourTransactionCommit();
}
factory2->Release();
factory2 = nullptr;
}
}
return result;
}
static HRESULT hkCreateDXGIFactory2(UINT Flags, REFIID riid, IDXGIFactory2** ppFactory)
{
auto result = o_CreateDXGIFactory2(Flags, riid, ppFactory);
if (result == S_OK)
AttachToFactory(*ppFactory);
if (result == S_OK && oCreateSwapChainForHwnd == nullptr)
{
IDXGIFactory2* factory2 = nullptr;
if ((*ppFactory)->QueryInterface(IID_PPV_ARGS(&factory2)) == S_OK && factory2 != nullptr)
{
void** pFactoryVTable = *reinterpret_cast<void***>(factory2);
bool skip = false;
if (oCreateSwapChain == nullptr)
oCreateSwapChain = (PFN_CreateSwapChain)pFactoryVTable[10];
else
skip = true;
oCreateSwapChainForHwnd = (PFN_CreateSwapChainForHwnd)pFactoryVTable[15];
if (oCreateSwapChainForHwnd != nullptr)
{
LOG_INFO("Hooking native DXGIFactory");
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
if (!skip)
DetourAttach(&(PVOID&)oCreateSwapChain, hkCreateSwapChain);
DetourAttach(&(PVOID&)oCreateSwapChainForHwnd, hkCreateSwapChainForHwnd);
DetourTransactionCommit();
}
factory2->Release();
factory2 = nullptr;
}
}
return result;
}
static HRESULT hkEnumAdapterByGpuPreference(IDXGIFactory6* This, UINT Adapter, DXGI_GPU_PREFERENCE GpuPreference, REFIID riid, IUnknown** ppvAdapter)
{
auto result = ptrEnumAdapterByGpuPreference(This, Adapter, GpuPreference, riid, ppvAdapter);
if (result == S_OK)
CheckAdapter(*ppvAdapter);
return result;
}
static HRESULT hkEnumAdapterByLuid(IDXGIFactory4* This, LUID AdapterLuid, REFIID riid, IUnknown** ppvAdapter)
{
auto result = ptrEnumAdapterByLuid(This, AdapterLuid, riid, ppvAdapter);
if (result == S_OK)
CheckAdapter(*ppvAdapter);
return result;
}
static HRESULT hkEnumAdapters1(IDXGIFactory1* This, UINT Adapter, IUnknown** ppAdapter)
{
auto result = ptrEnumAdapters1(This, Adapter, ppAdapter);
if (result == S_OK)
CheckAdapter(*ppAdapter);
return result;
}
static HRESULT hkEnumAdapters(IDXGIFactory* This, UINT Adapter, IUnknown** ppAdapter)
{
auto result = ptrEnumAdapters(This, Adapter, ppAdapter);
if (result == S_OK)
CheckAdapter(*ppAdapter);
return result;
}
#pragma endregion
@@ -1048,7 +757,7 @@ static HRESULT hkD3D11CreateDeviceAndSwapChain(IDXGIAdapter* pAdapter, D3D_DRIVE
HookToDevice(d3d11Device);
WrappedIDXGISwapChain4* buf = nullptr;
WrappedSwapChain* buf = nullptr;
if (buffer != nullptr && buffer->QueryInterface(IID_PPV_ARGS(&buf)) != S_OK)
{
// check for SL proxy
@@ -1082,8 +791,8 @@ static HRESULT hkD3D11CreateDeviceAndSwapChain(IDXGIAdapter* pAdapter, D3D_DRIVE
}
LOG_DEBUG("created new swapchain: {0:X}, hWnd: {1:X}", (UINT64)buffer, (UINT64)pSwapChainDesc->OutputWindow);
*ppSwapChain = new WrappedIDXGISwapChain4(real == nullptr ? buffer : real, d3d11Device, pSwapChainDesc->OutputWindow, Present, CleanupRenderTarget);
LOG_DEBUG("created new WrappedIDXGISwapChain4: {0:X}, pDevice: {1:X}", (UINT64)buffer, (UINT64)d3d11Device);
*ppSwapChain = new WrappedSwapChain(real == nullptr ? buffer : real, d3d11Device, pSwapChainDesc->OutputWindow, Present, CleanupRenderTarget);
LOG_DEBUG("created new WrappedSwapChain: {0:X}, pDevice: {1:X}", (UINT64)buffer, (UINT64)d3d11Device);
}
}
+29 -4
View File
@@ -499,14 +499,14 @@ VkResult MenuVulkan::QueuePresent(VkQueue queue, VkPresentInfoKHR* pPresentInfo)
_vkPresentMutex.lock();
if (MenuVulkan::vkUpscaleTrig && MenuVulkan::queryPool != VK_NULL_HANDLE)
if (vkUpscaleTrig && queryPool != VK_NULL_HANDLE)
{
// Retrieve timestamps
uint64_t timestamps[2];
vkGetQueryPoolResults(_device, MenuVulkan::queryPool, 0, 2, sizeof(timestamps), timestamps, sizeof(uint64_t), VK_QUERY_RESULT_64_BIT);
vkGetQueryPoolResults(_device, queryPool, 0, 2, sizeof(timestamps), timestamps, sizeof(uint64_t), VK_QUERY_RESULT_64_BIT);
// Calculate elapsed time in milliseconds
double elapsedTimeMs = (timestamps[1] - timestamps[0]) * MenuVulkan::timeStampPeriod / 1e6;
double elapsedTimeMs = (timestamps[1] - timestamps[0]) * timeStampPeriod / 1e6;
if (elapsedTimeMs > 0.0 && elapsedTimeMs < 5000.0)
{
@@ -514,7 +514,7 @@ VkResult MenuVulkan::QueuePresent(VkQueue queue, VkPresentInfoKHR* pPresentInfo)
Config::Instance()->upscaleTimes.pop_front();
}
MenuVulkan::vkUpscaleTrig = false;
vkUpscaleTrig = false;
}
LOG_DEBUG("rendering menu, swapchain count: {0}", pPresentInfo->swapchainCount);
@@ -648,3 +648,28 @@ void MenuVulkan::CreateSwapchain(VkDevice device, const VkSwapchainCreateInfoKHR
MenuBase::VulkanReady();
}
}
void MenuVulkan::PrepareTimeObjects(VkInstance InInstance, VkPhysicalDevice InPD, VkDevice InDevice)
{
VkQueryPoolCreateInfo queryPoolInfo = {};
queryPoolInfo.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
queryPoolInfo.queryType = VK_QUERY_TYPE_TIMESTAMP;
queryPoolInfo.queryCount = 2; // Start and End timestamps
vkCreateQueryPool(InDevice, &queryPoolInfo, nullptr, &queryPool);
VkPhysicalDeviceProperties deviceProperties;
vkGetPhysicalDeviceProperties(InPD, &deviceProperties);
timeStampPeriod = deviceProperties.limits.timestampPeriod;
}
void MenuVulkan::BeforeUpscale(VkCommandBuffer InCmdBuffer)
{
vkCmdWriteTimestamp(InCmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, queryPool, 0);
}
void MenuVulkan::AfterUpscale(VkCommandBuffer InCmdBuffer)
{
vkCmdWriteTimestamp(InCmdBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, queryPool, 1);
vkUpscaleTrig = true;
}
+3
View File
@@ -17,4 +17,7 @@ public:
static void CreateDevice(VkPhysicalDevice physicalDevice, VkDevice* pDevice);
static VkResult QueuePresent(VkQueue queue, VkPresentInfoKHR* pPresentInfo);
static void CreateSwapchain(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, VkSwapchainKHR* pSwapchain);
static void PrepareTimeObjects(VkInstance InInstance, VkPhysicalDevice InPD, VkDevice InDevice);
static void BeforeUpscale(VkCommandBuffer InCmdBuffer);
static void AfterUpscale(VkCommandBuffer InCmdBuffer);
};
@@ -1,4 +1,4 @@
#include "wrapped_swapchain.h"
#include "WrappedSwapChain.h"
#include <Util.h>
#include <Config.h>
@@ -8,7 +8,7 @@
static int scCount = 0;
WrappedIDXGISwapChain4::WrappedIDXGISwapChain4(IDXGISwapChain* real, IUnknown* pDevice, HWND hWnd, PFN_SC_Present renderTrig, PFN_SC_Clean clearTrig)
WrappedSwapChain::WrappedSwapChain(IDXGISwapChain* real, IUnknown* pDevice, HWND hWnd, PFN_SC_Present renderTrig, PFN_SC_Clean clearTrig)
: m_pReal(real), Device(pDevice), Handle(hWnd), RenderTrig(renderTrig), ClearTrig(clearTrig), m_iRefcount(1)
{
id = ++scCount;
@@ -19,12 +19,12 @@ WrappedIDXGISwapChain4::WrappedIDXGISwapChain4(IDXGISwapChain* real, IUnknown* p
m_pReal->QueryInterface(IID_PPV_ARGS(&m_pReal4));
}
WrappedIDXGISwapChain4::~WrappedIDXGISwapChain4()
WrappedSwapChain::~WrappedSwapChain()
{
}
HRESULT STDMETHODCALLTYPE WrappedIDXGISwapChain4::QueryInterface(REFIID riid, void** ppvObject)
HRESULT STDMETHODCALLTYPE WrappedSwapChain::QueryInterface(REFIID riid, void** ppvObject)
{
if (riid == __uuidof(IDXGISwapChain))
{
@@ -112,7 +112,7 @@ HRESULT STDMETHODCALLTYPE WrappedIDXGISwapChain4::QueryInterface(REFIID riid, vo
return E_NOINTERFACE;
}
HRESULT WrappedIDXGISwapChain4::ResizeBuffers(UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags)
HRESULT WrappedSwapChain::ResizeBuffers(UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags)
{
LOG_FUNC();
@@ -136,12 +136,12 @@ HRESULT WrappedIDXGISwapChain4::ResizeBuffers(UINT BufferCount, UINT Width, UINT
return result;
}
HRESULT STDMETHODCALLTYPE WrappedIDXGISwapChain4::GetContainingOutput(IDXGIOutput** ppOutput)
HRESULT STDMETHODCALLTYPE WrappedSwapChain::GetContainingOutput(IDXGIOutput** ppOutput)
{
return m_pReal->GetContainingOutput(ppOutput);
}
HRESULT WrappedIDXGISwapChain4::ResizeBuffers1(UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT Format, UINT SwapChainFlags,
HRESULT WrappedSwapChain::ResizeBuffers1(UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT Format, UINT SwapChainFlags,
const UINT* pCreationNodeMask, IUnknown* const* ppPresentQueue)
{
LOG_FUNC();
@@ -166,27 +166,27 @@ HRESULT WrappedIDXGISwapChain4::ResizeBuffers1(UINT BufferCount, UINT Width, UIN
return result;
}
HRESULT WrappedIDXGISwapChain4::SetFullscreenState(BOOL Fullscreen, IDXGIOutput* pTarget)
HRESULT WrappedSwapChain::SetFullscreenState(BOOL Fullscreen, IDXGIOutput* pTarget)
{
return m_pReal->SetFullscreenState(Fullscreen, pTarget);
}
HRESULT WrappedIDXGISwapChain4::GetFullscreenState(BOOL* pFullscreen, IDXGIOutput** ppTarget)
HRESULT WrappedSwapChain::GetFullscreenState(BOOL* pFullscreen, IDXGIOutput** ppTarget)
{
return m_pReal->GetFullscreenState(pFullscreen, ppTarget);
}
HRESULT WrappedIDXGISwapChain4::GetBuffer(UINT Buffer, REFIID riid, void** ppSurface)
HRESULT WrappedSwapChain::GetBuffer(UINT Buffer, REFIID riid, void** ppSurface)
{
return m_pReal->GetBuffer(Buffer, riid, ppSurface);
}
HRESULT WrappedIDXGISwapChain4::GetDevice(REFIID riid, void** ppDevice)
HRESULT WrappedSwapChain::GetDevice(REFIID riid, void** ppDevice)
{
return m_pReal->GetDevice(riid, ppDevice);
}
HRESULT WrappedIDXGISwapChain4::Present(UINT SyncInterval, UINT Flags)
HRESULT WrappedSwapChain::Present(UINT SyncInterval, UINT Flags)
{
if (m_pReal == nullptr)
return DXGI_ERROR_DEVICE_REMOVED;
@@ -201,7 +201,7 @@ HRESULT WrappedIDXGISwapChain4::Present(UINT SyncInterval, UINT Flags)
return result;
}
HRESULT WrappedIDXGISwapChain4::Present1(UINT SyncInterval, UINT Flags, const DXGI_PRESENT_PARAMETERS* pPresentParameters)
HRESULT WrappedSwapChain::Present1(UINT SyncInterval, UINT Flags, const DXGI_PRESENT_PARAMETERS* pPresentParameters)
{
if (m_pReal1 == nullptr)
return DXGI_ERROR_DEVICE_REMOVED;
@@ -216,7 +216,7 @@ HRESULT WrappedIDXGISwapChain4::Present1(UINT SyncInterval, UINT Flags, const DX
return result;
}
HRESULT STDMETHODCALLTYPE WrappedIDXGISwapChain4::GetRestrictToOutput(IDXGIOutput** ppRestrictToOutput)
HRESULT STDMETHODCALLTYPE WrappedSwapChain::GetRestrictToOutput(IDXGIOutput** ppRestrictToOutput)
{
return m_pReal1->GetRestrictToOutput(ppRestrictToOutput);
}
@@ -2,18 +2,16 @@
#include <pch.h>
#include "MenuBase.h"
#include <dxgi1_6.h>
typedef HRESULT(*PFN_SC_Present)(IDXGISwapChain*, UINT, UINT, const DXGI_PRESENT_PARAMETERS*, IUnknown*, HWND);
typedef void(*PFN_SC_Clean)(bool, HWND);
struct DECLSPEC_UUID("3af622a3-82d0-49cd-994f-cce05122c222") WrappedIDXGISwapChain4 : public IDXGISwapChain4
struct DECLSPEC_UUID("3af622a3-82d0-49cd-994f-cce05122c222") WrappedSwapChain : public IDXGISwapChain4
{
WrappedIDXGISwapChain4(IDXGISwapChain* real, IUnknown* pDevice, HWND hWnd, PFN_SC_Present renderTrig, PFN_SC_Clean clearTrig);
WrappedSwapChain(IDXGISwapChain* real, IUnknown* pDevice, HWND hWnd, PFN_SC_Present renderTrig, PFN_SC_Clean clearTrig);
virtual ~WrappedIDXGISwapChain4();
virtual ~WrappedSwapChain();
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject);
+5 -11
View File
@@ -1,20 +1,14 @@
#pragma once
#include "pch.h"
#include <pch.h>
#include "Util.h"
#include "Config.h"
#include "Logger.h"
#include <Util.h>
#include <Config.h>
#include <Logger.h>
#include "ffx_api.h"
#include <include/detours/detours.h>
typedef struct _feature_version
{
unsigned int major;
unsigned int minor;
unsigned int patch;
} feature_version;
#include <include/detours/detours.h>
class FfxApiProxy
{
+39 -123
View File
@@ -17,81 +17,14 @@ constexpr unsigned long long app_id_override = 0x24480451;
#pragma region spoofing hooks for 16xx
// NvAPI_GPU_GetArchInfo hooking based on Nukem's spoofing code here
// https://github.com/Nukem9/dlssg-to-fsr3/blob/89ddc8c1cce4593fb420e633a06605c3c4b9c3cf/source/wrapper_generic/nvapi.cpp#L50
enum class NV_INTERFACE : uint32_t
{
GPU_GetArchInfo = 0xD8265D24,
D3D12_SetRawScgPriority = 0x5DB3048A,
};
typedef void* (__stdcall* PFN_NvApi_QueryInterface)(NV_INTERFACE InterfaceId);
typedef NVSDK_NGX_Result(*PFN_NVSDK_NGX_D3D1X_GetFeatureRequirements)(IDXGIAdapter* Adapter, const NVSDK_NGX_FeatureDiscoveryInfo* FeatureDiscoveryInfo, NVSDK_NGX_FeatureRequirement* OutSupported);
typedef NVSDK_NGX_Result(*PFN_NVSDK_NGX_VULKAN_GetFeatureRequirements)(const VkInstance Instance, const VkPhysicalDevice PhysicalDevice,
const NVSDK_NGX_FeatureDiscoveryInfo* FeatureDiscoveryInfo, NVSDK_NGX_FeatureRequirement* OutSupported);
using PfnNvAPI_GPU_GetArchInfo = uint32_t(__stdcall*)(void* GPUHandle, NV_GPU_ARCH_INFO* ArchInfo);
inline static PFN_NvApi_QueryInterface OriginalNvAPI_QueryInterface = nullptr;
inline static PfnNvAPI_GPU_GetArchInfo OriginalNvAPI_GPU_GetArchInfo = nullptr;
inline static PFN_NVSDK_NGX_D3D1X_GetFeatureRequirements Original_D3D11_GetFeatureRequirements = nullptr;
inline static PFN_NVSDK_NGX_D3D1X_GetFeatureRequirements Original_D3D12_GetFeatureRequirements = nullptr;
inline static PFN_NVSDK_NGX_VULKAN_GetFeatureRequirements Original_Vulkan_GetFeatureRequirements = nullptr;
inline static uint32_t __stdcall HookedNvAPI_GPU_GetArchInfo(void* GPUHandle, NV_GPU_ARCH_INFO* ArchInfo)
{
if (OriginalNvAPI_GPU_GetArchInfo)
{
const auto status = OriginalNvAPI_GPU_GetArchInfo(GPUHandle, ArchInfo);
if (status == 0 && ArchInfo)
{
LOG_DEBUG("From api arch: {0:X} impl: {1:X} rev: {2:X}!", ArchInfo->architecture, ArchInfo->implementation, ArchInfo->revision);
// for 16xx cards
if (ArchInfo->architecture == NV_GPU_ARCHITECTURE_TU100 && ArchInfo->implementation > NV_GPU_ARCH_IMPLEMENTATION_TU106)
{
ArchInfo->implementation = NV_GPU_ARCH_IMPLEMENTATION_TU106;
ArchInfo->implementation_id = NV_GPU_ARCH_IMPLEMENTATION_TU106;
LOG_INFO("Spoofed arch: {0:X} impl: {1:X} rev: {2:X}!", ArchInfo->architecture, ArchInfo->implementation, ArchInfo->revision);
}
//else if (ArchInfo->architecture < NV_GPU_ARCHITECTURE_TU100 && ArchInfo->architecture >= NV_GPU_ARCHITECTURE_GP100)
//{
// LOG_INFO("Spoofing below 16xx arch: {0:X} impl: {1:X} rev: {2:X}!", ArchInfo->architecture, ArchInfo->implementation, ArchInfo->revision);
// ArchInfo->architecture = NV_GPU_ARCHITECTURE_TU100;
// ArchInfo->architecture_id = NV_GPU_ARCHITECTURE_TU100;
// ArchInfo->implementation = NV_GPU_ARCH_IMPLEMENTATION_TU106;
// ArchInfo->implementation_id = NV_GPU_ARCH_IMPLEMENTATION_TU106;
// LOG_INFO("Spoofed arch: {0:X} impl: {1:X} rev: {2:X}!", ArchInfo->architecture, ArchInfo->implementation, ArchInfo->revision);
//}
}
return status;
}
return 0xFFFFFFFF;
}
inline static void* __stdcall HookedNvAPI_QueryInterface(NV_INTERFACE InterfaceId)
{
const auto result = OriginalNvAPI_QueryInterface(InterfaceId);
if (result)
{
if (InterfaceId == NV_INTERFACE::GPU_GetArchInfo)
{
OriginalNvAPI_GPU_GetArchInfo = static_cast<PfnNvAPI_GPU_GetArchInfo>(result);
return &HookedNvAPI_GPU_GetArchInfo;
}
}
return result;
}
inline static NVSDK_NGX_Result __stdcall Hooked_Dx12_GetFeatureRequirements(IDXGIAdapter* Adapter, const NVSDK_NGX_FeatureDiscoveryInfo* FeatureDiscoveryInfo, NVSDK_NGX_FeatureRequirement* OutSupported)
{
LOG_FUNC();
@@ -144,29 +77,6 @@ inline static NVSDK_NGX_Result __stdcall Hooked_Vulkan_GetFeatureRequirements(co
return result;
}
inline static void HookNvApi()
{
if (OriginalNvAPI_QueryInterface != nullptr)
return;
LOG_DEBUG("Trying to hook NvApi");
OriginalNvAPI_QueryInterface = (PFN_NvApi_QueryInterface)DetourFindFunction("nvapi64.dll", "nvapi_QueryInterface");
LOG_DEBUG("OriginalNvAPI_QueryInterface = {0:X}", (unsigned long long)OriginalNvAPI_QueryInterface);
if (OriginalNvAPI_QueryInterface != nullptr)
{
LOG_INFO("NvAPI_QueryInterface found, hooking!");
if (!Config::Instance()->DE_Available)
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)OriginalNvAPI_QueryInterface, HookedNvAPI_QueryInterface);
DetourTransactionCommit();
}
}
}
inline static void HookNgxApi(HMODULE nvngx)
{
if (Original_D3D11_GetFeatureRequirements != nullptr || Original_D3D12_GetFeatureRequirements != nullptr)
@@ -200,42 +110,32 @@ inline static void HookNgxApi(HMODULE nvngx)
inline static void UnhookApis()
{
if (OriginalNvAPI_QueryInterface != nullptr || Original_D3D11_GetFeatureRequirements != nullptr || Original_D3D12_GetFeatureRequirements != nullptr)
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
if (Original_D3D11_GetFeatureRequirements != nullptr)
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
if (OriginalNvAPI_QueryInterface != nullptr)
{
DetourDetach(&(PVOID&)OriginalNvAPI_QueryInterface, HookedNvAPI_QueryInterface);
OriginalNvAPI_QueryInterface = nullptr;
}
if (Original_D3D11_GetFeatureRequirements != nullptr)
{
DetourDetach(&(PVOID&)Original_D3D11_GetFeatureRequirements, Hooked_Dx11_GetFeatureRequirements);
Original_D3D11_GetFeatureRequirements = nullptr;
}
if (Original_D3D12_GetFeatureRequirements != nullptr)
{
DetourDetach(&(PVOID&)Original_D3D12_GetFeatureRequirements, Hooked_Dx12_GetFeatureRequirements);
Original_D3D12_GetFeatureRequirements = nullptr;
}
if (Original_Vulkan_GetFeatureRequirements != nullptr)
{
DetourDetach(&(PVOID&)Original_Vulkan_GetFeatureRequirements, Hooked_Vulkan_GetFeatureRequirements);
Original_Vulkan_GetFeatureRequirements = nullptr;
}
DetourTransactionCommit();
DetourDetach(&(PVOID&)Original_D3D11_GetFeatureRequirements, Hooked_Dx11_GetFeatureRequirements);
Original_D3D11_GetFeatureRequirements = nullptr;
}
if (Original_D3D12_GetFeatureRequirements != nullptr)
{
DetourDetach(&(PVOID&)Original_D3D12_GetFeatureRequirements, Hooked_Dx12_GetFeatureRequirements);
Original_D3D12_GetFeatureRequirements = nullptr;
}
if (Original_Vulkan_GetFeatureRequirements != nullptr)
{
DetourDetach(&(PVOID&)Original_Vulkan_GetFeatureRequirements, Hooked_Vulkan_GetFeatureRequirements);
Original_Vulkan_GetFeatureRequirements = nullptr;
}
DetourTransactionCommit();
}
#pragma endregion
typedef NVSDK_NGX_Result(*PFN_CUDA_Init)(unsigned long long InApplicationId, const wchar_t* InApplicationDataPath, const NVSDK_NGX_FeatureCommonInfo* InFeatureInfo, NVSDK_NGX_Version InSDKVersion);
typedef NVSDK_NGX_Result(*PFN_CUDA_Init_ProjectID)(const char* InProjectId, NVSDK_NGX_EngineType InEngineType, const char* InEngineVersion, const wchar_t* InApplicationDataPath, NVSDK_NGX_Version InSDKVersion, const NVSDK_NGX_FeatureCommonInfo* InFeatureInfo);
typedef NVSDK_NGX_Result(*PFN_CUDA_Shutdown)(void);
@@ -382,7 +282,7 @@ public:
if (_dll != nullptr)
return;
LOG_FUNC();
spdlog::info("");
Config::Instance()->upscalerDisableHook = true;
@@ -492,11 +392,22 @@ public:
if (_dll != nullptr)
{
HookNvApi();
if (!Config::Instance()->DE_Available)
HookNgxApi(_dll);
LOG_INFO("nvngx.dll loaded, setting DLSS as default upscaler and disabling spoofing options set to auto");
Config::Instance()->DLSSEnabled = true;
if (!Config::Instance()->DxgiSpoofing.has_value())
Config::Instance()->DxgiSpoofing = false;
if (!Config::Instance()->VulkanSpoofing.has_value())
Config::Instance()->VulkanSpoofing = false;
if (!Config::Instance()->VulkanExtensionSpoofing.has_value())
Config::Instance()->VulkanExtensionSpoofing = false;
LOG_INFO("getting nvngx method addresses");
_D3D11_Init = (PFN_D3D11_Init)GetProcAddress(_dll, "NVSDK_NGX_D3D11_Init");
@@ -552,6 +463,11 @@ public:
_UpdateFeature = (PFN_UpdateFeature)GetProcAddress(_dll, "NVSDK_NGX_UpdateFeature");
}
else
{
LOG_INFO("Can't load nvngx.dll, disabling DLSS");
Config::Instance()->DLSSEnabled = false;
}
Config::Instance()->upscalerDisableHook = false;
}