为什么在使用 CopyResource 跨 ID3D11Devices 共享纹理时会出现视频内存泄漏?

问题描述

  • 我创建了两个设备 A 和 B,其中 A 是生产者,B 是消费者。纹理在两者之间通过 D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX 共享。现在我发现每次B调用copyResource将共享纹理复制到本地时,显存会不断增加。这个问题困扰了我很久。我搜索了github或其他代码源,但找不到解决方案。我的机器是Win10和Geforce GTX 1060。

  • 重现问题最精简的代码如下:

     #include <dxgi.h>
     #include <d3d11.h>
     #include <atlbase.h>
     #pragma comment(lib,"D3D11.lib")
    
     #define RETURN_ON_FAIL(hr)    if(Failed(hr)) return hr;
    
     namespace SharedTextureLeakTest
     {
     const UINT32 texture_width = 320;
     const UINT32 texture_height = 240;
    
     ATL::CComPtr<ID3D11Device>          device_1 = nullptr;
     ATL::CComPtr<ID3D11DeviceContext>   context_1 = nullptr;
     ATL::CComPtr<ID3D11Device>          device_2 = nullptr;
     ATL::CComPtr<ID3D11DeviceContext>   context_2 = nullptr;
     ATL::CComPtr<ID3D11Texture2D>       shared_texture_dev1 = nullptr;  //owner by device1
     ATL::CComPtr<ID3D11Texture2D>       dst_texture_dev2 = nullptr; //owner by device2
     HANDLE  shared_handle = nullptr;
    
     HRESULT CheckEnvironmentValid()
     {
         HRESULT hr = S_OK;
    
         //Create Device1
         if (!device_1)
         {
             D3D_FEATURE_LEVEL pFeatureLevel;
             UINT Flags = D3D11_CREATE_DEVICE_DEBUG;
             hr = ::D3D11CreateDevice(nullptr,D3D_DRIVER_TYPE_HARDWARE,nullptr,Flags,D3D11_SDK_VERSION,&device_1,&pFeatureLevel,&context_1);
             if (Failed(hr)) 
             {
                 device_1 = nullptr;
                 return hr;
             }
         }
    
         //Create Shared Texture
         if (!shared_texture_dev1)
         {
             D3D11_TEXTURE2D_DESC desc;
             desc.ArraySize = 1;
             desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
             desc.cpuAccessFlags = 0;
             desc.Format = dxgi_FORMAT_B8G8R8A8_UnorM;
             desc.Width = texture_width;
             desc.Height = texture_height;
             desc.MipLevels = 1;
             desc.Usage = D3D11_USAGE_DEFAULT;
             desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
             desc.SampleDesc.Count = 1;
             desc.SampleDesc.Quality = 0;
    
             hr = device_1->CreateTexture2D(&desc,&shared_texture_dev1);
             RETURN_ON_FAIL(hr);
         }
    
         //Get Handle of Shared Texture
         if (!shared_handle)
         {
             ATL::CComPtr<IdxgiResource> dxgi_res;
             hr = shared_texture_dev1->QueryInterface(__uuidof(IdxgiResource),(void**)&dxgi_res);
             RETURN_ON_FAIL(hr);
    
             hr = dxgi_res->GetSharedHandle(&shared_handle);
             RETURN_ON_FAIL(hr);
         }
    
         //Create Device2
         if (!device_2)
         {
             D3D_FEATURE_LEVEL pFeatureLevel;
             UINT Flags = D3D11_CREATE_DEVICE_DEBUG;
             hr = ::D3D11CreateDevice(nullptr,&device_2,&context_2);
             if (Failed(hr))
             {
                 device_2= nullptr;
                 return hr;
             }
         }
    
         //Create Dst Texture
         if (!dst_texture_dev2)
         {
             D3D11_TEXTURE2D_DESC desc;
             desc.ArraySize = 1;
             desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
             desc.cpuAccessFlags = 0;
             desc.Format = dxgi_FORMAT_B8G8R8A8_UnorM;
             desc.Width = texture_width;
             desc.Height = texture_height;
             desc.MipLevels = 1;
             desc.Usage = D3D11_USAGE_DEFAULT;
             desc.MiscFlags = 0;
             desc.SampleDesc.Count = 1;
             desc.SampleDesc.Quality = 0;
    
             hr = device_2->CreateTexture2D(&desc,&dst_texture_dev2);
             RETURN_ON_FAIL(hr);
         }
    
         return hr;
     }
    
     HRESULT LoopOncetest()
     {
         HRESULT hr = CheckEnvironmentValid();
         RETURN_ON_FAIL(hr);
    
         //Open Shared Texture
         ATL::CComPtr<ID3D11Texture2D>   shared_texture_dev2;
         hr = device_2->OpenSharedResource(shared_handle,IID_PPV_ARGS(&shared_texture_dev2));
         RETURN_ON_FAIL(hr);
    
         //copy
         do
         {
             CComPtr<IdxgiKeyedMutex> km;
             hr = shared_texture_dev2->QueryInterface(__uuidof(IdxgiKeyedMutex),(void**)&km);
             RETURN_ON_FAIL(hr);
    
             INT64 release_key = 0;
             hr = km->AcquireSync(0,10);
             RETURN_ON_FAIL(hr);
    
             if (hr == WAIT_OBJECT_0)
             {
                 context_2->copyResource(dst_texture_dev2,shared_texture_dev2);
             //  context_2->Flush();
             }
    
             hr = km->ReleaseSync(0);
             RETURN_ON_FAIL(hr);
    
         } while (FALSE);
    
         return hr;
     }
     }
    
     void Dotest()
     {
         for(;;)
         {
              SharedTextureLeakTest::LoopOncetest();
              Sleep(1000);
         }
     }
    

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...