From a05c7471928895232f6cafb5b060b9779b62908e Mon Sep 17 00:00:00 2001 From: cdozdil Date: Tue, 17 Sep 2024 16:27:04 +0300 Subject: [PATCH] fix for rtss crash, improve compatibility and stability --- OptiScaler/imgui/imgui_overlay_dx.cpp | 1102 +++++++++++++++---------- 1 file changed, 648 insertions(+), 454 deletions(-) diff --git a/OptiScaler/imgui/imgui_overlay_dx.cpp b/OptiScaler/imgui/imgui_overlay_dx.cpp index ea96fdd8..3d9030a4 100644 --- a/OptiScaler/imgui/imgui_overlay_dx.cpp +++ b/OptiScaler/imgui/imgui_overlay_dx.cpp @@ -10,31 +10,53 @@ #include "imgui/imgui_impl_win32.h" #include "../detours/detours.h" -#include #include +#include #include "wrapped_swapchain.h" -// Dx12 overlay code adoptes from -// https://github.com/bruhmoment21/UniversalHookX - // 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(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); +static PFN_CreateDXGIFactory o_CreateDXGIFactory = nullptr; +static PFN_CreateDXGIFactory1 o_CreateDXGIFactory1 = nullptr; +static PFN_CreateDXGIFactory2 o_CreateDXGIFactory2 = nullptr; + 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; -inline static ankerl::unordered_dense::map < UINT64, std::unique_ptr> WrappedSwapChains; +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); + +static PFN_D3D12_CREATE_DEVICE o_D3D12CreateDevice = nullptr; static PFN_CreateSampler o_CreateSampler = nullptr; +static PFN_D3D11_CREATE_DEVICE o_D3D11CreateDevice = nullptr; +static PFN_CreateSamplerState o_CreateSamplerState = nullptr; +static PFN_D3D11ON12_CREATE_DEVICE o_D3D11On12CreateDevice = nullptr; +static ID3D11Device* d3d11Device = nullptr; +static ID3D11Device* d3d11on12Device = nullptr; + +// current command queue for dx12 swapchain +static IUnknown* currentSCCommandQueue = nullptr; + // menu static int const NUM_BACK_BUFFERS = 8; static bool _dx11Device = false; @@ -55,33 +77,26 @@ static ID3D12CommandAllocator* g_commandAllocators[NUM_BACK_BUFFERS] = { }; static ID3D12Resource* g_mainRenderTargetResource[NUM_BACK_BUFFERS] = { }; static D3D12_CPU_DESCRIPTOR_HANDLE g_mainRenderTargetDescriptor[NUM_BACK_BUFFERS] = { }; -typedef HRESULT(*PFN_CreateDXGIFactory)(REFIID riid, void** ppFactory); -typedef HRESULT(*PFN_CreateDXGIFactory1)(REFIID riid, void** ppFactory); -typedef HRESULT(*PFN_CreateDXGIFactory2)(UINT Flags, REFIID riid, _COM_Outptr_ void** ppFactory); - -// Dx12 early binding -static PFN_D3D12_CREATE_DEVICE o_D3D12CreateDevice = nullptr; -static PFN_CreateDXGIFactory o_CreateDXGIFactory = nullptr; -static PFN_CreateDXGIFactory1 o_CreateDXGIFactory1 = nullptr; -static PFN_CreateDXGIFactory2 o_CreateDXGIFactory2 = nullptr; - -// Dx12 early binding -static PFN_CreateSwapChain oCreateSwapChain_EB = nullptr; -static PFN_CreateSwapChainForHwnd oCreateSwapChainForHwnd_EB = nullptr; -static PFN_CreateSwapChainForComposition oCreateSwapChainForComposition_EB = nullptr; -static PFN_CreateSwapChainForCoreWindow oCreateSwapChainForCoreWindow_EB = nullptr; - +// status static bool _isInited = false; // for showing static bool _showRenderImGuiDebugOnce = true; +// mutexes static std::mutex _dx11CleanMutex; static std::mutex _dx12CleanMutex; -static void RenderImGui_DX12(IDXGISwapChain* pSwapChain); + static void RenderImGui_DX11(IDXGISwapChain* pSwapChain); +static void RenderImGui_DX12(IDXGISwapChain* pSwapChain); static void DeatachAllHooks(); +static void hkCreateSampler(ID3D12Device* device, const D3D12_SAMPLER_DESC* pDesc, D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor); +static HRESULT hkCreateSamplerState(ID3D11Device* This, const D3D11_SAMPLER_DESC* pSamplerDesc, ID3D11SamplerState** ppSamplerState); +static HRESULT detEnumAdapters(IDXGIFactory* This, UINT Adapter, IUnknown** ppAdapter); +static HRESULT detEnumAdapters1(IDXGIFactory1* This, UINT Adapter, IUnknown** ppAdapter); +static HRESULT detEnumAdapterByLuid(IDXGIFactory4* This, LUID AdapterLuid, REFIID riid, IUnknown** ppvAdapter); +static HRESULT detEnumAdapterByGpuPreference(IDXGIFactory6* This, UINT Adapter, DXGI_GPU_PREFERENCE GpuPreference, REFIID riid, IUnknown** ppvAdapter); static int GetCorrectDXGIFormat(int eCurrentFormat) { @@ -191,13 +206,15 @@ static void CleanupRenderTargetDx12(bool clearQueue) if (g_pd3dCommandQueue != nullptr) { - g_pd3dCommandQueue->Release(); + auto count = g_pd3dCommandQueue->Release(); + LOG_DEBUG("D3D12 Queue refcount: {}", count); g_pd3dCommandQueue = nullptr; } if (g_pd3dDeviceParam != nullptr) { - g_pd3dDeviceParam->Release(); + auto count = g_pd3dDeviceParam->Release(); + LOG_DEBUG("D3D12 device refcount: {}", count); g_pd3dDeviceParam = nullptr; } @@ -225,12 +242,13 @@ static void CreateRenderTargetDx11(IDXGISwapChain* pSwapChain) } } -static void CleanupRenderTargetDx11() +static void CleanupRenderTargetDx11(bool shutDown) { if (!_isInited || !_dx11Device) return; - LOG_FUNC(); + if (!shutDown) + LOG_FUNC(); if (g_pd3dRenderTarget != nullptr) { @@ -248,98 +266,31 @@ static void CleanupRenderTargetDx11() _isInited = false; } +#pragma region Callbacks for wrapped swapchain + static void CleanupRenderTarget(bool clearQueue, HWND hWnd) { if (hWnd != Util::GetProcessWindow()) return; + if (clearQueue) + currentSCCommandQueue = nullptr; + if (_dx11Device) - CleanupRenderTargetDx11(); + CleanupRenderTargetDx11(false); else CleanupRenderTargetDx12(clearQueue); -} -#pragma region Mipmap Hook - -static void hkCreateSampler(ID3D12Device* device, const D3D12_SAMPLER_DESC* pDesc, D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor) -{ - if (pDesc == nullptr || device == nullptr) - return; - - D3D12_SAMPLER_DESC newDesc{}; - - newDesc.AddressU = pDesc->AddressU; - newDesc.AddressV = pDesc->AddressV; - newDesc.AddressW = pDesc->AddressW; - newDesc.BorderColor[0] = pDesc->BorderColor[0]; - newDesc.BorderColor[1] = pDesc->BorderColor[1]; - newDesc.BorderColor[2] = pDesc->BorderColor[2]; - newDesc.BorderColor[3] = pDesc->BorderColor[3]; - newDesc.ComparisonFunc = pDesc->ComparisonFunc; - - if (Config::Instance()->AnisotropyOverride.has_value() && - (pDesc->Filter == D3D12_FILTER_MIN_LINEAR_MAG_MIP_POINT || - pDesc->Filter == D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT || - pDesc->Filter == D3D12_FILTER_MIN_MAG_MIP_LINEAR || - pDesc->Filter == D3D12_FILTER_ANISOTROPIC)) + // Releasing RTSS D3D11on12 device + if (clearQueue && GetModuleHandle(L"RTSSHooks64.dll") != nullptr && d3d11on12Device != nullptr) { - LOG_INFO("Overriding Anisotrpic ({2}) filtering {0} -> {1}", pDesc->MaxAnisotropy, Config::Instance()->AnisotropyOverride.value(), (UINT)pDesc->Filter); - newDesc.Filter = D3D12_FILTER_ANISOTROPIC; - newDesc.MaxAnisotropy = Config::Instance()->AnisotropyOverride.value(); - } - else - { - newDesc.Filter = pDesc->Filter; - newDesc.MaxAnisotropy = pDesc->MaxAnisotropy; - } - - newDesc.MaxLOD = pDesc->MaxLOD; - newDesc.MinLOD = pDesc->MinLOD; - newDesc.MipLODBias = pDesc->MipLODBias; - - if (newDesc.MipLODBias < 0.0f) - { - if (Config::Instance()->MipmapBiasOverride.has_value()) - { - LOG_INFO("Overriding mipmap bias {0} -> {1}", pDesc->MipLODBias, Config::Instance()->MipmapBiasOverride.value()); - newDesc.MipLODBias = Config::Instance()->MipmapBiasOverride.value(); - } - - Config::Instance()->lastMipBias = newDesc.MipLODBias; - } - - return o_CreateSampler(device, &newDesc, DestDescriptor); -} - - -static void HookToDevice(ID3D12Device* InDevice) -{ - if (o_CreateSampler != nullptr || InDevice == nullptr) - return; - - // Get the vtable pointer - PVOID* pVTable = *(PVOID**)InDevice; - - // Get the address of the SetComputeRootSignature function from the vtable - o_CreateSampler = (PFN_CreateSampler)pVTable[22]; - - // Apply the detour - if (o_CreateSampler != nullptr) - { - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); - - DetourAttach(&(PVOID&)o_CreateSampler, hkCreateSampler); - - DetourTransactionCommit(); + LOG_DEBUG("Releasing D3d11on12 device"); + d3d11on12Device->Release(); + d3d11on12Device = nullptr; } } -#pragma endregion - -#pragma region Hooks for native EB Prensent Methods - -static void Present(IDXGISwapChain* pSwapChain, IUnknown* pDevice, HWND hWnd) +static HRESULT Present(IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags, const DXGI_PRESENT_PARAMETERS* pPresentParameters, IUnknown* pDevice, HWND hWnd) { ID3D12CommandQueue* cq = nullptr; ID3D11Device* device = nullptr; @@ -355,6 +306,8 @@ static void Present(IDXGISwapChain* pSwapChain, IUnknown* pDevice, HWND hWnd) { LOG_DEBUG("dx12 queue"); + currentSCCommandQueue = pDevice; + if (cq->GetDevice(IID_PPV_ARGS(&device12)) == S_OK) { LOG_DEBUG("_dx12Device"); @@ -367,23 +320,23 @@ static void Present(IDXGISwapChain* pSwapChain, IUnknown* pDevice, HWND hWnd) { if (ImGuiOverlayBase::IsInited() && ImGuiOverlayBase::IsVisible()) { - UINT64* timestampData; - ImGuiOverlayDx::readbackBuffer->Map(0, nullptr, reinterpret_cast(×tampData)); + UINT64* timestampData; + ImGuiOverlayDx::readbackBuffer->Map(0, nullptr, reinterpret_cast(×tampData)); - // Get the GPU timestamp frequency (ticks per second) - UINT64 gpuFrequency; - cq->GetTimestampFrequency(&gpuFrequency); + // 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(gpuFrequency) * 1000.0; + // Calculate elapsed time in milliseconds + UINT64 startTime = timestampData[0]; + UINT64 endTime = timestampData[1]; + double elapsedTimeMs = (endTime - startTime) / static_cast(gpuFrequency) * 1000.0; - Config::Instance()->upscaleTimes.push_back(elapsedTimeMs); - Config::Instance()->upscaleTimes.pop_front(); + Config::Instance()->upscaleTimes.push_back(elapsedTimeMs); + Config::Instance()->upscaleTimes.pop_front(); - // Unmap the buffer - ImGuiOverlayDx::readbackBuffer->Unmap(0, nullptr); + // Unmap the buffer + ImGuiOverlayDx::readbackBuffer->Unmap(0, nullptr); } ImGuiOverlayDx::dx12UpscaleTrig = false; @@ -409,45 +362,17 @@ static void Present(IDXGISwapChain* pSwapChain, IUnknown* pDevice, HWND hWnd) double elapsedTimeMs = (endTime - startTime) / static_cast(disjointData.Frequency) * 1000.0; Config::Instance()->upscaleTimes.push_back(elapsedTimeMs); Config::Instance()->upscaleTimes.pop_front(); + } + } } + } - if (disjointData.Disjoint) { - LOG_ERROR("Timestamps are disjoint, data is invalid."); - break; // Exit if the timestamps are invalid - } - - // Wait for the start timestamp data - while (g_pd3dDeviceContext->GetData(ImGuiOverlayDx::timestampStartQuery, nullptr, 0, 0) == S_FALSE) { - std::this_thread::yield(); - } - - // Retrieve the start timestamp - UINT64 startTime = 0; - if (g_pd3dDeviceContext->GetData(ImGuiOverlayDx::timestampStartQuery, &startTime, sizeof(UINT64), 0) != S_OK) { - LOG_ERROR("Failed to retrieve start timestamp!"); - break; - } - - // Wait for the end timestamp data - while (g_pd3dDeviceContext->GetData(ImGuiOverlayDx::timestampEndQuery, nullptr, 0, 0) == S_FALSE) { - std::this_thread::yield(); - } ImGuiOverlayDx::dx11UpscaleTrig[ImGuiOverlayDx::currentFrameIndex] = false; ImGuiOverlayDx::currentFrameIndex = (ImGuiOverlayDx::currentFrameIndex + 1) % ImGuiOverlayDx::QUERY_BUFFER_COUNT; - } - - // Calculate the elapsed time in milliseconds - if (disjointData.Frequency > 0) { - double elapsedTimeMs = (endTime - startTime) / static_cast(disjointData.Frequency) * 1000.0; - Config::Instance()->upscaleTimes.push_back(elapsedTimeMs); - Config::Instance()->upscaleTimes.pop_front(); - } - } while (false); - - ImGuiOverlayDx::dx11UpscaleTrig = false; } + // DXVK & process hWnd check if (Config::Instance()->IsRunningOnDXVK || hWnd != Util::GetProcessWindow()) { if (cq != nullptr) @@ -459,9 +384,18 @@ static void Present(IDXGISwapChain* pSwapChain, IUnknown* pDevice, HWND hWnd) if (device12 != nullptr) device12->Release(); - return; + if (pPresentParameters == nullptr) + { + return pSwapChain->Present(SyncInterval, Flags); + } + else + { + auto sc1 = (IDXGISwapChain1*)pSwapChain; + return sc1->Present1(SyncInterval, Flags, pPresentParameters); + } } + // Process window handle changed, update base if (ImGuiOverlayBase::Handle() != hWnd) { LOG_DEBUG("Handle changed"); @@ -472,179 +406,112 @@ static void Present(IDXGISwapChain* pSwapChain, IUnknown* pDevice, HWND hWnd) ImGuiOverlayBase::Init(hWnd); } + // Init if (!_isInited) { if (_dx11Device) { - CleanupRenderTargetDx11(); + CleanupRenderTargetDx11(false); + g_pd3dDevice = device; + g_pd3dDevice->AddRef(); + CreateRenderTargetDx11(pSwapChain); ImGuiOverlayBase::Dx11Ready(); _isInited = true; } - else if (pDevice->QueryInterface(IID_PPV_ARGS(&cq)) == S_OK) + else if (_dx12Device && (g_pd3dDeviceParam != nullptr || device12 != nullptr)) { - LOG_DEBUG("dx12 queue"); + if (g_pd3dDeviceParam != nullptr && device12 == nullptr) + device12 = g_pd3dDeviceParam; - if (cq->GetDevice(IID_PPV_ARGS(&device12)) == S_OK) + CleanupRenderTargetDx12(true); + + g_pd3dCommandQueue = cq; + g_pd3dDeviceParam = device12; + + auto count = g_pd3dCommandQueue->AddRef(); + LOG_DEBUG("D3D12 Queue refcount: {}", count); + + count = g_pd3dDeviceParam->AddRef(); + LOG_DEBUG("D3D12 Device refcount: {}", count); + + ImGuiOverlayBase::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) { - LOG_DEBUG("_dx12Device"); - } - - if (g_pd3dDeviceParam != nullptr || device12 != nullptr) - { - _dx12Device = true; - - if (g_pd3dDeviceParam != nullptr && device12 == nullptr) - device12 = g_pd3dDeviceParam; - - CleanupRenderTargetDx12(true); - g_pd3dCommandQueue = cq; - g_pd3dDeviceParam = device12; - ImGuiOverlayBase::Dx12Ready(); - _isInited = true; + mtState = dx11MultiThread->GetMultithreadProtected(); + dx11MultiThread->SetMultithreadProtected(TRUE); + dx11MultiThread->Enter(); } } } + // Render menu if (_dx11Device) RenderImGui_DX11(pSwapChain); else if (_dx12Device) RenderImGui_DX12(pSwapChain); + + // swapchain present + HRESULT presentResult; + if (pPresentParameters == nullptr) + { + presentResult = pSwapChain->Present(SyncInterval, Flags); + } + else + { + auto sc1 = (IDXGISwapChain1*)pSwapChain; + presentResult = sc1->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; } #pragma endregion -#pragma region Hook for DXGIFactory for Early bindind - -UINT64 lastSwapchainAddress = NULL; - -static HRESULT WINAPI hkCreateSwapChain_EB(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!"); - return oCreateSwapChain_EB(pFactory, pDevice, pDesc, ppSwapChain); - } - - if (pDevice == nullptr) - { - LOG_WARN("pDevice is nullptr!"); - return oCreateSwapChain_EB(pFactory, pDevice, pDesc, ppSwapChain); - } - - auto result = oCreateSwapChain_EB(pFactory, pDevice, pDesc, ppSwapChain); - - if (result == S_OK) - { - // check for SL proxy - IID riid; - 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"); - } - } - - Config::Instance()->ScreenWidth = pDesc->BufferDesc.Width; - Config::Instance()->ScreenHeight = pDesc->BufferDesc.Height; - - LOG_DEBUG("created new swapchain: {0:X}", (UINT64)*ppSwapChain); - - if (lastSwapchainAddress == (UINT64)*ppSwapChain) - LOG_WARN("using same swapchain: {0:X}", lastSwapchainAddress); - - lastSwapchainAddress = (UINT64)*ppSwapChain; - - *ppSwapChain = new WrappedIDXGISwapChain4(*ppSwapChain, pDevice, pDesc->OutputWindow, Present, CleanupRenderTarget); - - LOG_DEBUG("created new WrappedIDXGISwapChain4: {0:X}", (UINT64)*ppSwapChain); - } - - return result; -} - -static HRESULT WINAPI hkCreateSwapChainForHwnd_EB(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!"); - return oCreateSwapChainForHwnd_EB(pCommandQueue, pDevice, hWnd, pDesc, pFullscreenDesc, pRestrictToOutput, ppSwapChain); - } - - if (pDevice == nullptr) - { - LOG_WARN("pDevice is nullptr!"); - return oCreateSwapChainForHwnd_EB(pCommandQueue, pDevice, hWnd, pDesc, pFullscreenDesc, pRestrictToOutput, ppSwapChain); - } - - auto result = oCreateSwapChainForHwnd_EB(pCommandQueue, pDevice, hWnd, pDesc, pFullscreenDesc, pRestrictToOutput, ppSwapChain); - - if (result == S_OK) - { - // check for SL proxy - IID riid; - 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"); - } - } - - Config::Instance()->ScreenWidth = pDesc->Width; - Config::Instance()->ScreenHeight = pDesc->Height; - - LOG_DEBUG("created new swapchain: {0:X}", (UINT64)*ppSwapChain); - - if (lastSwapchainAddress == (UINT64)*ppSwapChain) - LOG_WARN("using same swapchain: {0:X}", lastSwapchainAddress); - - lastSwapchainAddress = (UINT64)*ppSwapChain; - - *ppSwapChain = new WrappedIDXGISwapChain4(*ppSwapChain, pDevice, hWnd, Present, CleanupRenderTarget); - - LOG_DEBUG("created new WrappedIDXGISwapChain4: {0:X}", (UINT64)*ppSwapChain); - } - - return result; -} - -#pragma endregion - -#pragma region Hooks for early binding +#pragma region DXGI hooks static void CheckAdapter(IUnknown* unkAdapter) { @@ -667,46 +534,6 @@ static void CheckAdapter(IUnknown* unkAdapter) adapter->Release(); } -static HRESULT WINAPI detEnumAdapterByGpuPreference(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 WINAPI detEnumAdapterByLuid(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 WINAPI detEnumAdapters1(IDXGIFactory1* This, UINT Adapter, IUnknown** ppAdapter) -{ - auto result = ptrEnumAdapters1(This, Adapter, ppAdapter); - - if (result == S_OK) - CheckAdapter(*ppAdapter); - - return result; -} - -static HRESULT WINAPI detEnumAdapters(IDXGIFactory* This, UINT Adapter, IUnknown** ppAdapter) -{ - auto result = ptrEnumAdapters(This, Adapter, ppAdapter); - - if (result == S_OK) - CheckAdapter(*ppAdapter); - - return result; -} - static void AttachToFactory(IUnknown* unkFactory) { PVOID* pVTable = *(PVOID**)unkFactory; @@ -772,46 +599,135 @@ static void AttachToFactory(IUnknown* unkFactory) } } -static HRESULT WINAPI hkD3D12CreateDevice(IUnknown* pAdapter, D3D_FEATURE_LEVEL MinimumFeatureLevel, REFIID riid, void** ppDevice) +static HRESULT hkCreateSwapChain(IDXGIFactory* pFactory, IUnknown* pDevice, DXGI_SWAP_CHAIN_DESC* pDesc, IDXGISwapChain** ppSwapChain) { - auto result = o_D3D12CreateDevice(pAdapter, MinimumFeatureLevel, riid, ppDevice); + LOG_FUNC(); + + *ppSwapChain = nullptr; + + if (Config::Instance()->VulkanCreatingSC) + { + LOG_WARN("Vulkan is creating swapchain!"); + 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) { - LOG_DEBUG("_dx12device"); - g_pd3dDeviceParam = (ID3D12Device*)*ppDevice; - HookToDevice(g_pd3dDeviceParam); + // 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"); + } + } + + Config::Instance()->ScreenWidth = pDesc->BufferDesc.Width; + Config::Instance()->ScreenHeight = pDesc->BufferDesc.Height; + + LOG_DEBUG("created new swapchain: {0:X}, hWnd", (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 WINAPI hkCreateDXGIFactory(REFIID riid, void** ppFactory) +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) { - auto result = o_CreateDXGIFactory1(riid, ppFactory); + LOG_FUNC(); + + *ppSwapChain = nullptr; + + if (Config::Instance()->VulkanCreatingSC) + { + LOG_WARN("Vulkan is creating swapchain!"); + 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) { - auto factory = (IDXGIFactory*)*ppFactory; - AttachToFactory(factory); + // 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"); + } + } + + Config::Instance()->ScreenWidth = pDesc->Width; + Config::Instance()->ScreenHeight = pDesc->Height; + + LOG_DEBUG("created new swapchain: {0:X}", (UINT64)*ppSwapChain); + *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); } - if (result == S_OK && oCreateSwapChain_EB == nullptr) + 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) { - auto factory = (IDXGIFactory*)*ppFactory; + void** pFactoryVTable = *reinterpret_cast(*ppFactory); - void** pFactoryVTable = *reinterpret_cast(factory); + oCreateSwapChain = (PFN_CreateSwapChain)pFactoryVTable[10]; - oCreateSwapChain_EB = (PFN_CreateSwapChain)pFactoryVTable[10]; - - if (oCreateSwapChain_EB != nullptr) + if (oCreateSwapChain != nullptr) { LOG_INFO("Hooking native DXGIFactory"); DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); - DetourAttach(&(PVOID&)oCreateSwapChain_EB, hkCreateSwapChain_EB); + DetourAttach(&(PVOID&)oCreateSwapChain, hkCreateSwapChain); DetourTransactionCommit(); } @@ -820,35 +736,31 @@ static HRESULT WINAPI hkCreateDXGIFactory(REFIID riid, void** ppFactory) return result; } -static HRESULT WINAPI hkCreateDXGIFactory1(REFIID riid, void** ppFactory) +static HRESULT hkCreateDXGIFactory1(REFIID riid, IDXGIFactory1** ppFactory) { auto result = o_CreateDXGIFactory1(riid, ppFactory); if (result == S_OK) - { - auto factory = (IDXGIFactory*)*ppFactory; - AttachToFactory(factory); - } + AttachToFactory(*ppFactory); - if (result == S_OK && oCreateSwapChainForHwnd_EB == nullptr) + if (result == S_OK && oCreateSwapChainForHwnd == nullptr) { - auto factory = (IDXGIFactory*)*ppFactory; IDXGIFactory2* factory2 = nullptr; - if (factory->QueryInterface(IID_PPV_ARGS(&factory2)) == S_OK) + if ((*ppFactory)->QueryInterface(IID_PPV_ARGS(&factory2)) == S_OK && factory2 != nullptr) { void** pFactoryVTable = *reinterpret_cast(factory2); bool skip = false; - if (oCreateSwapChain_EB == nullptr) - oCreateSwapChain_EB = (PFN_CreateSwapChain)pFactoryVTable[10]; + if (oCreateSwapChain == nullptr) + oCreateSwapChain = (PFN_CreateSwapChain)pFactoryVTable[10]; else skip = true; - oCreateSwapChainForHwnd_EB = (PFN_CreateSwapChainForHwnd)pFactoryVTable[15]; + oCreateSwapChainForHwnd = (PFN_CreateSwapChainForHwnd)pFactoryVTable[15]; - if (oCreateSwapChainForHwnd_EB != nullptr) + if (oCreateSwapChainForHwnd != nullptr) { LOG_INFO("Hooking native DXGIFactory"); @@ -856,9 +768,9 @@ static HRESULT WINAPI hkCreateDXGIFactory1(REFIID riid, void** ppFactory) DetourUpdateThread(GetCurrentThread()); if (!skip) - DetourAttach(&(PVOID&)oCreateSwapChain_EB, hkCreateSwapChain_EB); + DetourAttach(&(PVOID&)oCreateSwapChain, hkCreateSwapChain); - DetourAttach(&(PVOID&)oCreateSwapChainForHwnd_EB, hkCreateSwapChainForHwnd_EB); + DetourAttach(&(PVOID&)oCreateSwapChainForHwnd, hkCreateSwapChainForHwnd); DetourTransactionCommit(); } @@ -871,35 +783,31 @@ static HRESULT WINAPI hkCreateDXGIFactory1(REFIID riid, void** ppFactory) return result; } -static HRESULT WINAPI hkCreateDXGIFactory2(UINT Flags, REFIID riid, _COM_Outptr_ void** ppFactory) +static HRESULT hkCreateDXGIFactory2(UINT Flags, REFIID riid, IDXGIFactory2** ppFactory) { auto result = o_CreateDXGIFactory2(Flags, riid, ppFactory); if (result == S_OK) - { - auto factory = (IDXGIFactory*)*ppFactory; - AttachToFactory(factory); - } + AttachToFactory(*ppFactory); - if (result == S_OK && oCreateSwapChainForHwnd_EB == nullptr) + if (result == S_OK && oCreateSwapChainForHwnd == nullptr) { - auto factory = (IDXGIFactory*)*ppFactory; IDXGIFactory2* factory2 = nullptr; - if (factory->QueryInterface(IID_PPV_ARGS(&factory2)) == S_OK) + if ((*ppFactory)->QueryInterface(IID_PPV_ARGS(&factory2)) == S_OK && factory2 != nullptr) { void** pFactoryVTable = *reinterpret_cast(factory2); bool skip = false; - if (oCreateSwapChain_EB == nullptr) - oCreateSwapChain_EB = (PFN_CreateSwapChain)pFactoryVTable[10]; + if (oCreateSwapChain == nullptr) + oCreateSwapChain = (PFN_CreateSwapChain)pFactoryVTable[10]; else skip = true; - oCreateSwapChainForHwnd_EB = (PFN_CreateSwapChainForHwnd)pFactoryVTable[15]; + oCreateSwapChainForHwnd = (PFN_CreateSwapChainForHwnd)pFactoryVTable[15]; - if (oCreateSwapChainForHwnd_EB != nullptr) + if (oCreateSwapChainForHwnd != nullptr) { LOG_INFO("Hooking native DXGIFactory"); @@ -907,9 +815,9 @@ static HRESULT WINAPI hkCreateDXGIFactory2(UINT Flags, REFIID riid, _COM_Outptr_ DetourUpdateThread(GetCurrentThread()); if (!skip) - DetourAttach(&(PVOID&)oCreateSwapChain_EB, hkCreateSwapChain_EB); + DetourAttach(&(PVOID&)oCreateSwapChain, hkCreateSwapChain); - DetourAttach(&(PVOID&)oCreateSwapChainForHwnd_EB, hkCreateSwapChainForHwnd_EB); + DetourAttach(&(PVOID&)oCreateSwapChainForHwnd, hkCreateSwapChainForHwnd); DetourTransactionCommit(); } @@ -922,18 +830,335 @@ static HRESULT WINAPI hkCreateDXGIFactory2(UINT Flags, REFIID riid, _COM_Outptr_ return result; } +static HRESULT detEnumAdapterByGpuPreference(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 detEnumAdapterByLuid(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 detEnumAdapters1(IDXGIFactory1* This, UINT Adapter, IUnknown** ppAdapter) +{ + auto result = ptrEnumAdapters1(This, Adapter, ppAdapter); + + if (result == S_OK) + CheckAdapter(*ppAdapter); + + return result; +} + +static HRESULT detEnumAdapters(IDXGIFactory* This, UINT Adapter, IUnknown** ppAdapter) +{ + auto result = ptrEnumAdapters(This, Adapter, ppAdapter); + + if (result == S_OK) + CheckAdapter(*ppAdapter); + + return result; +} + #pragma endregion -static void RenderImGui_DX12(IDXGISwapChain* pSwapChainPlain) +#pragma region DirectX hooks + +static void HookToDevice(ID3D12Device* InDevice) +{ + if (o_CreateSampler != nullptr || InDevice == nullptr) + return; + + LOG_FUNC(); + + // Get the vtable pointer + PVOID* pVTable = *(PVOID**)InDevice; + + o_CreateSampler = (PFN_CreateSampler)pVTable[22]; + + // Apply the detour + if (o_CreateSampler != nullptr) + { + DetourTransactionBegin(); + DetourUpdateThread(GetCurrentThread()); + + DetourAttach(&(PVOID&)o_CreateSampler, hkCreateSampler); + + DetourTransactionCommit(); + } +} + +static void HookToDevice(ID3D11Device* InDevice) +{ + if (o_CreateSamplerState != nullptr || InDevice == nullptr) + return; + + LOG_FUNC(); + + // Get the vtable pointer + PVOID* pVTable = *(PVOID**)InDevice; + + o_CreateSamplerState = (PFN_CreateSamplerState)pVTable[23]; + + // Apply the detour + if (o_CreateSamplerState != nullptr) + { + DetourTransactionBegin(); + DetourUpdateThread(GetCurrentThread()); + + DetourAttach(&(PVOID&)o_CreateSamplerState, hkCreateSamplerState); + + DetourTransactionCommit(); + } +} + +static HRESULT hkD3D11On12CreateDevice(IUnknown* pDevice, UINT Flags, D3D_FEATURE_LEVEL* pFeatureLevels, UINT FeatureLevels, IUnknown** ppCommandQueues, + UINT NumQueues, UINT NodeMask, ID3D11Device** ppDevice, ID3D11DeviceContext** ppImmediateContext, D3D_FEATURE_LEVEL* pChosenFeatureLevel) { LOG_FUNC(); + // Assuming RTSS is creating a D3D11on12 device, not sure why but sometimes RTSS tries to create + // it's D3D11on12 device with old CommandQueue which results crash + // I am changing it's CommandQueue with current swapchain's command queue + if (currentSCCommandQueue != nullptr && *ppCommandQueues != currentSCCommandQueue && GetModuleHandle(L"RTSSHooks64.dll") != nullptr) + { + LOG_INFO("Replaced RTSS CommandQueue with correct one {0:X} -> {1:X}", (UINT64)*ppCommandQueues, (UINT64)currentSCCommandQueue); + *ppCommandQueues = currentSCCommandQueue; + } + + auto result = o_D3D11On12CreateDevice(pDevice, Flags, pFeatureLevels, FeatureLevels, ppCommandQueues, NumQueues, NodeMask, ppDevice, ppImmediateContext, pChosenFeatureLevel); + + if (result == S_OK && *ppDevice != nullptr) + { + LOG_INFO("Device captured, CommandQueue: {0:X}", (UINT64)*ppCommandQueues); + d3d11on12Device = *ppDevice; + d3d11on12Device->AddRef(); + + HookToDevice(d3d11on12Device); + } + + LOG_FUNC_RESULT(result); + + return result; +} + +static HRESULT hkD3D11CreateDevice(IDXGIAdapter* pAdapter, D3D_DRIVER_TYPE DriverType, HMODULE Software, UINT Flags, CONST D3D_FEATURE_LEVEL* pFeatureLevels, + UINT FeatureLevels, UINT SDKVersion, ID3D11Device** ppDevice, D3D_FEATURE_LEVEL* pFeatureLevel, ID3D11DeviceContext** ppImmediateContext) +{ + LOG_FUNC(); + + auto result = o_D3D11CreateDevice(pAdapter, DriverType, Software, Flags, pFeatureLevels, FeatureLevels, SDKVersion, ppDevice, pFeatureLevel, ppImmediateContext); + + if (result == S_OK && *ppDevice != nullptr) + { + LOG_INFO("Device captured"); + d3d11Device = *ppDevice; + + HookToDevice(d3d11Device); + } + + LOG_FUNC_RESULT(result); + + return result; +} + +static HRESULT hkD3D12CreateDevice(IUnknown* pAdapter, D3D_FEATURE_LEVEL MinimumFeatureLevel, REFIID riid, void** ppDevice) +{ + LOG_FUNC(); + + auto result = o_D3D12CreateDevice(pAdapter, MinimumFeatureLevel, riid, ppDevice); + + if (result == S_OK) + { + LOG_INFO("Device captured"); + g_pd3dDeviceParam = (ID3D12Device*)*ppDevice; + HookToDevice(g_pd3dDeviceParam); + } + + LOG_FUNC_RESULT(result); + + return result; +} + +static void hkCreateSampler(ID3D12Device* device, const D3D12_SAMPLER_DESC* pDesc, D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor) +{ + if (pDesc == nullptr || device == nullptr) + return; + + D3D12_SAMPLER_DESC newDesc{}; + + newDesc.AddressU = pDesc->AddressU; + newDesc.AddressV = pDesc->AddressV; + newDesc.AddressW = pDesc->AddressW; + newDesc.BorderColor[0] = pDesc->BorderColor[0]; + newDesc.BorderColor[1] = pDesc->BorderColor[1]; + newDesc.BorderColor[2] = pDesc->BorderColor[2]; + newDesc.BorderColor[3] = pDesc->BorderColor[3]; + newDesc.ComparisonFunc = pDesc->ComparisonFunc; + + if (Config::Instance()->AnisotropyOverride.has_value() && + (pDesc->Filter == D3D12_FILTER_MIN_LINEAR_MAG_MIP_POINT || + pDesc->Filter == D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT || + pDesc->Filter == D3D12_FILTER_MIN_MAG_MIP_LINEAR || + pDesc->Filter == D3D12_FILTER_ANISOTROPIC)) + { + LOG_INFO("Overriding Anisotrpic ({2}) filtering {0} -> {1}", pDesc->MaxAnisotropy, Config::Instance()->AnisotropyOverride.value(), (UINT)pDesc->Filter); + newDesc.Filter = D3D12_FILTER_ANISOTROPIC; + newDesc.MaxAnisotropy = Config::Instance()->AnisotropyOverride.value(); + } + else + { + newDesc.Filter = pDesc->Filter; + newDesc.MaxAnisotropy = pDesc->MaxAnisotropy; + } + + newDesc.MaxLOD = pDesc->MaxLOD; + newDesc.MinLOD = pDesc->MinLOD; + newDesc.MipLODBias = pDesc->MipLODBias; + + if (newDesc.MipLODBias < 0.0f) + { + if (Config::Instance()->MipmapBiasOverride.has_value()) + { + LOG_INFO("Overriding mipmap bias {0} -> {1}", pDesc->MipLODBias, Config::Instance()->MipmapBiasOverride.value()); + newDesc.MipLODBias = Config::Instance()->MipmapBiasOverride.value(); + } + + Config::Instance()->lastMipBias = newDesc.MipLODBias; + } + + return o_CreateSampler(device, &newDesc, DestDescriptor); +} + +static HRESULT hkCreateSamplerState(ID3D11Device* This, const D3D11_SAMPLER_DESC* pSamplerDesc, ID3D11SamplerState** ppSamplerState) +{ + if (pSamplerDesc == nullptr || This == nullptr) + return E_INVALIDARG; + + LOG_FUNC(); + + D3D11_SAMPLER_DESC newDesc{}; + + newDesc.AddressU = pSamplerDesc->AddressU; + newDesc.AddressV = pSamplerDesc->AddressV; + newDesc.AddressW = pSamplerDesc->AddressW; + newDesc.ComparisonFunc = pSamplerDesc->ComparisonFunc; + newDesc.BorderColor[0] = pSamplerDesc->BorderColor[0]; + newDesc.BorderColor[1] = pSamplerDesc->BorderColor[1]; + newDesc.BorderColor[2] = pSamplerDesc->BorderColor[2]; + newDesc.BorderColor[3] = pSamplerDesc->BorderColor[3]; + newDesc.MinLOD = pSamplerDesc->MinLOD; + newDesc.MaxLOD = pSamplerDesc->MaxLOD; + + if (Config::Instance()->AnisotropyOverride.has_value() && + (pSamplerDesc->Filter == D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT || + pSamplerDesc->Filter == D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT || + pSamplerDesc->Filter == D3D11_FILTER_MIN_MAG_MIP_LINEAR || + pSamplerDesc->Filter == D3D11_FILTER_ANISOTROPIC)) + { + LOG_INFO("Overriding Anisotrpic ({2}) filtering {0} -> {1}", pSamplerDesc->MaxAnisotropy, Config::Instance()->AnisotropyOverride.value(), (UINT)pSamplerDesc->Filter); + newDesc.Filter = D3D11_FILTER_ANISOTROPIC; + newDesc.MaxAnisotropy = Config::Instance()->AnisotropyOverride.value(); + } + else + { + newDesc.Filter = pSamplerDesc->Filter; + newDesc.MaxAnisotropy = pSamplerDesc->MaxAnisotropy; + } + + newDesc.MipLODBias = pSamplerDesc->MipLODBias; + + if (newDesc.MipLODBias < 0.0f) + { + if (Config::Instance()->MipmapBiasOverride.has_value()) + { + LOG_INFO("Overriding mipmap bias {0} -> {1}", pSamplerDesc->MipLODBias, Config::Instance()->MipmapBiasOverride.value()); + newDesc.MipLODBias = Config::Instance()->MipmapBiasOverride.value(); + } + + Config::Instance()->lastMipBias = newDesc.MipLODBias; + } + + return o_CreateSamplerState(This, &newDesc, ppSamplerState); +} + +#pragma endregion + +static void RenderImGui_DX11(IDXGISwapChain* pSwapChain) +{ + bool drawMenu = false; + + do + { + if (!ImGuiOverlayBase::IsInited()) + break; + + // Draw only when menu activated + if (!ImGuiOverlayBase::IsVisible()) + break; + + if (!_dx11Device || g_pd3dDevice == nullptr) + break; + + drawMenu = true; + + } while (false); + + if (!drawMenu) + { + ImGuiOverlayBase::HideMenu(); + return; + } + + LOG_FUNC(); + + if (ImGui::GetIO().BackendRendererUserData == nullptr) + { + if (pSwapChain->GetDevice(IID_PPV_ARGS(&g_pd3dDevice)) == S_OK) + { + g_pd3dDevice->GetImmediateContext(&g_pd3dDeviceContext); + ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext); + } + } + + if (_isInited) + { + if (!g_pd3dRenderTarget) + CreateRenderTargetDx11(pSwapChain); + + if (ImGui::GetCurrentContext() && g_pd3dRenderTarget) + { + ImGui_ImplDX11_NewFrame(); + ImGui_ImplWin32_NewFrame(); + + ImGuiOverlayBase::RenderMenu(); + + ImGui::Render(); + + g_pd3dDeviceContext->OMSetRenderTargets(1, &g_pd3dRenderTarget, NULL); + ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); + } + } +} + +static void RenderImGui_DX12(IDXGISwapChain* pSwapChainPlain) +{ bool drawMenu = false; IDXGISwapChain3* pSwapChain = nullptr; do { - if (pSwapChainPlain->QueryInterface(IID_PPV_ARGS(&pSwapChain)) != S_OK) + if (pSwapChainPlain->QueryInterface(IID_PPV_ARGS(&pSwapChain)) != S_OK || pSwapChain == nullptr) return; if (!ImGuiOverlayBase::IsInited()) @@ -957,7 +1182,7 @@ static void RenderImGui_DX12(IDXGISwapChain* pSwapChainPlain) return; } - LOG_DEBUG("start drawing"); + LOG_FUNC(); // Get device from swapchain ID3D12Device* device = g_pd3dDeviceParam; @@ -1126,6 +1351,7 @@ static void RenderImGui_DX12(IDXGISwapChain* pSwapChainPlain) ID3D12CommandList* ppCommandLists[] = { g_pd3dCommandList }; g_pd3dCommandQueue->ExecuteCommandLists(1, ppCommandLists); + } else { @@ -1140,70 +1366,23 @@ static void RenderImGui_DX12(IDXGISwapChain* pSwapChainPlain) pSwapChain->Release(); } -static void RenderImGui_DX11(IDXGISwapChain* pSwapChain) -{ - LOG_FUNC(); - - bool drawMenu = false; - - do - { - if (!ImGuiOverlayBase::IsInited()) - break; - - // Draw only when menu activated - if (!ImGuiOverlayBase::IsVisible()) - break; - - if (!_dx11Device || g_pd3dDevice == nullptr) - break; - - drawMenu = true; - - } while (false); - - if (!drawMenu) - { - ImGuiOverlayBase::HideMenu(); - return; - } - - LOG_DEBUG("start drawing"); - - if (ImGui::GetIO().BackendRendererUserData == nullptr) - { - if (pSwapChain->GetDevice(IID_PPV_ARGS(&g_pd3dDevice)) == S_OK) - { - g_pd3dDevice->GetImmediateContext(&g_pd3dDeviceContext); - ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext); - } - } - - if (_isInited) - { - if (!g_pd3dRenderTarget) - CreateRenderTargetDx11(pSwapChain); - - if (ImGui::GetCurrentContext() && g_pd3dRenderTarget) - { - ImGui_ImplDX11_NewFrame(); - ImGui_ImplWin32_NewFrame(); - - ImGuiOverlayBase::RenderMenu(); - - ImGui::Render(); - - g_pd3dDeviceContext->OMSetRenderTargets(1, &g_pd3dRenderTarget, NULL); - ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); - } - } -} - void DeatachAllHooks() { DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); + if (o_D3D11CreateDevice != nullptr) + { + DetourDetach(&(PVOID&)o_D3D11CreateDevice, hkD3D11CreateDevice); + o_D3D11CreateDevice = nullptr; + } + + if (o_D3D11On12CreateDevice != nullptr) + { + DetourDetach(&(PVOID&)o_D3D11On12CreateDevice, hkD3D11On12CreateDevice); + o_D3D11CreateDevice = nullptr; + } + if (o_D3D12CreateDevice != nullptr) { DetourDetach(&(PVOID&)o_D3D12CreateDevice, hkD3D12CreateDevice); @@ -1222,16 +1401,16 @@ void DeatachAllHooks() o_CreateDXGIFactory2 = nullptr; } - if (oCreateSwapChain_EB != nullptr) + if (oCreateSwapChain != nullptr) { - DetourDetach(&(PVOID&)oCreateSwapChain_EB, hkCreateSwapChain_EB); - oCreateSwapChain_EB = nullptr; + DetourDetach(&(PVOID&)oCreateSwapChain, hkCreateSwapChain); + oCreateSwapChain = nullptr; } - if (oCreateSwapChainForHwnd_EB != nullptr) + if (oCreateSwapChainForHwnd != nullptr) { - DetourDetach(&(PVOID&)oCreateSwapChainForHwnd_EB, hkCreateSwapChainForHwnd_EB); - oCreateSwapChainForHwnd_EB = nullptr; + DetourDetach(&(PVOID&)oCreateSwapChainForHwnd, hkCreateSwapChainForHwnd); + oCreateSwapChainForHwnd = nullptr; } if (o_CreateSampler != nullptr) @@ -1249,7 +1428,6 @@ void ImGuiOverlayDx::HookDx() return; o_D3D12CreateDevice = (PFN_D3D12_CREATE_DEVICE)DetourFindFunction("d3d12.dll", "D3D12CreateDevice"); - if (o_D3D12CreateDevice != nullptr) { DetourTransactionBegin(); @@ -1260,6 +1438,22 @@ void ImGuiOverlayDx::HookDx() DetourTransactionCommit(); } + o_D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)DetourFindFunction("d3d11.dll", "D3D11CreateDevice"); + o_D3D11On12CreateDevice = (PFN_D3D11ON12_CREATE_DEVICE)DetourFindFunction("d3d11.dll", "D3D11On12CreateDevice"); + if (o_D3D11CreateDevice != nullptr || o_D3D11On12CreateDevice != nullptr) + { + DetourTransactionBegin(); + DetourUpdateThread(GetCurrentThread()); + + if (o_D3D11CreateDevice != nullptr) + DetourAttach(&(PVOID&)o_D3D11CreateDevice, hkD3D11CreateDevice); + + if (o_D3D11On12CreateDevice != nullptr) + DetourAttach(&(PVOID&)o_D3D11On12CreateDevice, hkD3D11On12CreateDevice); + + DetourTransactionCommit(); + } + o_CreateDXGIFactory = (PFN_CreateDXGIFactory)DetourFindFunction("dxgi.dll", "CreateDXGIFactory"); o_CreateDXGIFactory1 = (PFN_CreateDXGIFactory1)DetourFindFunction("dxgi.dll", "CreateDXGIFactory1"); o_CreateDXGIFactory2 = (PFN_CreateDXGIFactory2)DetourFindFunction("dxgi.dll", "CreateDXGIFactory2"); @@ -1299,7 +1493,7 @@ void ImGuiOverlayDx::UnHookDx() if (_isInited) { if (_dx11Device) - CleanupRenderTargetDx11(); + CleanupRenderTargetDx11(true); else CleanupRenderTargetDx12(true); }