mirror of
https://github.com/optiscaler/OptiScaler.git
synced 2026-09-24 14:25:42 +00:00
stash
This commit is contained in:
@@ -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" />
|
||||
|
||||
@@ -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(×tampQueryDesc, &ImGuiOverlayDx::startQueries[i]);
|
||||
InDevice->CreateQuery(×tampQueryDesc, &ImGuiOverlayDx::endQueries[i]);
|
||||
InDevice->CreateQuery(&disjointQueryDesc, &MenuDx::disjointQueries[i]);
|
||||
InDevice->CreateQuery(×tampQueryDesc, &MenuDx::startQueries[i]);
|
||||
InDevice->CreateQuery(×tampQueryDesc, &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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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**>(×tampData));
|
||||
|
||||
// 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()
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#include <pch.h>
|
||||
|
||||
class DxgiHooks
|
||||
{
|
||||
private:
|
||||
public:
|
||||
static void Hook();
|
||||
static void Unhook();
|
||||
};
|
||||
@@ -1,6 +0,0 @@
|
||||
#include "Hooks.h"
|
||||
|
||||
void Hooks::Attach()
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
#pragma once
|
||||
#include <pch.h>
|
||||
|
||||
class Hooks
|
||||
{
|
||||
public:
|
||||
void Attach();
|
||||
};
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user