How/When 在 DirectX 中释放资源和资源视图

How/When to release resources and resource views in DirectX

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

我能想象出三种场景:
+ 我应该单独留下资源。它通过调用 someShaderResourceView->Release()
释放 + 我应该将它与着色器资源视图对象一起手动释放。
+ 我应该立即释放它。这似乎可行,尽管对我来说似乎不合理。

正确的处理方法是什么?

编辑:我正在使用 DirectXTex 纹理加载库,但我想保持这个问题的笼统。

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

也可以使用旧的 D3DX11 函数 D3DX11CreateShaderResourceViewFromFile(...).

而不是 CreateWICTextureFromFile(...)

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

具体来说,如果 对对象的引用是在设备上下文中设置它(a.k.a。将其绑定到渲染管道),那就是不足以让它保持活动状态,因为这些方法没有 increment/decrement 引用计数。参见 Microsoft Docs。因此,您的程序需要保留对它当前使用的 Direct3D 对象的一些其他引用。

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

你还应该记住,Direct3D 对象直到未来某个时间点才真正销毁(a.k.a。它使用惰性销毁)所以即使引用计数为零,也可能需要几帧在完全清理干净之前。如果您正在处理大量活动资源并且不得不担心过度提交,这最重要——顺便说一句,您可以使用 ID3D11DeviceContext::Flush 强制完成未决的销毁,但这不是提高性能的好习惯经常做。

TL;DR: ID3D11ShaderResourceView 对象向引用的 ID3D11Resource 对象添加了引用计数,因此只要 SRV 处于活动状态,资源也保持活力。 CreateWICTextureFromFile 的 return 个对象你只需要取其中一个,但如果你愿意,也可以两个都取。有关详细信息,请参阅 WICTextureLoader 模块的 wiki 页面。

This is a good reason to learn to use the ComPtr smart-pointer. It takes care of the reference counts if you use it correctly so you can avoid worrying about it in most cases.

更新:旧版 DirectX SDK 中的主题 Programming DirectX with COM 现已更新并发布在 Microsoft Docs 上。