2
\$\begingroup\$

On direct3d_11.1 initialisation the swapchain is resized to the desired proportions but after the getting the backbuffer it isn't released. I check the return value and check its address which doesn't get nullified. It can't for the life of me see why/what is holding itself live. Do you know of any clever ways of determining this? I have done a solution-search for all places I use the swapchain. Which was Direct2d class - but I don't instantiate it anymore.

Here is a snippet of the onresize function which is called once at the end of the initialisation and once during WM_SIZE. Yes I know I need to release all outstanding references but the backbuffer won't release. Neither, for that matter, will a few depthstencilstates. Where should I look? How do I find it? Is there something that tells you what the references are?

VS Output says swapchain cannot resize due to outstanding references. The number of references is 2 after getting the backbuffer and continues to be so even after the pBackbuffer->release request.

    try
{
    assert(m_spD3DImmediateContext);
    assert(m_spD3DDevice);
    assert(m_spSwapChain);

    //ReleaseCOM(m_pRenderTargetView);
    //ReleaseCOM(m_pDepthStencilView);
    //ReleaseCOM(m_spDepthStencilBuffer);
    //m_spRenderTargetView.Reset();
    //m_spDepthStencilView.Reset();
    //m_spDepthStencilBuffer.Reset();
    //m_spDepthDisabledStencilState.Reset();

    // This is used to monitor the reference count
    auto Myref = m_spSwapChain->AddRef();
    Myref = m_spSwapChain->Release();

    ULONG RefCount = 0;


    //CRenderStates::ResetAll();

    //if (m_spDepthEnabledStencilState)
    //  RefCount = m_spDepthEnabledStencilState->Release();
    ////assert(RefCount == 0); // FAIL
    //if (m_spDepthDisabledStencilState)
    //  RefCount = m_spDepthDisabledStencilState->Release();
    //assert(RefCount == 0);   // FAIL   

    m_spD3DImmediateContext->OMSetRenderTargets(0, 0, 0);   

    if (m_spDepthStencilView)
        RefCount = m_spDepthStencilView->Release();
    assert(RefCount == 0); // OK
    if (m_spDepthStencilBuffer)
        RefCount = m_spDepthStencilBuffer->Release();
    assert(RefCount == 0); // OK
    if (m_spRenderTargetView)
        RefCount = m_spRenderTargetView->Release();
    assert(RefCount == 0); // OK

    //m_spRenderTargetView.Reset();
    //m_spDepthStencilView.Reset();
    //m_spDepthStencilBuffer.Reset();
    //m_spDepthDisabledStencilState.Reset();

    //assert(m_spRenderTargetView == nullptr);
    //assert(m_spDepthStencilView == nullptr);
    //assert(m_spDepthStencilBuffer == nullptr);
    //assert(m_spDepthDisabledStencilState == nullptr);

    Myref = m_spSwapChain->AddRef();
    Myref = m_spSwapChain->Release();

    // **** Fails Here after WM_SIZE ****
    // Resize the swap chain and recreate the render target view.
    COMERR(m_spSwapChain->ResizeBuffers(1, m_iClientWidth, m_iClientHeight, DXGI_FORMAT_R8G8B8A8_UNORM, 0),
        "CD3DObject::OnResize() SwapChain Could not resize.");
    ID3D11Texture2D* pBackBuffer;
    COMERR(m_spSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&pBackBuffer)),
        "CD3DObject::OnResize() SwapChain could not get backbuffer 0.");
    COMERR(m_spD3DDevice->CreateRenderTargetView(pBackBuffer, 0, m_spRenderTargetView.GetAddressOf()),
        "CD3DObject::OnResize() Could not re-create render target view.");

    Myref = m_spSwapChain->AddRef();
    Myref = m_spSwapChain->Release();

    //ReleaseCOM(pBackBuffer);
    RefCount = pBackBuffer->Release();

    Myref = m_spSwapChain->AddRef();
    Myref = m_spSwapChain->Release();

    // **SNIP**

Note: The COMERR macros are for exception handling the return values.enter code here. Thank you for any help or wisdom on this.

EDIT

This is the InitDirect3D function:

//CALLSTACK_PUT("CD3DObject::InitDirect3D")

//UINT uiCreateDeviceFlags = 0;
// This flag adds support for surfaces with a different color channel ordering
// than the API default. It is required for compatibility with Direct2D.
UINT uiCreateDeviceFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; // Interop
#if defined(DEBUG) || defined(_DEBUG)  
uiCreateDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif

