如何解决为什么在使用 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 举报,一经查实,本站将立刻删除。