From 30fe868ea23a2ddc7d9417f6956820e6b46d1833 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Wed, 7 Feb 2024 08:02:49 -0600 Subject: [PATCH] Add DXGIDebug logic to help track memory leaks, fix SRV leak it discovered --- src/Refresh_Driver_D3D11.c | 76 +++++++++++++++++++++++++++++ src/Refresh_Driver_D3D11_cdefines.h | 6 ++- 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index fcb3231..602ce10 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -29,10 +29,12 @@ #define D3D11_NO_HELPERS #define CINTERFACE #define COBJMACROS + #include #include #include #include +#include #include #include "Refresh_Driver.h" @@ -45,9 +47,11 @@ #define D3D11_DLL "d3d11.dll" #define DXGI_DLL "dxgi.dll" +#define DXGIDEBUG_DLL "dxgidebug.dll" #define D3D11_CREATE_DEVICE_FUNC "D3D11CreateDevice" #define D3DCOMPILE_FUNC "D3DCompile" #define CREATE_DXGI_FACTORY1_FUNC "CreateDXGIFactory1" +#define DXGI_GET_DEBUG_INTERFACE_FUNC "DXGIGetDebugInterface" #define WINDOW_DATA "Refresh_D3D11WindowData" #define UBO_BUFFER_SIZE 16000 /* 16KB */ @@ -463,8 +467,11 @@ typedef struct D3D11Renderer ID3D11DeviceContext *immediateContext; IDXGIFactory1 *factory; IDXGIAdapter1 *adapter; + IDXGIDebug *dxgiDebug; + IDXGIInfoQueue *dxgiInfoQueue; void *d3d11_dll; void *dxgi_dll; + void *dxgidebug_dll; void *d3dcompiler_dll; uint8_t debugMode; @@ -612,9 +619,25 @@ static void D3D11_DestroyDevice( IDXGIAdapter_Release(renderer->adapter); IDXGIFactory_Release(renderer->factory); + /* Report leaks and clean up debug objects */ + if (renderer->dxgiDebug) + { + IDXGIDebug_ReportLiveObjects(renderer->dxgiDebug, D3D_IID_DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_ALL); + IDXGIDebug_Release(renderer->dxgiDebug); + } + + if (renderer->dxgiInfoQueue) + { + IDXGIInfoQueue_Release(renderer->dxgiInfoQueue); + } + /* Release the DLLs */ SDL_UnloadObject(renderer->d3d11_dll); SDL_UnloadObject(renderer->dxgi_dll); + if (renderer->dxgidebug_dll) + { + SDL_UnloadObject(renderer->dxgidebug_dll); + } SDL_UnloadObject(renderer->d3dcompiler_dll); /* Free the primary Refresh structures */ @@ -1842,7 +1865,18 @@ static void D3D11_QueueDestroyTexture( Refresh_Texture *texture ) { D3D11Texture *d3d11Texture = (D3D11Texture*) texture; + + if (d3d11Texture->shaderView) + { + ID3D11ShaderResourceView_Release(d3d11Texture->shaderView); + } + if (d3d11Texture->targetView) + { + ID3D11View_Release(d3d11Texture->targetView); + } + ID3D11Resource_Release(d3d11Texture->handle); + SDL_free(d3d11Texture); } @@ -3052,6 +3086,42 @@ static uint8_t D3D11_PrepareDriver( return 1; } +static void D3D11_INTERNAL_TryInitializeDXGIDebug(D3D11Renderer *renderer) +{ + PFN_DXGI_GET_DEBUG_INTERFACE DXGIGetDebugInterfaceFunc; + HRESULT res; + + renderer->dxgidebug_dll = SDL_LoadObject(DXGIDEBUG_DLL); + if (renderer->dxgidebug_dll == NULL) + { + Refresh_LogWarn("Could not find " DXGIDEBUG_DLL); + return; + } + + DXGIGetDebugInterfaceFunc = SDL_LoadFunction( + renderer->dxgidebug_dll, + DXGI_GET_DEBUG_INTERFACE_FUNC + ); + if (DXGIGetDebugInterfaceFunc == NULL) + { + Refresh_LogWarn("Could not load function: " DXGI_GET_DEBUG_INTERFACE_FUNC); + return; + } + + res = DXGIGetDebugInterfaceFunc(&D3D_IID_IDXGIDebug, &renderer->dxgiDebug); + if (FAILED(res)) + { + Refresh_LogWarn("Could not get IDXGIDebug interface"); + } + + /* FIXME: Actually do something with the info queue! */ + res = DXGIGetDebugInterfaceFunc(&D3D_IID_IDXGIInfoQueue, &renderer->dxgiInfoQueue); + if (FAILED(res)) + { + Refresh_LogWarn("Could not get IDXGIInfoQueue interface"); + } +} + static Refresh_Device* D3D11_CreateDevice( uint8_t debugMode ) { @@ -3141,6 +3211,12 @@ static Refresh_Device* D3D11_CreateDevice( /* Get information about the selected adapter. Used for logging info. */ IDXGIAdapter1_GetDesc1(renderer->adapter, &adapterDesc); + /* Initialize the DXGI debug layer, if applicable */ + if (debugMode) + { + D3D11_INTERNAL_TryInitializeDXGIDebug(renderer); + } + /* Load the D3D library */ renderer->d3d11_dll = SDL_LoadObject(D3D11_DLL); if (renderer->d3d11_dll == NULL) diff --git a/src/Refresh_Driver_D3D11_cdefines.h b/src/Refresh_Driver_D3D11_cdefines.h index f9361c4..da87aef 100644 --- a/src/Refresh_Driver_D3D11_cdefines.h +++ b/src/Refresh_Driver_D3D11_cdefines.h @@ -26,11 +26,15 @@ /* Function Pointer Signatures */ typedef HRESULT(WINAPI* PFN_CREATE_DXGI_FACTORY1)(const GUID* riid, void** ppFactory); +typedef HRESULT(WINAPI* PFN_DXGI_GET_DEBUG_INTERFACE)(const GUID* riid, void** ppDebug); /* IIDs (from https://magnumdb.com) */ - static const IID D3D_IID_IDXGIFactory1 = { 0x770aae78,0xf26f,0x4dba,{0xa8,0x29,0x25,0x3c,0x83,0xd1,0xb3,0x87} }; static const IID D3D_IID_IDXGIFactory6 = { 0xc1b6694f,0xff09,0x44a9,{0xb0,0x3c,0x77,0x90,0x0a,0x0a,0x1d,0x17} }; static const IID D3D_IID_IDXGIAdapter1 = { 0x29038f61,0x3839,0x4626,{0x91,0xfd,0x08,0x68,0x79,0x01,0x1a,0x05} }; static const IID D3D_IID_ID3D11Texture2D = { 0x6f15aaf2,0xd208,0x4e89,{0x9a,0xb4,0x48,0x95,0x35,0xd3,0x4f,0x9c} }; static const IID D3D_IID_ID3D11Device1 = { 0xa04bfb29,0x08ef,0x43d6,{0xa4,0x9c,0xa9,0xbd,0xbd,0xcb,0xe6,0x86} }; +static const IID D3D_IID_IDXGIDebug = { 0x119e7452,0xde9e,0x40fe,{0x88,0x06,0x88,0xf9,0x0c,0x12,0xb4,0x41} }; +static const IID D3D_IID_IDXGIInfoQueue = { 0xd67441c7,0x672a,0x476f,{0x9e,0x82,0xcd,0x55,0xb4,0x49,0x49,0xce} }; + +static const GUID D3D_IID_DXGI_DEBUG_ALL = { 0xe48ae283,0xda80,0x490b,{0x87,0xe6,0x43,0xe9,0xa9,0xcf,0xda,0x08} };