// Set feature levels supported by our application
D3D_FEATURE_LEVEL eFeatureLevel1[] =
{
    D3D_FEATURE_LEVEL_11_1,
    D3D_FEATURE_LEVEL_11_0,
    D3D_FEATURE_LEVEL_10_1,
    D3D_FEATURE_LEVEL_10_0,
    D3D_FEATURE_LEVEL_9_3,
    D3D_FEATURE_LEVEL_9_2,
    D3D_FEATURE_LEVEL_9_1
};

// Create Direct3D device and context
ComPtr<ID3D11Device>        spDevice;
ComPtr<ID3D11DeviceContext> spContext;
D3D_FEATURE_LEVEL           stReturnedFeatureLevel;
LOGADDRESS_SP(spDevice.GetAddressOf());
LOGADDRESS_SP(spContext.GetAddressOf());


COMERR(D3D11CreateDevice(nullptr,                   // default adapter
                         D3D_DRIVER_TYPE_HARDWARE, 
                         0,                         // no software device
                         uiCreateDeviceFlags, 
                         eFeatureLevel1, 
                         ARRAYSIZE(eFeatureLevel1), 
                         D3D11_SDK_VERSION,
                         &spDevice, 
                         &stReturnedFeatureLevel, 
                         &spContext),
    "CD3DObject::InitDirect3D()\nD3D11.1 Could not create device.");

if(stReturnedFeatureLevel < D3D_FEATURE_LEVEL_11_0)
{
    MessageBox(m_hMainWnd, "CD3DObject::InitDirect3D()\nThis software needs DirectX 11.1 and is unsupported by your computer.", "Error", MB_OK);
    return false;
}

// Fetch the underlying interfaces and store them:
COMERR(spDevice.As(&m_spD3DDevice), "CD3DObject::InitDirect3D()\nCould not get device as DirectX 11.1.");
COMERR(spContext.As(&m_spD3DImmediateContext), "CD3DObject::InitDirect3D()\nCould not get Context as DirectX 11.1.");

spDevice->Release();
spContext->Release();

LOGADDRESS_SP(m_spD3DDevice.GetAddressOf());
LOGADDRESS_SP(m_spD3DImmediateContext.GetAddressOf());

// This is the earliest the Debug Layer can be created
g_pEngine->CreateDebugLayer();
g_pEngine->GetDebug()->ReportLiveDeviceObjects(D3D11_RLDO_SUMMARY | D3D11_RLDO_DETAIL);


// Set private data
SETPRIVATEDATA(spDevice, "spDevice");
SETPRIVATEDATA(m_spD3DDevice, "CD3DObject::m_spD3DDevice");

HR(m_spD3DDevice->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, 
                                              4, 
                                              &m_ui4xMsaaQuality));
assert(m_ui4xMsaaQuality > 0);

DXGI_SWAP_CHAIN_DESC1 stSwpChainDesc = { 0 };
stSwpChainDesc.Width = 0;
stSwpChainDesc.Height             = 0;
stSwpChainDesc.Format             = DXGI_FORMAT_B8G8R8A8_UNORM;
stSwpChainDesc.Stereo             = false;
stSwpChainDesc.SampleDesc.Count   = 1;
stSwpChainDesc.SampleDesc.Quality = 0;
stSwpChainDesc.BufferUsage        = DXGI_USAGE_RENDER_TARGET_OUTPUT;
stSwpChainDesc.BufferCount        = 1;                                  // Used to be 1
stSwpChainDesc.Scaling            = DXGI_SCALING_STRETCH;
stSwpChainDesc.SwapEffect         = DXGI_SWAP_EFFECT_DISCARD;
stSwpChainDesc.Flags              = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
LOGADDRESS(stSwpChainDesc);

// Use 4X MSAA? 
if(m_bEnable4xMsaa)
{
    stSwpChainDesc.SampleDesc.Count   = 4;
    stSwpChainDesc.SampleDesc.Quality = m_ui4xMsaaQuality-1;
}
// No MSAA
else
{
    stSwpChainDesc.SampleDesc.Count   = 1;
    stSwpChainDesc.SampleDesc.Quality = 0;
}

Microsoft::WRL::ComPtr<IDXGIDevice> spDXGIDevice;
m_spD3DDevice.As(&spDXGIDevice);

IDXGIAdapter* pDxgiAdapter = 0;
HR(spDXGIDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&pDxgiAdapter));

IDXGIFactory2* pDxgiFactory = 0;
HR(pDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&pDxgiFactory));
pDxgiFactory->CreateSwapChainForHwnd(m_spD3DDevice.Get(), m_hMainWnd, &stSwpChainDesc, nullptr, nullptr, &m_spSwapChain);

