D3D12 不可避免的泄漏报告
D3D12 unavoidable leak report
这个程序:
#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 调试设备中报告的工作方式中的不良行为?关于如何解决它的任何想法?
谢谢!
您应该尝试使用 D3D12_RLDO_IGNORE_INTERNAL
标志忽略那些 RefCount 为 0 但仍具有 IntRef 的项目。
对于"干净关闭"方案,我更喜欢使用 DXGI 调试设备报告而不是 Direct3D 报告。
在我的设备资源实现中,我按如下方式创建 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 availablen");
}
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,执行泄漏检查的最佳位置是在由设备删除错误导致的"设备丢失"处理程序中。
使用 ComPtr 对象定义 D3D12 对象,如 Chuck 的示例所示:
ComPtr<ID3D12Debug> debugController;
这是避免泄漏所必需的,并且不需要执行对象>Release()调用,因为ComPtr对象在其解构函数中执行这些调用。
相关文章:
- Valgrind 在 QThread::start() 上报告内存泄漏
- 如何在-fsanitize=地址下运行时抑制泄漏清理器报告?
- 为什么 Valgrind 在此实现中报告内存泄漏?
- 瓦尔格林德在组成中报告的内存泄漏
- 如何修复Valgrind报告的C 数组驱动器中的内存泄漏
- D3D12 不可避免的泄漏报告
- 可视检漏仪未报告泄漏
- Valgrind不会报告现有的泄漏/错误的条件
- Valgrind在定义字符*数组时报告内存泄漏
- valgrind报告使用Ubuntu在C 中泄漏
- 瓦尔格林德报告内存泄漏,但我不明白它发生在哪里
- 程序的内存使用量随着时间的推移而增加,但内存泄漏工具报告没有问题
- Valgrind 报告了许多在运行之间更改的地方的内存泄漏
- 我的 MFC 应用中报告了错误的内存泄漏
- CRT调试堆在包含exception_ptr.hpp时报告泄漏
- 在OSX上,Valgrind报告了内存泄漏,它来自哪里
- 如何使用 DrMemory 在 C++ 中显示和报告内存泄漏
- 为什么一个简单的SDL程序会报告Valgrind中的内存泄漏?
- LeakSanitizer:获取运行时泄漏报告
- Valgrind报告mysql_real_connect的泄漏