首页 > 解决方案 > 如何/何时在 DirectX 中释放资源和资源视图

问题描述

我正在开发 DirectX 11 演示应用程序并偶然发现以下问题:
当我从文件创建着色器资源视图(假设是纹理)时,我必须在使用后释放它,就像所有其他 D3D11 对象一样。但是,隐式创建的底层资源呢?

我可以想象三种情况:
+ 我应该不理会资源。它是通过调用someShaderResourceView->Release()
+ 我应该与着色器资源视图对象一起手动释放的。
+ 我应该立即释放它。这似乎可行,尽管对我来说似乎不合理。

处理这个问题的正确方法是什么?

编辑:我正在使用 DirectXTex 纹理加载库,但我想保持问题的一般性。

ID3D11Resource *resource;
ID3D11ShaderResourceView *resourceView;
HRESULT result = CreateWICTextureFromFile(device, path.c_str(), &resource, &texture, 0);
//resource->Release(); ???

CreateWICTextureFromFile(...)也可以使用旧的 D3DX11 功能代替D3DX11CreateShaderResourceViewFromFile(...)

标签: c++resourcesdirectx

解决方案


Direct3D 使用引用计数(通过AddRefand Release)方法来控制对象的生命周期,但有一些特定的怪癖,因为它不遵循通用组件对象模型 ( COM ) 的所有规则。

具体来说,如果对对象的唯一引用是在设备上下文中设置它(也就是将其绑定到渲染管道),那还不足以让它保持活动状态,因为这些方法不会增加/减少引用计数。请参阅Microsoft 文档。因此,您的程序需要保留对其当前使用的 Direct3D 对象的一些其他引用。

另一个区别是如果ID3D11Device由于引用计数为零而被销毁,那么它的所有ID3D11DeviceChild对象的引用计数是多少并不重要,并且在那时这些都是无效的。

您还应该记住,Direct3D 对象实际上直到将来某个时候才被销毁(也就是它使用延迟销毁),因此即使引用计数为零,它也可能需要几帧才能完全清除。如果您正在处理大量活动资源并且不得不担心过度提交,这很重要 - 顺便说一句,您可以使用 强制完成待处理的破坏ID3D11DeviceContext::Flush,但经常这样做并不是提高性能的好习惯。

TL;DR:ID3D11ShaderResourceView对象向被引用对象添加了一个引用计数ID3D11Resource,因此只要 SRV 处于活动状态,资源也会保持活动状态。您只需要获取 的返回对象之一CreateWICTextureFromFile,但如果您愿意,可以同时获取。有关更多信息,请参阅 WICTextureLoader 模块的wiki页面。

这是学习使用ComPtr智能指针的一个很好的理由。如果您正确使用它,它会处理引用计数,因此在大多数情况下您可以避免担心它。

更新:来自旧版 DirectX SDK 的使用 COM 编程 DirectX主题现已更新并发布在 Microsoft Docs 上。


推荐阅读