c++comdirect3d11

WRL::ComPtr causes object leaks in d3d?


I am making a simple d3d 11 application and I'm using the Microsoft::WRL::ComPtr to release the resources automatically. For some reason though when the applications exits I'm getting 30-40 Live Object warnings from d3d. I could have missed one or two, but this seems more like the count of all objects I have. I'm obviously doing something wrong. My general usage would be to have a member in some wrapper class:

class graphics_device
{
   // ...
   ComPtr<ID3D11Device> hwdevice;
}

Which in theory should release the object upon class destruction. (I'm creating most objects on stack and I've double checked that I delete the ones that are on the heap)

When I create my functionality I pass them around as references. For example:

void graphics_device::create_constant_buffer(u32 size, const void* data, ComPtr<ID3D11Buffer>& constantBuffer)
{
    D3D11_BUFFER_DESC bufferDesc;
    ZeroMemory(&bufferDesc, sizeof(bufferDesc));

    bufferDesc.Usage = D3D11_USAGE_DEFAULT;
    bufferDesc.ByteWidth = size;
    bufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
    bufferDesc.CPUAccessFlags = 0;

    D3D11_SUBRESOURCE_DATA initData;
    ZeroMemory(&initData, sizeof(initData));
    initData.pSysMem = data;

    device->CreateBuffer(&bufferDesc, &initData, &constantBuffer);
}

Any ideas what I'm missing?

EDIT: Forgot to post the warnings from d3d11:

D3D11 WARNING:  Live Object at 0x0061D93C, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING:  Live Object at 0x0061DBE4, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING:  Live Object at 0x0061DE8C, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: Live                         Object :     31 [ STATE_CREATION WARNING #0: UNKNOWN]
DXGI WARNING: Live Producer at 0x005ADDC0, Refcount: 4. [ STATE_CREATION WARNING #0: ]
DXGI WARNING:   Live Object at 0x005B7FD0, Refcount: 2. [ STATE_CREATION WARNING #0: ]
DXGI WARNING: Live                         Object :      1 [ STATE_CREATION WARNING #0: ]

And many more similar. I'm not getting any other warnings during runtime.


Solution

  • Getting a 'clean exit' can be a little challenging. It's not likely to be ComPtr if used correctly. Per the comment, a good place to start is object naming. Remember that the output happens when the Direct3D Device is released, so you may need to look at the 'release order' to get it to cleanly exit. There are also 'internal' vs. 'external' ref-counts so they can be a little confusing. See this blog post for some notes on the debug layer usage.

    Another thing to keep in mind is that Direct3D object reporting can't really tell you about DXGI-owned objects. That's why also using DXGI Debug Device can be useful as well.

    The directx-vs-templates put all advice from these blog posts in one place, so you might want to look at them.

    Finally, passing ComPtr as a parameter is generally not the best use case even by reference. Using ComPtr as data members and local variables is great, but usually as parameters it's best to use "raw pointers" since the lifetime is implicit already. So your function signature would be better as:

    void graphics_device::create_constant_buffer(u32 size, const void* data, ID3D11Buffer** constantBuffer);
    

    Then when calling that function, you use a ComPtr:

    ComPtr<ID3D11Buffer> cb;
    graphicsdevice->create_constant_buffer(size, data, &cb);
    

    See this wiki on ComPtr for some hints on using it most effectively.