g_pEngine->GetDebug()->ReportLiveDeviceObjects(D3D11_RLDO_SUMMARY | D3D11_RLDO_DETAIL);

ReleaseCOM(pDxgiAdapter);
ReleaseCOM(pDxgiFactory);

spDXGIDevice->Release();

LOGADDRESS_SP(spDXGIDevice.GetAddressOf());
LOGADDRESS_SP(pDxgiAdapter);
LOGADDRESS_SP(pDxgiFactory);

g_pEngine->GetDebug()->ReportLiveDeviceObjects(D3D11_RLDO_SUMMARY | D3D11_RLDO_DETAIL);

OnResize();

SETPRIVATEDATA(m_spD3DImmediateContext, "CD3DObject::m_spD3DImmediateContext");
SETPRIVATEDATA(m_spSwapChain,           "CD3DObject::m_spSwapChain");
SETPRIVATEDATA(m_spDepthStencilBuffer,  "CD3DObject::m_spDepthStencilBuffer");
SETPRIVATEDATA(m_spRenderTargetView,    "CD3DObject::m_spRenderTargetView");
SETPRIVATEDATA(m_spDepthStencilView,    "CD3DObject::m_spDepthStencilView");
SETPRIVATEDATA(m_spDepthEnabledStencilState,  "CD3DObject::m_spDepthEnabledStencilState");
SETPRIVATEDATA(m_spDepthDisabledStencilState, "CD3DObject::m_spDepthDisabledStencilState");
//CALLSTACK_REMOVE

This is the ONResize function: Note that the reason I do so many Debug reports is to compare them before and after ->release-ing (etc).

    //CALLSTACK_PUT("CD3DObject::OnResize")
