DirectX没有 - >发布()

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)

use*_*447 5

编辑:这个答案已被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.