它指出我可以从多个线程对ID3D11Device进行调用(除非使用了D3D11_CREATE_DEVICE_SINGLETHREADED),但是对ID3D11DeviceContext的调用必须被关键部分包围。
对于使用纹理,渲染目标,顶点/索引缓冲区,着色器之类的资源,我尚未发现有关使用资源的“释放”方法释放资源的任何信息。
ID3D11Texture2D,ID3D11Texture3D,ID3D11ShaderResourceView,ID3D11RenderTargetView,ID3D11DepthStencilView
ID3D11Buffer。
ID3D11VertexShader,ID3D11HullShader,ID3D11DomainShader,ID3D11PixelShader。
1)我可以在不使用渲染线程的ID3D11DeviceContext未使用关键节的情况下,随时从任何线程调用这些资源的“释放”吗?
2)即使其他线程正在渲染线程中的ID3D11DeviceContext正在使用这些资源,我也可以调用这些资源的“释放”吗?
还是我需要用与访问ID3D11DeviceContext相同的关键部分来包围Release调用?
答案 0 :(得分:2)
通常,COM参考计数的内部实现是以线程安全的方式(原子增量/减量)完成的,因此从多个线程调用AddRef
和Release
是安全的。
当然,如果refcount变为0,那么您将销毁对象,因此,如果您有多个线程使用同一资源,则它必须具有适当数量的引用计数以保持其存活,这一点很重要。在Direct3D中,对象销毁通常是延迟销毁,因此实际的对象清理可能不会在几帧之内发生,但是如果有人引用它,则仍应保留非零引用计数。
Direct3D 11使用与Direct3D 10相同的规则。它对管道设置方法使用“弱引用”,因此仅在设备上下文中设置资源不足以增加其引用计数。 IOW:如果您有两个线程都使用相同的资源进行渲染,则每个线程必须在对象上保留一个引用计数,以使其保持“活动”状态,无论是否在任何给定的时刻在设备上下文中“对其进行了主动设置”。 >
通过这种方式可以避免在每个渲染帧中不断增加/减少参考计数的开销。在Direct3D 9中,这种情况在一帧或更多帧中发生数千次。
此外,如果ID3D11Device
的引用计数为零,则将释放它和所有其子对象,而不管各个设备子引用的计数如何。
请参见Microsoft Docs。
最好的答案是使用像Microsoft::WRL::ComPtr这样的智能指针,并让使用给定资源的每个线程都有自己的
ComPtr
指向该资源。这样,您唯一真正的特殊情况就是拆卸设备时(例如响应DXGI_ERROR_DEVICE_REMOVED
或执行“干净出口”)。