try
{
    assert(m_spD3DImmediateContext);
    assert(m_spD3DDevice);
    assert(m_spSwapChain);

    //ReleaseCOM(m_pRenderTargetView);
    //ReleaseCOM(m_pDepthStencilView);
    //ReleaseCOM(m_spDepthStencilBuffer);
    //m_spRenderTargetView.Reset();
    //m_spDepthStencilView.Reset();
    //m_spDepthStencilBuffer.Reset();
    //m_spDepthDisabledStencilState.Reset();

    // This is used to monitor the reference count
    auto Myref = m_spSwapChain->AddRef();
    Myref = m_spSwapChain->Release();

    ULONG RefCount = 0;
    m_spD3DImmediateContext->ClearState();

    CRenderStates::ResetAll();

    if (m_spDepthEnabledStencilState)
        RefCount = m_spDepthEnabledStencilState->Release();
    assert(RefCount == 0); // FAILS == 1
    if (m_spDepthDisabledStencilState)
        RefCount = m_spDepthDisabledStencilState->Release();
    assert(RefCount == 0); // FAILS == 1
    if (m_spDepthEnabledStencilState)
        RefCount = m_spDepthEnabledStencilState->Release();
    assert(RefCount == 0); // OK == 0
    if (m_spDepthDisabledStencilState)
        RefCount = m_spDepthDisabledStencilState->Release();
    assert(RefCount == 0); // OK == 0

    m_spD3DImmediateContext->OMSetRenderTargets(0, 0, 0);

    if (m_spDepthStencilView)
        RefCount = m_spDepthStencilView->Release();
    assert(RefCount == 0);
    if (m_spDepthStencilBuffer)
        RefCount = m_spDepthStencilBuffer->Release();
    assert(RefCount == 0);
    if (m_spRenderTargetView)
        RefCount = m_spRenderTargetView->Release();
    assert(RefCount == 0);

    //m_spRenderTargetView.Reset();
    //m_spDepthStencilView.Reset();
    //m_spDepthStencilBuffer.Reset();
    //m_spDepthDisabledStencilState.Reset();

    //assert(m_spRenderTargetView == nullptr);
    //assert(m_spDepthStencilView == nullptr);
    //assert(m_spDepthStencilBuffer == nullptr);
    //assert(m_spDepthDisabledStencilState == nullptr);

    //LOGADDRESS_SP(m_spD3DImmediateContext.GetAddressOf());
    //LOGADDRESS_SP(m_spSwapChain.GetAddressOf());
    //LOGADDRESS_SP(m_spDepthStencilBuffer.GetAddressOf());
    //LOGADDRESS_SP(m_spRenderTargetView.GetAddressOf());
    //LOGADDRESS_SP(m_spDepthStencilView.GetAddressOf());
    //LOGADDRESS_SP(m_spDepthEnabledStencilState.GetAddressOf());
    //LOGADDRESS_SP(m_spDepthDisabledStencilState.GetAddressOf());
    //LOGADDRESS_SP(m_spSwapChain.GetAddressOf());
    LOGADDRESS_SP(m_spD3DDevice.Get());
    LOGADDRESS_SP(m_spD3DImmediateContext.Get());
    LOGADDRESS_SP(m_spSwapChain.Get());
    LOGADDRESS_SP(m_spDepthStencilBuffer.Get());
    LOGADDRESS_SP(m_spRenderTargetView.Get());
    LOGADDRESS_SP(m_spDepthStencilView.Get());
    LOGADDRESS_SP(m_spDepthEnabledStencilState.Get());
    LOGADDRESS_SP(m_spDepthDisabledStencilState.Get());
    LOGADDRESS_SP(m_spSwapChain.Get());

    Myref = m_spSwapChain->AddRef();
    Myref = m_spSwapChain->Release();

    g_pEngine->GetDebug()->ReportLiveDeviceObjects(D3D11_RLDO_SUMMARY | D3D11_RLDO_DETAIL);

    // Resize the swap chain and recreate the render target view.
    COMERR(m_spSwapChain->ResizeBuffers(1, m_iClientWidth, m_iClientHeight, DXGI_FORMAT_R8G8B8A8_UNORM, 0),
        "CD3DObject::OnResize() SwapChain Could not resize.");
    ID3D11Texture2D* pBackBuffer;
    COMERR(m_spSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&pBackBuffer)),
        "CD3DObject::OnResize() SwapChain could not get backbuffer 0.");
    COMERR(m_spD3DDevice->CreateRenderTargetView(pBackBuffer, 0, m_spRenderTargetView.GetAddressOf()),
        "CD3DObject::OnResize() Could not re-create render target view.");

    g_pEngine->GetDebug()->ReportLiveDeviceObjects(D3D11_RLDO_SUMMARY | D3D11_RLDO_DETAIL);

    Myref = m_spSwapChain->AddRef();
    Myref = m_spSwapChain->Release();

    //ReleaseCOM(pBackBuffer);
    LOGADDRESS_SP(pBackBuffer);
    RefCount = pBackBuffer->Release();
    RefCount = pBackBuffer->Release();
    LOGADDRESS_SP(pBackBuffer);
    //assert(RefCount == 0);

    g_pEngine->GetDebug()->ReportLiveDeviceObjects(D3D11_RLDO_SUMMARY | D3D11_RLDO_DETAIL);

    Myref = m_spSwapChain->AddRef();
    Myref = m_spSwapChain->Release();

    // Create the depth/stencil buffer and view.
    D3D11_TEXTURE2D_DESC stDepthStencilDesc;

    stDepthStencilDesc.Width = m_iClientWidth;                // Width of texture in texels
    stDepthStencilDesc.Height = m_iClientHeight;                  // Hieght of texture in texels
    stDepthStencilDesc.MipLevels = 1;                             // Mipmap levels
    stDepthStencilDesc.ArraySize = 1;                             // Number of textures in a texture array
    stDepthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; // 24bits depth [0,1] 8 bits stencil [0,255] 

    // Use 4X MSAA? --must match swap chain MSAA values.
    // AD This is set to false in this constructor.
    if (m_bEnable4xMsaa)
    {
        stDepthStencilDesc.SampleDesc.Count = 4;
        stDepthStencilDesc.SampleDesc.Quality = m_ui4xMsaaQuality - 1;
    }
    // No MSAA
    else
    {
        stDepthStencilDesc.SampleDesc.Count = 1;
        stDepthStencilDesc.SampleDesc.Quality = 0;
    }

    stDepthStencilDesc.Usage = D3D11_USAGE_DEFAULT;   // Texture is: GPU only Read/Write
    stDepthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; // How the texture is bound to the pipeline
    stDepthStencilDesc.CPUAccessFlags = 0;                        // How CPU will access the texture
    stDepthStencilDesc.MiscFlags = 0;                         // Optional - N/A to depth/stencil buffer

    //ID3D11Texture2D* pDSB = m_spDepthStencilBuffer.GetInterfacePtr();
    COMERR(m_spD3DDevice->CreateTexture2D(&stDepthStencilDesc,       // Description of texture to create
        0,                         // Pointer to initial data to fill texture with 
        //m_spDepthStencilBuffer.ReleaseAndGetAddressOf())); // Return pointer to depth/stencil buffer
        m_spDepthStencilBuffer.GetAddressOf()), // Return pointer to depth/stencil buffer
        //&pDSB));                   // Return pointer to depth/stencil buffer
        "CD3DObject::OnResize() Could not create 2D Texture.");

    assert(m_spDepthStencilBuffer);

    //ID3D11DepthStencilView* pDSV = m_spDepthStencilView.GetInterfacePtr();
    COMERR(m_spD3DDevice->CreateDepthStencilView(m_spDepthStencilBuffer.Get(),  // Resource we want to create as view to
        0,                       // Null if we already specified the data type of this d/s buffer 
        m_spDepthStencilView.GetAddressOf()), // Return depth/stencil view
        //&pDSV));                 // Return depth/stencil view
        "CD3DObject::OnResize() Could not create depth stencil view.");

    assert(m_spDepthStencilView);

    //ID3D11RenderTargetView* pRTV = m_spRenderTargetView.GetInterfacePtr();
    // Bind to the 'Output Merger' Stage
    // Bind the render target view and depth/stencil view to the pipeline.
    m_spD3DImmediateContext->OMSetRenderTargets(1,                     // Number of render targets we are binding
        m_spRenderTargetView.GetAddressOf(), // First of array of render target views
        //&pRTV,                 // First of array of render target views
        m_spDepthStencilView.Get()); // Pointer to the d/s view to bind

    //assert(m_spRenderTargetView);
    //assert(pRTV);
    //assert(m_spDepthStencilView);

    // Set the viewport transform.
    m_ScreenViewport.TopLeftX = 0;
    m_ScreenViewport.TopLeftY = 0;
    m_ScreenViewport.Width = static_cast<float>(m_iClientWidth);
    m_ScreenViewport.Height = static_cast<float>(m_iClientHeight);
    m_ScreenViewport.MinDepth = 0.0f;
    m_ScreenViewport.MaxDepth = 1.0f;

    m_spD3DImmediateContext->RSSetViewports(1, &m_ScreenViewport);

    /**** ****** ****** ******* ******* ***** **/
    //      (Re) create the DepthEnabledStencilState &
    //      DepthDisabledStencilState
    /**** ****** ****** ******* ******* ***** **/

    D3D11_DEPTH_STENCIL_DESC stDepthEnabledStencilDesc;

    // Initialize the description of the stencil state.
    ZeroMemory(&stDepthEnabledStencilDesc, sizeof(stDepthEnabledStencilDesc));

    // Set up the description of the stencil state.
    stDepthEnabledStencilDesc.DepthEnable = true;
    stDepthEnabledStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
    stDepthEnabledStencilDesc.DepthFunc = D3D11_COMPARISON_LESS;

    stDepthEnabledStencilDesc.StencilEnable = true;
    stDepthEnabledStencilDesc.StencilReadMask = 0xFF;
    stDepthEnabledStencilDesc.StencilWriteMask = 0xFF;

    // Stencil operations if pixel is front-facing.
    stDepthEnabledStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
    stDepthEnabledStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
    stDepthEnabledStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
    stDepthEnabledStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;

    // Stencil operations if pixel is back-facing.
    stDepthEnabledStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
    stDepthEnabledStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
    stDepthEnabledStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
    stDepthEnabledStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;

    // Create the depth stencil state.
    COMERR(m_spD3DDevice.Get()->CreateDepthStencilState(&stDepthEnabledStencilDesc,
        m_spDepthEnabledStencilState.GetAddressOf()),
        "CD3DObject::OnResize() Could not create depth 'enabled' stencil state.");

    // Set the depth stencil state.
    m_spD3DImmediateContext.Get()->OMSetDepthStencilState(m_spDepthEnabledStencilState.Get(), 1);

    /* ***  **  *** ** *** ** *** ** *** ** *** **
    Initialise the Disabled depth stencil state
    */ // ***  **  *** ** *** ** *** ** *** ** *** 

    D3D11_DEPTH_STENCIL_DESC stDepthDisabledStencilDesc;

    /*
    Here we setup the description of the depth stencil.
    Notice the only difference between this new depth stencil
    and the old one is the DepthEnable is set to false here
    for 2D drawing.
    */

    // Clear the second depth stencil state before setting the parameters.
    ZeroMemory(&stDepthDisabledStencilDesc, sizeof(stDepthDisabledStencilDesc));

    // Now create a second depth stencil state which turns off the Z buffer for 2D rendering.  The only difference is 
    // that DepthEnable is set to false, all other parameters are the same as the other depth stencil state.
    stDepthDisabledStencilDesc.DepthEnable = false;
    stDepthDisabledStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
    stDepthDisabledStencilDesc.DepthFunc = D3D11_COMPARISON_LESS;
    stDepthDisabledStencilDesc.StencilEnable = true;
    stDepthDisabledStencilDesc.StencilReadMask = 0xFF;
    stDepthDisabledStencilDesc.StencilWriteMask = 0xFF;
    stDepthDisabledStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
    stDepthDisabledStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
    stDepthDisabledStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
    stDepthDisabledStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
    stDepthDisabledStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
    stDepthDisabledStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
    stDepthDisabledStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
    stDepthDisabledStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;

    // Create the state using the device.
    COMERR(m_spD3DDevice.Get()->CreateDepthStencilState(&stDepthDisabledStencilDesc,
        m_spDepthDisabledStencilState.GetAddressOf()),
        "CD3DObject::OnResize() Could not create depth disabled stencil state.");

}
catch (CException e)
{
    e.ExceptionMsgBox();
    exit(E_FAIL);
}
catch (std::exception e)
{
    CException x(e.what(), __FILE__, S__LINE__, (HRESULT)0);
    x.ExceptionMsgBox();
    exit(E_FAIL);
}
//CALLSTACK_REMOVE

