2017-10-18 142 views
2

這個程序:D3D12不可避免的泄漏報告

#include <d3d12.h> 
#pragma comment(lib,"d3d12") 

int main() 
{ 
    ID3D12Debug *pDebug = NULL; 
    D3D12GetDebugInterface(__uuidof(ID3D12Debug),(void**)&pDebug); 
    pDebug->EnableDebugLayer(); 
    pDebug->Release(); 

    ID3D12Device *pDev = NULL; 
    D3D12CreateDevice(NULL,D3D_FEATURE_LEVEL_12_1,__uuidof(ID3D12Device),(void**)&pDev); 

    ID3D12DebugDevice *pDebugDevice = NULL; 
    pDev->QueryInterface(&pDebugDevice); 
    pDev->Release(); 
    pDebugDevice->ReportLiveDeviceObjects(D3D12_RLDO_DETAIL); 
    pDebugDevice->Release(); 
} 

給出了這樣的調試輸出:

D3D12 WARNING: Live ID3D12Device at 0x000C6BA8, Refcount: 2 [ STATE_CREATION WARNING #274: LIVE_DEVICE] 
D3D12 WARNING: Live ID3D12RootSignature at 0x000E62E8, Refcount: 0, IntRef: 2 [ STATE_CREATION WARNING #577: LIVE_ROOTSIGNATURE] 
D3D12 WARNING: Live ID3D12PipelineState at 0x0011C3C8, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #572: LIVE_PIPELINESTATE] 
D3D12 WARNING: Live ID3D12PipelineState at 0x001421D8, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #572: LIVE_PIPELINESTATE] 
D3D12 WARNING: Live ID3D12Resource at 0x00138FF8, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #575: LIVE_RESOURCE] 
D3D12 WARNING: Live ID3D12Heap at 0x00144DD8, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #579: LIVE_HEAP] 

調試設備報告,我創建的D3D12裝置還活着即使我釋放。我知道這確實是真的,因爲調試設備本身實際上是保持D3D12設備活着的唯一剩餘引用,但從我的角度來看,這不是泄漏,因爲我正確地發佈了我的D3D12設備。這只是對我的程序輸出的污染,給出了我的代碼中存在錯誤的錯誤提示。

我的問題是:我確實在這裏做錯了什麼?或者在D3D12調試設備的報告工作方式中這是一種不好的行爲?任何想法如何解決它?

謝謝!

回答

4

您應該嘗試使用D3D12_RLDO_IGNORE_INTERNAL標誌來忽略RefCount爲0但仍具有IntRef的項目。

我更喜歡使用DXGI調試設備報告而不是Direct3D的'乾淨關閉'方案。

在我DeviceResources實現中,我創建DXGI設備如下:

m_dxgiFactoryFlags = 0; 

#if defined(_DEBUG) 
    // Enable the debug layer (requires the Graphics Tools "optional feature"). 
    // 
    // NOTE: Enabling the debug layer after device creation will invalidate the active device. 
    { 
     ComPtr<ID3D12Debug> debugController; 
     if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(debugController.GetAddressOf())))) 
     { 
      debugController->EnableDebugLayer(); 
     } 
     else 
     { 
      OutputDebugStringA("WARNING: Direct3D Debug Device is not available\n"); 
     } 

     ComPtr<IDXGIInfoQueue> dxgiInfoQueue; 
     if (SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(dxgiInfoQueue.GetAddressOf())))) 
     { 
      m_dxgiFactoryFlags = DXGI_CREATE_FACTORY_DEBUG; 

      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 

    ThrowIfFailed(CreateDXGIFactory2(m_dxgiFactoryFlags, IID_PPV_ARGS(m_dxgiFactory.ReleaseAndGetAddressOf()))); 

然後當我關閉和要檢查 '泄漏':

#ifdef _DEBUG 
    { 
     ComPtr<IDXGIDebug1> dxgiDebug; 
     if (SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(&dxgiDebug)))) 
     { 
      dxgiDebug->ReportLiveObjects(DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_FLAGS(DXGI_DEBUG_RLO_SUMMARY | DXGI_DEBUG_RLO_IGNORE_INTERNAL)); 
     } 
    } 
#endif 

對於Win32應用程序,有一個明確的時間來做'清理出口'報告泄漏。對於UWP應用程序,生命週期由PLM控制,因此您永遠不會得到「乾淨退出」 - 該過程僅在暫停後終止。對於UWP,泄漏檢查的最佳位置在由設備移除錯誤引起的「設備丟失」處理程序中。

+0

'D3D12_RLDO_IGNORE_INTERNAL'標誌只刪除了提及的內部對象,但D3D12Device本身仍然被報告爲泄漏。 但是,您在示例中使用的DXGI方法完美無缺。謝謝Chuck! –