diff --git a/OptiScaler/SysUtils.h b/OptiScaler/SysUtils.h index 7c64f077..52518a07 100644 --- a/OptiScaler/SysUtils.h +++ b/OptiScaler/SysUtils.h @@ -51,6 +51,9 @@ // Enable D3D11 Debug Layers // #define ENABLE_DEBUG_LAYER_DX11 +// Enable DXGI Debug Layers +// #define DXGI_DEBUG_ENABLED + #ifdef ENABLE_DEBUG_LAYER_DX12 // Enable GPUValidation // #define ENABLE_GPU_VALIDATION diff --git a/OptiScaler/hooks/Dxgi_Hooks.cpp b/OptiScaler/hooks/Dxgi_Hooks.cpp index fcee1d5a..b2c54ad6 100644 --- a/OptiScaler/hooks/Dxgi_Hooks.cpp +++ b/OptiScaler/hooks/Dxgi_Hooks.cpp @@ -113,7 +113,7 @@ inline static HRESULT hkCreateDXGIFactory(REFIID riid, IDXGIFactory** ppFactory) HRESULT result; auto owner = State::GetOwner(); State::DisableChecks(owner, "dxgi"); -#ifndef ENABLE_DEBUG_LAYER_DX12 +#ifndef DXGI_DEBUG_ENABLED result = o_CreateDXGIFactory(riid, ppFactory); #else result = o_CreateDXGIFactory2(DXGI_CREATE_FACTORY_DEBUG, riid, (IDXGIFactory2**) ppFactory); @@ -173,7 +173,7 @@ inline static HRESULT hkCreateDXGIFactory1(REFIID riid, IDXGIFactory1** ppFactor HRESULT result; auto owner = State::GetOwner(); State::DisableChecks(owner, "dxgi"); -#ifndef ENABLE_DEBUG_LAYER_DX12 +#ifndef DXGI_DEBUG_ENABLED result = o_CreateDXGIFactory1(riid, ppFactory); #else result = o_CreateDXGIFactory2(DXGI_CREATE_FACTORY_DEBUG, riid, (IDXGIFactory2**) ppFactory); @@ -234,7 +234,7 @@ inline static HRESULT hkCreateDXGIFactory2(UINT Flags, REFIID riid, IDXGIFactory HRESULT result; auto owner = State::GetOwner(); State::DisableChecks(owner, "dxgi"); -#ifndef ENABLE_DEBUG_LAYER_DX12 +#ifndef DXGI_DEBUG_ENABLED result = o_CreateDXGIFactory2(Flags, riid, ppFactory); #else result = o_CreateDXGIFactory2(DXGI_CREATE_FACTORY_DEBUG, riid, (IDXGIFactory2**) ppFactory); diff --git a/OptiScaler/wrapped/wrapped_swapchain.cpp b/OptiScaler/wrapped/wrapped_swapchain.cpp index 75c9b9e7..b1f80f56 100644 --- a/OptiScaler/wrapped/wrapped_swapchain.cpp +++ b/OptiScaler/wrapped/wrapped_swapchain.cpp @@ -19,6 +19,17 @@ #include #include +#ifdef DXGI_DEBUG_ENABLED +#include +#include + +#pragma comment(lib, "dxguid.lib") + +#ifdef ENABLE_DEBUG_LAYER_DX12 +#include +#endif +#endif + #pragma intrinsic(_ReturnAddress) // Used RenderDoc's wrapped object as referance @@ -85,6 +96,54 @@ static void WaitForGPUIdle(IUnknown* object) } } } + +#ifdef DXGI_DEBUG_ENABLED +void ReportDXGILiveObjects() +{ + IDXGIDebug1* dxgiDebug = nullptr; + + if (SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(&dxgiDebug)))) + { + dxgiDebug->ReportLiveObjects(DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_ALL); + dxgiDebug->Release(); + } +} + +void ReadDxgiInfoQueue() +{ + IDXGIInfoQueue* dxgiInfoQueue = nullptr; + if (DXGIGetDebugInterface1(0, IID_PPV_ARGS(&dxgiInfoQueue)) == S_OK) + { + UINT64 msgCount = dxgiInfoQueue->GetNumStoredMessages(DXGI_DEBUG_ALL); + for (UINT64 i = 0; i < msgCount; ++i) + { + SIZE_T msgLen = 0; + dxgiInfoQueue->GetMessage(DXGI_DEBUG_ALL, i, nullptr, &msgLen); + std::vector buf(msgLen); + auto* msg = reinterpret_cast(buf.data()); + dxgiInfoQueue->GetMessage(DXGI_DEBUG_ALL, i, msg, &msgLen); + + auto description = std::string(msg->pDescription, msg->DescriptionByteLength); + LOG_DEBUG("DXGI Debug Message: Category: {}, Severity: {}, ID: {}, Description: {}", + magic_enum::enum_name(msg->Category), magic_enum::enum_name(msg->Severity), msg->ID, description); + } + } +} + +#ifdef ENABLE_DEBUG_LAYER_DX12 +void ReportD3D12LiveObjects(ID3D12Device* device) +{ + ID3D12DebugDevice* debugDevice = nullptr; + + if (SUCCEEDED(device->QueryInterface(IID_PPV_ARGS(&debugDevice)))) + { + debugDevice->ReportLiveDeviceObjects(D3D12_RLDO_DETAIL | D3D12_RLDO_IGNORE_INTERNAL); + debugDevice->Release(); + } +} +#endif +#endif + static HRESULT LocalPresent(IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags, const DXGI_PRESENT_PARAMETERS* pPresentParameters, IUnknown* pDevice, HWND hWnd, bool isUWP) { @@ -485,13 +544,13 @@ ULONG STDMETHODCALLTYPE WrappedIDXGISwapChain4::Release() } else { - // Release real swapchain, otherwise it can cause issues when re-creating swapchain with same handle - while (refCount > 0) - { - LOG_DEBUG("Waiting for real swapchain to be released, refCount: {}", refCount); - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - refCount = _real->Release(); - } + // Release real swapchain, otherwise it can cause issues when re-creating swapchain with same handle + while (refCount > 0) + { + LOG_DEBUG("Waiting for real swapchain to be released, refCount: {}", refCount); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + refCount = _real->Release(); + } } LOG_DEBUG("Real swapchain released, refCount: {}", refCount); @@ -726,6 +785,15 @@ HRESULT STDMETHODCALLTYPE WrappedIDXGISwapChain4::ResizeBuffers(UINT BufferCount std::this_thread::sleep_for(std::chrono::milliseconds(100)); } + +#ifdef DXGI_DEBUG_ENABLED + ReportDXGILiveObjects(); + +#ifdef ENABLE_DEBUG_LAYER_DX12 + ReportD3D12LiveObjects(State::Instance().currentD3D12Device); +#endif +#endif + if (Config::Instance()->FGDontUseSwapchainBuffers.value_or_default()) { ScopedSkipHeapCapture skipHeapCapture {}; @@ -739,6 +807,11 @@ HRESULT STDMETHODCALLTYPE WrappedIDXGISwapChain4::ResizeBuffers(UINT BufferCount result = _real->ResizeBuffers(BufferCount, Width, Height, NewFormat, SwapChainFlags); } +#ifdef DXGI_DEBUG_ENABLED + if (result != S_OK) + ReadDxgiInfoQueue(); +#endif + if (result == S_OK && State::Instance().currentFeature == nullptr) { State::Instance().screenWidth = static_cast(Width); @@ -1009,7 +1082,7 @@ HRESULT STDMETHODCALLTYPE WrappedIDXGISwapChain4::ResizeBuffers1(UINT BufferCoun LOG_TRACE("Accuired ffxMutex: {}", State::Instance().currentFG->Mutex.getOwner()); } - HRESULT result; + HRESULT result = E_FAIL; DXGI_SWAP_CHAIN_DESC desc {}; _real->GetDesc(&desc); @@ -1052,6 +1125,14 @@ HRESULT STDMETHODCALLTYPE WrappedIDXGISwapChain4::ResizeBuffers1(UINT BufferCoun LOG_DEBUG( "Found SK swapchain, skip releasing backbuffersand using ResizeBuffers instead of ResizeBuffers1"); +#ifdef DXGI_DEBUG_ENABLED + ReportDXGILiveObjects(); + +#ifdef ENABLE_DEBUG_LAYER_DX12 + ReportD3D12LiveObjects(State::Instance().currentD3D12Device); +#endif +#endif + if (Config::Instance()->FGDontUseSwapchainBuffers.value_or_default()) { ScopedSkipHeapCapture skipHeapCapture {}; @@ -1099,22 +1180,36 @@ HRESULT STDMETHODCALLTYPE WrappedIDXGISwapChain4::ResizeBuffers1(UINT BufferCoun } std::this_thread::sleep_for(std::chrono::milliseconds(100)); - if (Config::Instance()->FGDontUseSwapchainBuffers.value_or_default()) - { - ScopedSkipHeapCapture skipHeapCapture {}; - _lastFlags = SwapChainFlags; - result = _real3->ResizeBuffers1(BufferCount, Width, Height, Format, SwapChainFlags, pCreationNodeMask, - ppPresentQueue); - } - else - { - _lastFlags = SwapChainFlags; - result = _real3->ResizeBuffers1(BufferCount, Width, Height, Format, SwapChainFlags, pCreationNodeMask, - ppPresentQueue); - } +#ifdef DXGI_DEBUG_ENABLED + ReportDXGILiveObjects(); + +#ifdef ENABLE_DEBUG_LAYER_DX12 + ReportD3D12LiveObjects(State::Instance().currentD3D12Device); +#endif +#endif + + if (Config::Instance()->FGDontUseSwapchainBuffers.value_or_default()) + { + ScopedSkipHeapCapture skipHeapCapture {}; + + _lastFlags = SwapChainFlags; + result = _real3->ResizeBuffers1(BufferCount, Width, Height, Format, SwapChainFlags, pCreationNodeMask, + ppPresentQueue); + } + else + { + _lastFlags = SwapChainFlags; + result = _real3->ResizeBuffers1(BufferCount, Width, Height, Format, SwapChainFlags, pCreationNodeMask, + ppPresentQueue); + } } +#ifdef DXGI_DEBUG_ENABLED + if (result != S_OK) + ReadDxgiInfoQueue(); +#endif + if (result == S_OK && State::Instance().currentFeature == nullptr) { State::Instance().screenWidth = static_cast(Width);