Here is the DebugReport - right when OnResize is called - not the first time but during a WM_SIZE - once the user has resized the window. Report right before the swapchain resize:

D3D11 WARNING: Live ID3D11Device at 0x000000000031D8C0, Name: CD3DObject::m_spD3DDevice, Refcount: 8 [ STATE_CREATION WARNING #441: LIVE_DEVICE] D3D11 WARNING: Live ID3D11Context at 0x0000000000323A00, Name: CD3DObject::m_spD3DImmediateContext, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #2097226: LIVE_CONTEXT] D3D11 WARNING: Live ID3DDeviceContextState at 0x000000000033B7A0, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #3145742: LIVE_DEVICECONTEXTSTATE] D3D11 WARNING: Live ID3D11BlendState at 0x0000000000346B00, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #435: LIVE_BLENDSTATE] D3D11 WARNING: Live ID3D11DepthStencilState at 0x00000000003470C0, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #436: LIVE_DEPTHSTENCILSTATE] D3D11 WARNING: Live ID3D11RasterizerState at 0x00000000003472E0, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #437: LIVE_RASTERIZERSTATE] D3D11 WARNING: Live ID3D11Sampler at 0x0000000000347600, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #434: LIVE_SAMPLER] D3D11 WARNING: Live ID3D11Query at 0x0000000000347880, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #438: LIVE_QUERY] D3D11 WARNING: Live IDXGISwapChain at 0x0000000000347A60, Name: CD3DObject::m_spSwapChain, Refcount: 1 [ STATE_CREATION WARNING #442: LIVE_SWAPCHAIN] D3D11 WARNING: Live ID3D11Texture2D at 0x00000000003481C0, Refcount: 0, IntRef: 2 [ STATE_CREATION WARNING #425: LIVE_TEXTURE2D] D3D11 WARNING: Live ID3D11RenderTargetView at 0x00000000003487D0, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #428: LIVE_RENDERTARGETVIEW] D3D11 WARNING: Live ID3D11RenderTargetView at 0x0000000000348BD0, Name: CD3DObject::m_spRenderTargetView, Refcount: 0, IntRef: 0 [ STATE_CREATION WARNING #428: LIVE_RENDERTARGETVIEW] D3D11 WARNING: Live ID3D11Texture2D at 0x0000000000348DF0, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #425: LIVE_TEXTURE2D] D3D11 WARNING: Live ID3D11Texture2D at 0x0000000000349170, Name: CD3DObject::m_spDepthStencilBuffer, Refcount: 0, IntRef: 2 [ STATE_CREATION WARNING #425: LIVE_TEXTURE2D] D3D11 WARNING: Live ID3D11DepthStencilView at 0x00000000003494F0, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #429: LIVE_DEPTHSTENCILVIEW] D3D11 WARNING: Live ID3D11DepthStencilView at 0x0000000000349720, Name: CD3DObject::m_spDepthStencilView, Refcount: 0, IntRef: 0 [ STATE_CREATION WARNING #429: LIVE_DEPTHSTENCILVIEW] D3D11 WARNING: Live ID3D11DepthStencilState at 0x00000000003499A0, Name: CD3DObject::m_spDepthEnabledStencilState, Refcount: 0, IntRef: 0 [ STATE_CREATION WARNING #436: LIVE_DEPTHSTENCILSTATE] D3D11 WARNING: Live ID3D11Texture2D at 0x000000000034EAB0, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #425: LIVE_TEXTURE2D] D3D11 WARNING: Live ID3D11Context : 1 [ STATE_CREATION WARNING #422: LIVE_OBJECT_SUMMARY] D3D11 WARNING: Live ID3DDeviceContextState : 1 [ STATE_CREATION WARNING #422: LIVE_OBJECT_SUMMARY] D3D11 WARNING: Live ID3D11BlendState : 1 [ STATE_CREATION WARNING #422: LIVE_OBJECT_SUMMARY] D3D11 WARNING: Live ID3D11DepthStencilState : 2 [ STATE_CREATION WARNING #422: LIVE_OBJECT_SUMMARY] D3D11 WARNING: Live ID3D11RasterizerState : 1 [ STATE_CREATION WARNING #422: LIVE_OBJECT_SUMMARY] D3D11 WARNING: Live ID3D11Sampler : 1 [ STATE_CREATION WARNING #422: LIVE_OBJECT_SUMMARY] D3D11 WARNING: Live ID3D11Query : 1 [ STATE_CREATION WARNING #422: LIVE_OBJECT_SUMMARY] D3D11 WARNING: Live IDXGISwapChain : 1 [ STATE_CREATION WARNING #422: LIVE_OBJECT_SUMMARY] D3D11 WARNING: Live ID3D11Texture2D : 4 [ STATE_CREATION WARNING #422: LIVE_OBJECT_SUMMARY] D3D11 WARNING: Live ID3D11RenderTargetView : 2 [ STATE_CREATION WARNING #422: LIVE_OBJECT_SUMMARY] D3D11 WARNING: Live ID3D11DepthStencilView : 2 [ STATE_CREATION WARNING #422: LIVE_OBJECT_SUMMARY]

\$\endgroup\$
6
  • \$\begingroup\$ Note that the return value from AddRef/Release is "for debugging purposes only." Also you may want to consider using smart COM pointers (like CComPtr or shared_ptr with an appropriate deleter) to manage your COM objects as it can help prevent accidentally forgetting a Release somewhere. \$\endgroup\$
    – user1430
    Feb 19 '15 at 17:44
  • \$\begingroup\$ I recommend using Microsoft::WRL::ComPtr. See Smart Pointers and ComPtr. \$\endgroup\$ Feb 19 '15 at 19:25
  • \$\begingroup\$ @Chuck Walbourn Thanks. I am already using ComPtr. Trying to understand why there is an extra RenderTargetView. Is one for the front buffer and one for the back buffer? \$\endgroup\$
    – Elixir
    Feb 19 '15 at 21:30
  • \$\begingroup\$ Try changing m_spRenderTargetView.GetAddressOf() to m_spRenderTargetView.ReleaseAndGetAddressOf() \$\endgroup\$ Feb 20 '15 at 6:59
  • \$\begingroup\$ @Chuck Walbourn That just breaks because I've already released it and asserted the return value. The other RenderTargetView is at a different address. Is there a way to find a variable from its address in code? I wrote a Macro to Log the addresses as I create objects. I am not creating anything now just displaying a screen. I will edit my post to show how I initialise DX11.1 and also the reported debug information. \$\endgroup\$
    – Elixir
    Feb 21 '15 at 5:14
4
\$\begingroup\$

The ID3D11Debug interface allows you to ReportLiveObjects, which is a useful way to acquire a breakdown of the live D3D objects at any given point in time. This report will show you the total reference count to an interface, broken down into the external (your) and internal (D3D's) numbers. This will let you confirm that

  • you have actually released all your references to an object at a given point in time and,
  • if D3D is still holding a reference to an object internally

The latter may mean that you are holding a reference to an interface which itself, internally, holds a reference to the swap chain.

To get an ID3D11Debug interface, use QueryInterface on your device object using the IID_ID3D11Debug ID. Then call ReportLiveObjects on the resulting interface using the D3D11_RLDO_DETAIL flag. Note that you must also have enabled the debug layer when creating the device itself.

The output will consist of a lot of lines like:

D3D11 WARNING:  Live <type> at <address>, Refcount: X, IntRef: Y [STATE_CREATION WARNING #nnn: LIVE_<type>]

This shows you the object type, it's address, external and internal reference count.

You should always get at least some output from this function when you call it, because the debug interface itself (and thus the device) will be alive and thus reported. Unfortunately there is no way to get a report on the specific interfaces holding a given interface alive, you simply have to work backwards manually through the report.

\$\endgroup\$
2
  • \$\begingroup\$ Thanks. I used live reporting to show that I am in fact failing to produce DX11.1 for some reason. Defaulting to 11.0. Also right after the GetBuffer it shows live: 2x swapchains and 2x ID3D11Texture2D at the same address. Also I have 2x ID3D11RenderTargetView at different addresses. The attempt to release the backbuffer does in fact delete only one of the ID3D11Texture2D. Is the reason that there was a doubling due to the way I create the 11.1 device? (with 1 class level id3d11device1 and 1 function scope id3d11device - that is explicitly released as well)? \$\endgroup\$
    – Elixir
    Feb 19 '15 at 20:52
  • \$\begingroup\$ Oh yes my graphics card is only 11.0 thats why. So ignore the beginning of my question. :) \$\endgroup\$
    – Elixir
    Feb 19 '15 at 21:00
0
\$\begingroup\$

I think the problem is your use of m_spD3DImmediateContext->OMSetRenderTargets(0, 0, 0); which doesn't do anything at all to the render target view binding--it just clears the depth/stencil view. To clear the render target settings, you should use the following assuming you aren't using Multiple Render Targets (MRTs):

ID3D11RenderTargetView* nullViews [] = { nullptr };
m_spD3DImmediateContext->OMSetRenderTargets(1, nullViews, nullptr);

If you are using MRTs, you may need as many nullViews entries as you have maximum MRTs with a worst case of:

ID3D11RenderTargetView* nullViews [D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT] = { 0 };
m_spD3DImmediateContext->OMSetRenderTargets(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT, nullViews, nullptr);

However, it is probably sufficient to do the first form assuming you never bind the swapchain backbuffer RTV anywhere but the 0th slot.

Also, be sure to use the following just before you start doing the swap chain resize:

m_spD3DImmediateContext->Flush();

This is actually noted on MSDN as a critical step for resizing because of deferred destruction of objects.

If you look at the code for handling resize in the Direct3D Win32 Game Visual Studio template, you'll see that I do the following sequence before the use of DXGI's ResizeBuffers for resizing the swap chain:

// Clear the previous window size specific context.
ID3D11RenderTargetView* nullViews [] = { nullptr };
m_d3dContext->OMSetRenderTargets(ARRAYSIZE(nullViews), nullViews, nullptr);
m_renderTargetView.Reset();
m_depthStencilView.Reset();
m_d3dContext->Flush();
\$\endgroup\$
0
\$\begingroup\$

The actual answer I found it to be was based on a cumulation of both Josh Petrie's and Chuck Walbourn's answer/comments. Using LiveReporting both before and after each call in the resize function I was able to determine the area of the problem - Which was the extra Texture2D being created. It turns out that (I think) the ComPtr somehow instatiates one just by creating the pointer. Most likely statically.

ComPtr<ID3D11Texture2D> spBackBuffer;

Then I call ReleaseAndGetAddressOf() not only on the spBackBuffer but also on the RenderTargetView (Partial Qudos to the great and powerful Chuck Walbourn). For some reason the DepthBuffer and DepthView do not need it. They are released in the first instance before the resize anyway.

    g_pEngine->GetDebug()->ReportLiveDeviceObjects(D3D11_RLDO_SUMMARY | D3D11_RLDO_DETAIL);
    // Resize the swap chain and recreate the render target view.
    COMERR(m_spSwapChain->ResizeBuffers(1, m_iClientWidth, m_iClientHeight, DXGI_FORMAT_R8G8B8A8_UNORM, 0),
        "CD3DObject::OnResize() SwapChain Could not resize.");
    g_pEngine->GetDebug()->ReportLiveDeviceObjects(D3D11_RLDO_SUMMARY | D3D11_RLDO_DETAIL);
    //ID3D11Texture2D* pBackBuffer;
    ComPtr<ID3D11Texture2D> spBackBuffer;
    //COMERR(m_spSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&pBackBuffer)),
    COMERR(m_spSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(spBackBuffer.ReleaseAndGetAddressOf())),
        "CD3DObject::OnResize() SwapChain could not get backbuffer 0.");
    g_pEngine->GetDebug()->ReportLiveDeviceObjects(D3D11_RLDO_SUMMARY | D3D11_RLDO_DETAIL);
    //COMERR(m_spD3DDevice->CreateRenderTargetView(pBackBuffer, 0, m_spRenderTargetView.ReleaseAndGetAddressOf()),
    COMERR(m_spD3DDevice->CreateRenderTargetView(spBackBuffer.Get(), 0, m_spRenderTargetView.ReleaseAndGetAddressOf()),
        "CD3DObject::OnResize() Could not re-create render target view.");
    g_pEngine->GetDebug()->ReportLiveDeviceObjects(D3D11_RLDO_SUMMARY | D3D11_RLDO_DETAIL);

After the WM_SIZE and resize is called, the LiveReport (detail not summary) shows what outstanding objects need to be released. Internal refs are ok its the external ones I needed to worry about. Ideally all the DepthStates/DepthView/DepthBuffer/RenderTarget and hey presto resizing worked.

Thank you all that helped - I really learned a lot be going over this.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.