How COM warning works? how does the device get initialized?

61 views Asked by At

My d3d11 c++ code produces warning for live COM objects that I never initialized.

my code:


#define _INCLUDE_LIBS__

#include "stdafx.h"

#define WINDOW_NAME L"main window"
#define WS WS_OVERLAPPEDWINDOW

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{

    HWND hwnd = NULL; {

        WNDCLASS wc = { 0 };
        wc.cbClsExtra = 0;
        wc.cbWndExtra = 0;
        wc.hbrBackground = CreateSolidBrush(RGB(0, 0, 1));
        wc.hCursor = NULL;
        wc.hIcon = NULL;
        wc.hInstance = hInstance;
        wc.lpfnWndProc = WndProc;
        wc.lpszClassName = L"MainClass";
        wc.lpszMenuName = NULL;
        wc.style = CS_HREDRAW | CS_VREDRAW;

        if (!RegisterClass(&wc)) OutputDebugString(L"ERROR  :   window class registration failed!");

        hwnd = CreateWindow(wc.lpszClassName, WINDOW_NAME, WS, 0, 0, 1000, 600, NULL, NULL, hInstance, NULL);

        if(!hwnd) OutputDebugString(L"ERROR  :   window Creation failed!");

    }

    IDXGIFactory1* factory = nullptr; {

        CreateDXGIFactory1(IID_PPV_ARGS(&factory));
    }

    IDXGIAdapter* adapter = nullptr; {

        factory->EnumAdapters(0, &adapter);

        DXGI_ADAPTER_DESC desc;

        adapter->GetDesc(&desc);

        OutputDebugString(L"\n");
        OutputDebugString(desc.Description);
        OutputDebugString(L"\n\n");

    }

    ID3D11Device* device = nullptr; ID3D11DeviceContext* context = nullptr; {

        D3D_FEATURE_LEVEL lvl[] = { D3D_FEATURE_LEVEL_10_0 };
        UINT flag = D3D11_CREATE_DEVICE_DEBUG;

        D3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, flag, lvl, ARRAYSIZE(lvl), D3D11_SDK_VERSION, &device, NULL, &context);

    }

    ID3D11Debug* debug = nullptr; {

        device->QueryInterface(IID_PPV_ARGS(&debug));

    }


    if (context) context->Release();
    if (device) device->Release();
    if (adapter) adapter->Release();
    if (factory) factory->Release();

    debug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL);

    return 0;

}



LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}


But this produces warning :

D3D11 WARNING: Live ID3D11Device at 0x0000020454692FF0, Refcount: 2 [ STATE_CREATION WARNING #441: LIVE_DEVICE]
D3D11 WARNING:  Live ID3D11Context at 0x0000020454695020, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #2097226: LIVE_CONTEXT]
D3D11 WARNING:  Live ID3DDeviceContextState at 0x000002045626F000, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #3145742: LIVE_DEVICECONTEXTSTATE]
D3D11 WARNING:  Live ID3D11BlendState at 0x0000020456266170, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #435: LIVE_BLENDSTATE]
D3D11 WARNING:  Live ID3D11DepthStencilState at 0x0000020456266370, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #436: LIVE_DEPTHSTENCILSTATE]
D3D11 WARNING:  Live ID3D11RasterizerState at 0x0000020456266570, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #437: LIVE_RASTERIZERSTATE]
D3D11 WARNING:  Live ID3D11Sampler at 0x0000020456266780, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #434: LIVE_SAMPLER]
D3D11 WARNING:  Live ID3D11Query at 0x0000020456266E60, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #438: LIVE_QUERY]

I dont't know why those extra objects like gets initialized. I did the release on the device twice and it seemed to work all fine again and I dont' know that happened either.

I would like to know if I made a mistake somewhere because I don't know how COM works internally even a little bit all i knew that I create the object, I release the object.

Yea and I have no idea why this happened, can somone please explain why this happens and what I should do to fix this?

I am using the visual studio community 2019, OS : Windows 64-bit

1

There are 1 answers

0
Simon Mourier On

Your code is fine (just don't forget to do debug->Release too).

The refcount = 0 lines are pretty useless, they are not leaks, and are here obviously created by internal D3D11 code (you don't create a blend state, etc.).

You can also use D3D11_RLDO_DETAIL | D3D11_RLDO_IGNORE_INTERNAL to get rid of some of these.

Now, using this API is notorious to show false positive, "on the edge". Experience shows its common to get 1 or 2 leaks on a device before quitting (probably some internal cache at play). In general, you really want to worry when ReportLiveDeviceObjects results shows big numbers like you get 40 references to something while it should be 0, ie: this API is still useful.

However, when you work with COM objects, I strongly suggest you use any kind of smart pointers technology, there's ATL CComPtr (with Visual Studio), WIL com_ptr, C++/WinRT com_ptr, etc. this is the best way to avoid COM reference leaks.

For example, this code is 100% leak free (with ATL):

#include <atlbase.h>

CComPtr<IDXGIFactory> factory;
CreateDXGIFactory(IID_PPV_ARGS(&factory));

CComPtr<IDXGIAdapter> adapter;
factory->EnumAdapters(0, &adapter);