[DX11调试]检查D3D对象是否释放:ReportLiveObjects()的用法

参考文章《DirectX Leak Debugging》:http://masterkenth.com/blog/2014/03/07/directx-leak-debugging/

DX11在debug方面有许多改进,其中之一就是能输出未释放的d3d对象,但默认情况下,是输出这个样子:

D3D11 WARNING: Process is terminating. Using simple reporting. Please call ReportLiveObjects() at runtime for standard reporting. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: Live Producer at 0x00361180, Refcount: 3. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: 	Live Object at 0x00362010, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: 	Live Object at 0x003713F8, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: 	Live Object at 0x0037755C, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: 	Live Object at 0x003776FC, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: 	Live Object at 0x00377894, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: 	Live Object at 0x00377B34, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: 	Live Object at 0x00377CC4, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: 	Live Object at 0x00378290, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: 	Live Object at 0x003787F4, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: 	Live Object at 0x0037A884, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: 	Live Object at 0x0037AA44, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: 	Live Object at 0x0037C7AC, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: 	Live Object at 0x0037B784, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: 	Live Object at 0x0037CC14, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: 	Live Object at 0x0037F29C, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: 	Live Object at 0x0037DE1C, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: 	Live Object at 0x0037FE3C, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: 	Live Object at 0x04191A14, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: 	Live Object at 0x041E0364, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: Live                         Object :     19 [ STATE_CREATION WARNING #0: UNKNOWN]
DXGI WARNING: Live Producer at 0x00340978, Refcount: 4. [ STATE_CREATION WARNING #0: ]
DXGI WARNING: 	Live Object at 0x00353640, Refcount: 2. [ STATE_CREATION WARNING #0: ]
DXGI WARNING: Live                         Object :      1 [ STATE_CREATION WARNING #0: ]

以上这些不清不楚的警告对我们而言毫无帮助,和没有输出任何东西一样。所以d3d提供了一个ReportLiveObjects()方法,让开发者直接查询当前各个d3d对象的状态

一、

在使用这个方法之前,我们需要先做一些准备 —— 把d3d的device定义为debug模式。在创建device的时候flag参数设置为 D3D11_CREATE_DEVICE_DEBUG。和dx sdk自带的sample里的例子是一样的做法

#if defined(DEBUG) || defined(_DEBUG)
	createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
D3D11CreateDeviceAndSwapChain(NULL, mDriverType, NULL, createDeviceFlags, featureLevels, numFeatureLevels,
			D3D11_SDK_VERSION, &desc, &mSwapChain, &mDevice, &mFeatureLevel, &mDeviceContext);

二、

接下来我们就可以随时调用ReportLiveObjects()方法了。一般是放在device->Release()之前,用来检查其他对象是否已经正确释放。示范如下:

#if defined(DEBUG) || defined(_DEBUG)
	ID3D11Debug *d3dDebug;
	HRESULT hr = mDevice->QueryInterface(__uuidof(ID3D11Debug), reinterpret_cast<void**>(&d3dDebug));
	if (SUCCEEDED(hr))
	{
		hr = d3dDebug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL);
	}
	if (d3dDebug != nullptr)			d3dDebug->Release();
#endif
	if (mDevice != nullptr)				mDevice->Release();

三、

ReportLiveObjects()的参数是一个enum,有3个:

D3D11_RLDO_SUMMARY

显示总概况

D3D11_RLDO_DETAIL

显示详细信息

D3D11_RLDO_IGNORE_INTERNAL

MSDN解释是无用,只是给DX内部使用(那你定义这个做什么啊!)

忽略第三个卖萌的,D3D11_RLDO_SUMMARY和D3D11_RLDO_DETAIL有什么不同呢?我们看下2个的输出

D3D11_RLDO_SUMMARY

D3D11 WARNING: Using ID3D11Debug::ReportLiveDeviceObjects with D3D11_RLDO_DETAIL will help drill into object lifetimes. Objects with Refcount=0 and IntRef=0 will be eventually destroyed through typical Immediate Context usage. However, if the application requires these objects to be destroyed sooner, ClearState followed by Flush on the Immediate Context will realize their destruction.
 [ STATE_CREATION WARNING #422: LIVE_OBJECT_SUMMARY]
D3D11 WARNING: Live ID3D11Device at 0x0036110C, Refcount: 5 [ STATE_CREATION WARNING #441: LIVE_DEVICE]

D3D11_RLDO_DETAIL:

D3D11 WARNING: Live ID3D11Device at 0x004ED84C, Refcount: 5 [ STATE_CREATION WARNING #441: LIVE_DEVICE]
D3D11 WARNING: 	Live ID3D11Context at 0x004EE5C8, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #2097226: LIVE_CONTEXT]
D3D11 WARNING: 	Live ID3DDeviceContextState at 0x005013D8, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #3145742: LIVE_DEVICECONTEXTSTATE]
D3D11 WARNING: 	Live ID3D11BlendState at 0x0050753C, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #435: LIVE_BLENDSTATE]
D3D11 WARNING: 	Live ID3D11DepthStencilState at 0x005076DC, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #436: LIVE_DEPTHSTENCILSTATE]
D3D11 WARNING: 	Live ID3D11RasterizerState at 0x0050784C, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #437: LIVE_RASTERIZERSTATE]
D3D11 WARNING: 	Live ID3D11Sampler at 0x00507AEC, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #434: LIVE_SAMPLER]
D3D11 WARNING: 	Live ID3D11Query at 0x00507CA4, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #438: LIVE_QUERY]
D3D11 WARNING: 	Live IDXGISwapChain at 0x00508270, Refcount: 0 [ STATE_CREATION WARNING #442: LIVE_SWAPCHAIN]
D3D11 WARNING: 	Live ID3D11Texture2D at 0x005087D4, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #425: LIVE_TEXTURE2D]
D3D11 WARNING: 	Live ID3D11RasterizerState at 0x0050A89C, Refcount: 0, IntRef: 0 [ STATE_CREATION WARNING #437: LIVE_RASTERIZERSTATE]
D3D11 WARNING: 	Live ID3D11RenderTargetView at 0x0050AA34, Refcount: 0, IntRef: 0 [ STATE_CREATION WARNING #428: LIVE_RENDERTARGETVIEW]
D3D11 WARNING: 	Live ID3D11VertexShader at 0x0050C79C, Refcount: 0, IntRef: 0 [ STATE_CREATION WARNING #430: LIVE_VERTEXSHADER]
D3D11 WARNING: 	Live ID3D11InputLayout at 0x0050B774, Refcount: 0, IntRef: 0 [ STATE_CREATION WARNING #433: LIVE_INPUTLAYOUT]
D3D11 WARNING: 	Live ID3D11PixelShader at 0x0050CC04, Refcount: 0, IntRef: 0 [ STATE_CREATION WARNING #432: LIVE_PIXELSHADER]
D3D11 WARNING: 	Live ID3D11VertexShader at 0x0050D0CC, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #430: LIVE_VERTEXSHADER]
D3D11 WARNING: 	Live ID3D11InputLayout at 0x0050DEAC, Refcount: 0, IntRef: 0 [ STATE_CREATION WARNING #433: LIVE_INPUTLAYOUT]
D3D11 WARNING: 	Live ID3D11PixelShader at 0x00517844, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #432: LIVE_PIXELSHADER]
D3D11 WARNING: 	Live ID3D11Buffer at 0x009066D4, Refcount: 0, IntRef: 0 [ STATE_CREATION WARNING #423: LIVE_BUFFER]
D3D11 WARNING: 	Live ID3D11Texture2D at 0x00979754, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #425: LIVE_TEXTURE2D]

很显而易见吧!

四、

IntRef是d3d内部的对象引用,Refcount是我们程序里未释放的d3d对象,比如我们的ID3D11Context,Refcount是0,但IntRef是1,因为我们在程序里创建过一个context,所以在d3d内部还保留着引用,我们只需要注意Refcount不为0的对象就OK了。

所以上面的那几行信息,告诉我们还有一个ID3D11Device,ID3D11VertexShader和ID3D11PixelShader对象未释放,vs和ps对象可以释放,但因为ReportLiveObjects()方法是device调用的,所以在这之前我们还不能释放device,不过无问题,在确保其他对象的Refcount为0后,我们再安全释放ID3D11Debug和ID3D11Device就OK了。

时间: 2024-08-25 01:54:00

[DX11调试]检查D3D对象是否释放:ReportLiveObjects()的用法的相关文章

检查SharePoint代码中对象是否释放的小工具

问题 一般继承IDisposable接口的对象, 在使用完成后可以释放对象以免占用过多的资源, 当然也可是使用using语句来完成此操作. 但是当项目很大的时候, 代码也比较多, 我们更多希望有工具来检查项目中是否有类似的对象没有释放. 解决办法 微软其实提供了一个小工具"SharePoint Dispose Checker Tool", 但是很遗憾, 不支持SharePoint 2013, 有需求的朋友可以点击下面的链接查看. 地址: https://gallery.technet.

C#+ArcEngine中com对象的释放问题

1.问题描述 最近在写C#下AE的开发,在循环获取数据并修改时碰到了两个问题"超出系统资源"和"超出打开游标最大数":在网上看了一些资料,发现都是说在循环中没有释放已经使用过的对象,但是在循环中实际上是有为com对象赋值为null的,但是还是没法解决.后来想着将对象赋值为null和marshal是不是效果不一样,就特意写了一个简单的循环来测试,代码如下(初级代码,比较乱,请轻喷): 1 public void Test_释放游标方式() 2 { 3 string s

java 哪些情况下会使对象锁释放

Java_多线程_锁释放 问:Java多线程运行环境中,在哪些情况下会使对象锁释放?答:由于等待一个锁的线程只有在获得这把锁之后,才能恢复运行,所以让持有锁的线程在不再需要锁的时候及时释放锁是很重要的.在以下情况下,持有锁的线程会释放锁:(1)执行完同步代码块,就会释放锁.(synchronized)(2)在执行同步代码块的过程中,遇到异常而导致线程终止,锁也会被释放.(exception)(3)在执行同步代码块的过程中,执行了锁所属对象的wait()方法,这个线程会释放锁,进        入

java匿名类和匿名对象及this的其他用法

/* 匿名内部类:就是内部类的简写格式. 必须前提:内部类必须继承或者实现一个类或者接口. 匿名内部类其实就是一个匿名 子类对象. 格式:new 父类对象 or 接口(){ 子类内容:(覆盖父类的, 而且可以增加自己的方法) }//相当于将 继承父类 和 new 的过程 写到了一起有某有!很方便有某有! */ class Outer{ int num; public Outer(){ num = 5; } class Inner{ int num; public Inner(){ num = 1

c#配置问题以及简单防止sql注入,连接池问题,sqldatareader对象对于connection对象的释放

添加引用.system configuration configurationManager.AppSettings[""] <appSetings> <add key="" value=""> </appSetings> <connectionStrings> <add key="" connectionString=""> </conne

ARC下面的对象被释放的bug

一般在ARC管理的方式之下,很难出现对象被过度释放的问题,下面是我将遇到的一个crash. * thread #1: tid = 0x31d1db, 0x0000000102e5e00b libobjc.A.dylib`objc_msgSend + 11, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x18) frame #0: 0x0000000102e5e00b libobjc

Powershell检查AD对象是否存在

在Powershell(PS)脚本或.Net活动目录编程时经常需要检查一个AD对象是否存在,但无论是PS的AD模块还是到目前的版本的Framework尚未提供一个直接的方法.本文根据近几年写AD脚本的经验,总结如下: 第一种方法是用调用ADSI静态方法Exists(),其使用的查询可以是上个世纪的WinNT provider也可以是LDAP,使用语法如下:[ADSI]::Exists("WinNT://DomainName/SamAccountName");[ADSI]::Exists

inspect模块---检查活动对象

inspect模块提供了一些有用的函数来帮助获取有关活动对象(如模块,类,方法,函数,跟踪,框架对象和代码对象)的信息.例如,它可以帮助您检查类的内容,检索方法的源代码,提取和格式化函数的参数列表,或获取显示详细追溯所需的所有信息. 这个模块提供了四种主要的服务: 类型检查, 获取源代码, 检查类和函数, 以及检查解释器堆栈 一.type and members 1. inspect.getmembers(object[, predicate]) 第二个参数通常可以根据需要调用如下16个方法:

js调试--查找dom对象绑定的函数

点击最右侧的js文件. 选中函数upload_pic_box,右击,选择在控制台中调试,或者在控制台直接输入该函数 点击最后一行代码会打开该函数所在的js文件