编写 DIY 内存管理器最令人满意的部分是构建它,这样您就可以忘记 [删除](例如,通过将所有内容捆绑到一个单独分配/取消分配的缓冲区中)。
DirectX 处理对象创建的方式意味着您不能简单地将无效内存转换为您想要创建的类型(可以吗?)并且您必须依赖 COM(+ 记住在每个析构函数中 [Release] 本地内存) 反而。有什么方法可以颠覆这一点并说服 DirectX 使用我的指针吗?
代替:
ID3D12Thing* thng = DirectX::CreateThing();
...
thng->Release();
thng = nullptr;
我要:
ID3D12Thing* thng = DirectX::CreateThingAt(Allocator->AlignedAlloc(sizeof(ID3D12Thing));
...
[memory emptied during shutdown]
最佳答案
编辑:此答案已被 Chuck Walbourn 的平行答案取代。
虽然我的回答并非完全错误,但经过一些调查后,我很确定 Chuck Walbourn 使用 Microsoft::WRL::ComPtr
的建议是更好的选择(另请参阅 C.B. 的回答下的评论部分原因)。 /编辑
据我所知,不可能在 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;
...
然后指针简单地分配给例如。 myUniqueDxBufferPtr.reset( myRawBufferPtr )
或类似的。
这有很大的好处,即不需要跟踪版本。这不仅适用于 Direct X,而且适用于需要分配和释放的各种外部库(例如,我对 Freeimage 和 ffmpeg 也使用相同的技术)。
也可以为多个项目共享的资源定义 std::shared_ptr
(例如,只要存在任何缓冲区,您就可以让设备保持事件状态)。但这是小心处理 - 与std::unique_ptr
相反,std::shared_ptr
没有删除器作为模板参数,但作为 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 ) );
}
在这种情况下,您必须始终确保使用 dx_device_shared myDevice = assignDevice(myRawDevicePtr)
分配创建的设备,但绝不能使用 dx_device_shared myDevice = myRawDevicePtr
。
关于c++ - 没有 ->Release() 的 DirectX,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49836725/