microsoft / DirectX-Graphics-Samples

This repo contains the DirectX Graphics samples that demonstrate how to build graphics intensive applications on Windows.
MIT License
6k stars 2.02k forks source link

Creating and using array of ComPtr objects #753

Closed DTL2020 closed 2 years ago

DTL2020 commented 2 years ago

Is there exist a sample of operating with some simple array of D3D12 resources that are ComPtr objects ?

Typically 'Hello' samples uses statically declared in .h file objects. If processing require an array od ComPtr objects of dynamic size - how to create it?

Tried: In .h file:

  // pool of resources in accelerator
  int iNumFrameResources; // number of textures
  Microsoft::WRL::ComPtr<ID3D12Resource>** ppFramesResources; // pointer to array of frames textures resources

In array init:

      iNumFrameResources = 2 * df + 1; // number of frames to operate in the accelerator's pool
      ppFramesResources = new ComPtr<ID3D12Resource>*[iNumFrameResources];
      for (int i = 0; i < iNumFrameResources; i++)
      {
        ComPtr<ID3D12Resource>* pRes = new ComPtr<ID3D12Resource>;
        ppFramesResources[i] = pRes;
      }

And in usage loop for creating textures:

    for (int i = 0; i < iNumFrameResources; i++)
    {
      ID3D12Resource* pTextureResource = ppFramesResources[i]->Get();

      hr = m_D3D12device->CreateCommittedResource(
        &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
        D3D12_HEAP_FLAG_NONE,
        &textureDesc,
        D3D12_RESOURCE_STATE_COMMON,
        nullptr,
        IID_PPV_ARGS(&pTextureResource));
}

The C++ compiler build it but ID3D12Resource* pTextureResource = ppFramesResources[i]->Get(); - return zero pointer.

walbourn commented 2 years ago

There's nothing in your 'creating textures' loop that is actually assigning the raw pointer to ID3D12Resource back to any ComPtr instance. In fact, it just leaks all the resources.

For the code above, you'd need to do something like:

for (int i = 0; i < iNumFrameResources; i++)
{
      ID3D12Resource* pTextureResource = nullptr;

      hr = m_D3D12device->CreateCommittedResource(
        &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
        D3D12_HEAP_FLAG_NONE,
        &textureDesc,
        D3D12_RESOURCE_STATE_COMMON,
        nullptr,
        IID_PPV_ARGS(&pTextureResource));

      if (SUCCEED(hr))
      {
          ppFramesResources[i]->Attach(pTextureResource);
      }
}

Your code above is an unusual mix of raw pointers and smart-pointers, so it's really easy to get confused. You are losing a lot of the utility of the smart-pointer in the process. A better usage would be something like a std::vector<Microsoft::WRL::ComPtr<ID3D12Resource>> of resources. That said, you normally embed the smart-pointer in a data structure that's doing more than just tracking the resource reference.

You can find a lot of examples of ComPtr usage in DirectX Tool Kit. I also have a short tutorial page on ComPtr here.