c++ - 如何/何时在 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(...)
。
解决方案
Direct3D 使用引用计数(通过AddRef
and Release
)方法来控制对象的生命周期,但有一些特定的怪癖,因为它不遵循通用组件对象模型 ( COM ) 的所有规则。
具体来说,如果对对象的唯一引用是在设备上下文中设置它(也就是将其绑定到渲染管道),那还不足以让它保持活动状态,因为这些方法不会增加/减少引用计数。请参阅Microsoft 文档。因此,您的程序需要保留对其当前使用的 Direct3D 对象的一些其他引用。
另一个区别是如果ID3D11Device
由于引用计数为零而被销毁,那么它的所有ID3D11DeviceChild
对象的引用计数是多少并不重要,并且在那时这些都是无效的。
您还应该记住,Direct3D 对象实际上直到将来某个时候才被销毁(也就是它使用延迟销毁),因此即使引用计数为零,它也可能需要几帧才能完全清除。如果您正在处理大量活动资源并且不得不担心过度提交,这很重要 - 顺便说一句,您可以使用 强制完成待处理的破坏ID3D11DeviceContext::Flush
,但经常这样做并不是提高性能的好习惯。
TL;DR:该ID3D11ShaderResourceView
对象向被引用对象添加了一个引用计数ID3D11Resource
,因此只要 SRV 处于活动状态,资源也会保持活动状态。您只需要获取 的返回对象之一CreateWICTextureFromFile
,但如果您愿意,可以同时获取。有关更多信息,请参阅 WICTextureLoader 模块的wiki页面。
这是学习使用ComPtr智能指针的一个很好的理由。如果您正确使用它,它会处理引用计数,因此在大多数情况下您可以避免担心它。
更新:来自旧版 DirectX SDK 的使用 COM 编程 DirectX主题现已更新并发布在 Microsoft Docs 上。
推荐阅读
- for-loop - 对于目录中的每个文件,将文件名和子字符串打印到 csv,
- .net - 为什么我们有两个用于 JWT 令牌 JwtSecurityTokenHandler 和 JsonWebTokenHandler 的类?
- vb.net - OpenXML 按名称获取工作表 VB.Net
- python - 基于现有数值列在数据框中创建新列,字符串列表作为列名,元组列表作为值
- c# - 如何在 JSON 文件中添加、删除、更新、只读一个条目?
- asp.net - 如何将工作簿(.aspx 文件)从 html 链接复制到当前工作簿
- c# - 外键属性设置不正确
- url - 如何通过“curl -O”引用同一url中的变量
- neo4j - 如何汇总分数
- azure-batch - “ResourceContainerAccessDenied”作为 CloudTask.ExecutionInformation.FailureInformation.Code 的值返回,但不在 TaskFailureInformationCodes 中