Pau*_*ris 0 c++ com directx memory-management
编写DIY内存管理器最令人满意的部分是构造它,这样你就可以忘记[删除](例如,通过将所有内容捆绑到单独分配/解除分配的缓冲区中).
DirectX处理对象创建的方式意味着你不能简单地将void内存转换为你想要制作的类型(可以吗?)而你必须依赖COM(+记住每个析构函数中的[Release]本地内存).有没有办法颠覆这个并说服DirectX使用我的指针?
代替:
ID3D12Thing* thng = DirectX::CreateThing();
...
thng->Release();
thng = nullptr;
Run Code Online (Sandbox Code Playgroud)
我想要:
ID3D12Thing* thng = DirectX::CreateThingAt(Allocator->AlignedAlloc(sizeof(ID3D12Thing));
...
[memory emptied during shutdown]
Run Code Online (Sandbox Code Playgroud)
编辑:这个答案已被Chuck Walbourn的平行答案所取代.虽然我的答案并非完全错误,经过一番调查后我很确定Chuck Walbourn的使用建议Microsoft::WRL::ComPtr是更好的选择(请参阅CB答案中的评论部分)./编辑
据我所知,不可能在Direct X结构上植入外部存储器,因为它们都是由Direct X本身创建的.
然而,如果主要目标是维护和安全,则可以std::unique_ptr使用自定义删除器来定义一个执行释放工作的人员.
struct DxDeleter {
void operator() (IUnknown* _moribund) { if(_moribund) _moribund->Release(); }
};
typedef std::unique_ptr<ID3D11Buffer,DxDeleter> dx_buffer_ptr;
typedef std::unique_ptr<ID3D11ShaderResourceView,DxDeleter> dx_resource_ptr;
typedef std::unique_ptr<ID3D11UnorderedAccessView,DxDeleter> dx_access_ptr;
...
Run Code Online (Sandbox Code Playgroud)
然后,指针简单地分配有例如myUniqueDxBufferPtr.reset( myRawBufferPtr )或类似的.
这具有很高的好处,不需要跟踪发布.这不仅适用于Direct X,也适用于需要分配和释放的各种外部库(例如,我对Freeimage和ffmpeg使用相同的技术).
也可以std::shared_ptr为资源定义s,这些资源由多个项共享(例如,只要存在任何缓冲区,您就可以保持设备处于活动状态).但是要小心处理 - 相反std::unique_ptr,std::shared_ptrs没有删除器作为模板参数,而是作为ctor参数 - 这使得错误地分配具有丢失删除器(泄漏)的东西非常容易.
void g_dxDelete( IUnknown* _moribund ) {
if( _moribund )
_moribund->Release();
}
typedef std::shared_ptr<ID3D11Device> dx_device_shared;
inline dx_device_shared assignDevice( ID3D11Device* _device ) {
return std::move( dx_device_shared( _device, g_dxDelete ) );
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,您必须始终确保为创建的设备分配dx_device_shared myDevice = assignDevice(myRawDevicePtr),但绝不使用dx_device_shared myDevice = myRawDevicePtr.