DXGI Debug Device


In my original post on using the debug layer, I mentioned several tricks for getting helpful behavior out of the Direct3D SDK debug layer for your applications. This best practice is demonstrated in my Visual C++ Game templates as follows:

 #ifndef NDEBUG
Microsoft::ComPtr<ID3D11Debug> d3dDebug;
hr = m_d3dDevice.As(&d3dDebug);
if (SUCCEEDED(hr))
{
       ComPtr<ID3D11InfoQueue> d3dInfoQueue;
       hr = d3dDebug.As(&d3dInfoQueue);
       if (SUCCEEDED(hr))
       {
#ifdef _DEBUG
              d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true);
              d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true);
#endif
              D3D11_MESSAGE_ID hide [] =
              {
                     D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS,
              // TODO: Add more message IDs here as needed
              };
              D3D11_INFO_QUEUE_FILTER filter;
              memset(&filter, 0, sizeof(filter));
              filter.DenyList.NumIDs = _countof(hide);
              filter.DenyList.pIDList = hide;
              d3dInfoQueue->AddStorageFilterEntries(&filter);
       }
}
#endif

This snippet ensures that a common but harmless warning message is suppressed in non-Production builds, and enables 'break on' functionality in Debug builds if there are any serious corruption or error messages.

With the Direct3D 11.1 Runtime or later, you can also use a DXGI debug interface to track down additional leaks that are not known to your Direct3D 11 device. How this new interface is exposed, however, is a bit confusing.

For traditional Windows desktop apps, you are expected to use explicit linking. Since the DXGI debug layer is not present on end-user machines, this pattern encourages being able to handle the case of it not being present on the system. The confusing part is that the function you need, DXGIGetDebugInterface is not defined in any header and is not present in any import library.

#include <dxgidebug.h>
#if defined(_DEBUG)
    Microsoft::WRL::ComPtr<IDXGIInfoQueue> dxgiInfoQueue;
 
    typedef HRESULT (WINAPI * LPDXGIGETDEBUGINTERFACE)(REFIID, void ** );
 
    HMODULE dxgidebug = LoadLibraryEx( L"dxgidebug.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32 );
    if ( dxgidebug )
    {
        auto dxgiGetDebugInterface = reinterpret_cast<LPDXGIGETDEBUGINTERFACE>(
            reinterpret_cast<void*>( GetProcAddress( dxgidebug, "DXGIGetDebugInterface" ) ) );
 
        if ( SUCCEEDED( dxgiGetDebugInterface( IID_PPV_ARGS( dxgiInfoQueue.GetAddressOf() ) ) ) )
        {
            dxgiInfoQueue->SetBreakOnSeverity( DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, true );
            dxgiInfoQueue->SetBreakOnSeverity( DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, true );
        }
    }
#endif
 

One issue with this pattern is that you can't use it for Windows Store or universal Windows apps since LoadPackagedLibrary cannot load a system DLL as a security measure. In the DirectX 11.2 Runtime (Windows 8.1 and Windows 10), there is now a DXGIGetDebugInterface1 defined in the dxgi1_3.h header and in the dxgi.lib import library. This implicit linking works fine for Windows Store apps and UWP, but for desktop apps you should stick with the explicit method particularly if you need Windows 7 support as this function is not present in the 11.1 or 11.0 runtime.

#if defined(_DEBUG)
Microsoft::WRL::ComPtr<IDXGIInfoQueue> dxgiInfoQueue;
if ( SUCCEEDED( DXGIGetDebugInterface1( 0, IID_PPV_ARGS( dxgiInfoQueue.GetAddressOf() ) ) ) )
{
       dxgiInfoQueue->SetBreakOnSeverity( DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, true );
       dxgiInfoQueue->SetBreakOnSeverity( DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, true );
}
#endif

As with the Direct3D debug layer, there is a method for reporting live DXGI objects as well for tracking down resource leaks. You obtain a IDXGIDevice instance the same was as you do a IDXGIInfoQueue interface above, and then call ReportLiveObjects.

DXGUID: One other issue of note is that the various DXGI debug control GUIDs (i.e. DXGI_DEBUG_ALL) are missing from DXGUID.LIB. You have to define it yourself using INITGUID. This is fixed for the Windows 10 SDK.

Related: Direct3D SDK Debug Layer Tricks, DirectX 11.1 and Windows 7 Update

Comments (1)

  1. ET3D says:

    Took me some time to realise that ‘define it yourself using INITGUID’ simply means including initguid.h before dxgidebug.h. Probably worth noting.

Skip to main content