Thread: An embarrassing ComPtr issue

  1. #1
    Registered User
    Join Date
    Jan 2010
    Posts
    199

    Exclamation An embarrassing ComPtr issue

    Hi there!

    I'm a bit wary of asking this question as it's a bit drawn out and might make me look stupid. But I'll do it anyway

    I have recently come across a line of code in my DirectX12 stuff that got me puzzled. I'll write it as follows:

    Code:
    CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHeapHandle(mRtvHeap->GetCPUDescriptorHandleForHeapStart());
    	for (UINT i = 0; i < SwapChainBufferCount; i++)
    	{
    		ThrowIfFailed(mSwapChain->GetBuffer(i, IID_PPV_ARGS(&mSwapChainBuffer[i])));
    		md3dDevice->CreateRenderTargetView(mSwapChainBuffer[i].Get(), nullptr, rtvHeapHandle);
    		rtvHeapHandle.Offset(1, mRtvDescriptorSize);
    	}
    I've highlighted the part in bold. It's the mSwapChain->GetBuffer function. I know this place isn't graphics dedicated so I'll explain. This code takes an already made descriptor heap and makes the two resources in the swap chain render target views. It iterates through the two descriptors the swap chains uses and creates a render target view to them. It needs a descriptor handle to do this at the start (can't just use an array index). Fair enough I guess.

    But.... what I didn't quite get is why this line was needed because it doesn't seem to really do anything:

    Code:
    ThrowIfFailed(mSwapChain->GetBuffer(i, IID_PPV_ARGS(&mSwapChainBuffer[i])));
    If you look at the original iteration loop all it does is select a resource/buffer from the swap chain and set a render target view to it. Then it does it for the next one (maximum of 2).

    This is where the ComPtr stuff comes in. If I do the following (comment out the GetBuffer() call):

    Code:
    CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHeapHandle(mRtvHeap->GetCPUDescriptorHandleForHeapStart());
    	for (UINT i = 0; i < SwapChainBufferCount; i++)
    	{
    		//ThrowIfFailed(mSwapChain->GetBuffer(i, IID_PPV_ARGS(&mSwapChainBuffer[i])));
    		md3dDevice->CreateRenderTargetView(mSwapChainBuffer[i].Get(), nullptr, rtvHeapHandle);
    		rtvHeapHandle.Offset(1, mRtvDescriptorSize);
    	}
    Then a little further down the lines this function fails:

    Code:
    ThrowIfFailed(md3dDevice->CreateCommittedResource(
            &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
    		D3D12_HEAP_FLAG_NONE,
            &depthStencilDesc,
    		D3D12_RESOURCE_STATE_COMMON,
            &optClear,
            IID_PPV_ARGS(mDepthStencilBuffer.GetAddressOf())));
    Now to be clear where ComPtr stuff is concerned both md3dDevice and mDepthStencilBuffer are ComPtr's. So..... is the original reference to a ComPtr mSwapChain->GetBuffer (which I tried to comment out) making an increment of some kind to the ComPtr which then goes out of scope after the iteration loop, which then allows the further two ComPtr variables to behave normally? Have I screwed up this mechanism by trying to comment out mSwapChain->GetBuffer in the iteration loop?

    I hope I've presented that well and good enough to warrant a reply. Please be gentle though, thanks

  2. #2
    Registered User
    Join Date
    Dec 2017
    Posts
    1,626
    Why do you think this "doesn't seem to really do anything"?
    Code:
    ThrowIfFailed(mSwapChain->GetBuffer(i, IID_PPV_ARGS(&mSwapChainBuffer[i])));
    A little inaccuracy saves tons of explanation. - H.H. Munro

  3. #3
    Registered User
    Join Date
    Jan 2010
    Posts
    199
    I don't know John it just seems to me that it isn't really needed to get a buffer in the swap chain. I thought the iterator was enough to do that in the line:

    Code:
    md3dDevice->CreateRenderTargetView(mSwapChainBuffer[i].Get(), nullptr, rtvHeapHandle);
    The mSwapChainBuffer[i].Get() part returns a pointer to a buffer. I don't see why that isn't enough to do it on it's own. I'm guessing there's something about COM I'm really not understanding here

  4. #4
    Registered User
    Join Date
    Dec 2017
    Posts
    1,626
    I don't think it has anything to do with COM per se. The line you think might not be necessary fills mSwapChainBuffer[i] with valid data. Without that line mSwapChainBuffer[i] will presumably have arbitrary data for the CreateRenderTargetView call. The arbitrary data then presumably causes the subsequent CreateCommittedResource call to fail.
    A little inaccuracy saves tons of explanation. - H.H. Munro

  5. #5
    Registered User
    Join Date
    Jan 2010
    Posts
    199
    Thanks very much (again) John I'll have a look into the code and see if that's the culprit. Cheers

  6. #6
    Registered User
    Join Date
    Jan 2010
    Posts
    199

    Post More info!

    Well I had a bit more of a look and have understood that amazingly (to me anyway) this does not cause a compile error. It causes a run time error.

    The compiler will accept this:

    Code:
    //ThrowIfFailed(mSwapChain->GetBuffer(i, IID_PPV_ARGS(&mSwapChainBuffer[i])));		
    		md3dDevice->CreateRenderTargetView(mSwapChainBuffer[i].Get(), nullptr, rtvHeapHandle);
    		rtvHeapHandle.Offset(1, mRtvDescriptorSize);
    With the mSwapChain->GetBuffer part commented out. The function however:

    Code:
    ThrowIfFailed(md3dDevice->CreateCommittedResource(
            &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
    		D3D12_HEAP_FLAG_NONE,
            &depthStencilDesc,
    		D3D12_RESOURCE_STATE_COMMON,
            &optClear,
            IID_PPV_ARGS(mDepthStencilBuffer.GetAddressOf())));
    fails at run time with a message that there is an issue with the GPU instance. For those who don't know the md3dDevice is a COMPtr of type <ID3D12Device>. Now there's a lot of code between the first function (where I commented out a line) and the second one which causes a run-time failure. All of this runs fine.

    So.... the culprit it seems is indeed...md3dDevice. When i saw the error message stating that the GPU instance (md3dDevice) had been suspended it became a little clearer. By commenting out the mSwapChain->GetBuffer call it appears something has indeed happened with (most likely) a COM reference. That has then screwed up something in the md3dDevice which means when it's called a second time (it compiles ok) it fails at run-time.

    This is actually starting to look like a COMPtr issue. I'll quote the book I'm reading as follows with regards to the mSwapChain->GetBuffer call:

    The call to IDXGISwapChain::GetBuffer increases the COM reference count to the back buffer, so we must Release it when we are finished with it.

    To those who don't know the IDXGISwapChain contains two buffers which are used in graphics rendering. One is the front buffer one is the back buffer. Their pointers are swapped each time a frame is rendered so nothing is ever seen being drawn on screen. It's all drawn to the back buffer which is then presented to the monitor (display output).

    But that's by the by. What isn't by the by is that if this function is called:

    Code:
    md3dDevice->CreateRenderTargetView(mSwapChainBuffer[i].Get(), nullptr, rtvHeapHandle);
    And this preceding line is not executed:

    Code:
    ThrowIfFailed(mSwapChain->GetBuffer(i, IID_PPV_ARGS(&mSwapChainBuffer[i])));
    the code compiles but buggers up the md3dDevice instance when then causes the following function:

    Code:
    ThrowIfFailed(md3dDevice->CreateCommittedResource(
            &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
    		D3D12_HEAP_FLAG_NONE,
            &depthStencilDesc,
    		D3D12_RESOURCE_STATE_COMMON,
            &optClear,
            IID_PPV_ARGS(mDepthStencilBuffer.GetAddressOf())));
    to fail at run time.

    At this moment I've no idea why but I will keep trying to find out what this is and I'll post updates when/if I make any progress. I don't really expect any more replies from anyone I just think I should try and follow up myself on a question I've asked.

    Well.. thanks John for replying and to anyone else who reads this cheers

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Hi i have a little issue
    By eyalfish in forum C Programming
    Replies: 1
    Last Post: 04-11-2015, 09:44 AM
  2. 32/64 bit issue
    By jcfuller in forum C Programming
    Replies: 4
    Last Post: 04-27-2014, 01:42 PM
  3. Another big issue
    By albireo in forum C++ Programming
    Replies: 40
    Last Post: 03-22-2014, 05:24 PM
  4. bandwidth issue / network issue with wireless device communication
    By vlrk in forum Networking/Device Communication
    Replies: 0
    Last Post: 07-05-2010, 11:52 PM
  5. DNS issue
    By George2 in forum C# Programming
    Replies: 1
    Last Post: 08-02-2008, 10:15 AM

Tags for this Thread