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 使用引用计数(通过 AddRef
和 Release
)方法来控制对象的生命周期,但有一些特殊的怪癖,因为它不遵循通用组件对象模型的所有规则( 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 上。
我正在开发 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 使用引用计数(通过 AddRef
和 Release
)方法来控制对象的生命周期,但有一些特殊的怪癖,因为它不遵循通用组件对象模型的所有规则( 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 上。