DX11调用OpenSharedResource实现窗口捕获时GPU内存泄漏排查求助
我现在碰到个棘手的问题:用DX11通过OpenSharedResource做窗口捕获的时候,GPU显存一直在泄漏——我用System Informer监测"Gpu Dedicated bytes",发现每执行一次循环,显存占用就会涨一点。
我一开始怀疑是没调用CloseHandle(hDxSurface)释放共享句柄,但加上这个调用后直接抛出异常,现在完全摸不着头脑,不知道还有哪里可能导致泄漏,求各位帮忙排查下!
#include "stdafx.h" #include <Windows.h> #include <chrono> #include <thread> #include <atomic> #include <memory> #include <d3d11.h> #include <dxgi1_2.h> #pragma comment(lib, "d3d11.lib") #pragma comment(lib, "dxgi.lib") typedef HRESULT(WINAPI* PFN_DwmDxGetWindowSharedSurface)(HWND, HANDLE*, LUID*, ULONG*, ULONG*, ULONGLONG*); PFN_DwmDxGetWindowSharedSurface DwmGetDxSharedSurface = nullptr; bool getDwmGetDxSharedSurface() { HMODULE hUser32 = LoadLibraryA("user32.dll"); if (hUser32 != NULL) DwmGetDxSharedSurface = (PFN_DwmDxGetWindowSharedSurface)GetProcAddress(hUser32, "DwmGetDxSharedSurface"); return DwmGetDxSharedSurface != nullptr; } class WindowCapture { public: // DirectX resources (cached and reused) IDXGIFactory1* m_pFactory = nullptr; IDXGIAdapter* m_pAdapter = nullptr; ID3D11DeviceContext* m_pContext = nullptr; ID3D11Device* m_pDevice = nullptr; // Target window HWND m_hwnd = nullptr; // **PERFORMANCE OPTIMIZATION**: Double-buffered staging textures ID3D11Texture2D* m_pStagingTexture[2] = {nullptr, nullptr}; int m_currentStagingIndex = 0; UINT m_lastWidth = 0; UINT m_lastHeight = 0; DXGI_FORMAT m_lastFormat = DXGI_FORMAT_UNKNOWN; // DIB Section for direct pixel access (cached) HBITMAP m_hDIBSection = nullptr; void* m_pDIBBits = nullptr; UINT m_dibWidth = 0; UINT m_dibHeight = 0; WindowCapture() {}; bool initialize(HWND hwnd); bool captureToPixelBuffer(void** ppPixels, UINT* pWidth, UINT* pHeight, UINT* pPitch); bool captureToFile(const wchar_t* filename); bool initializeDirectX(); bool createOrUpdateStagingTextures(UINT width, UINT height, DXGI_FORMAT format); bool createOrUpdateDIBSection(UINT width, UINT height); bool copyTextureDataToDIB(const D3D11_MAPPED_SUBRESOURCE& mapped, UINT width, UINT height); }; bool WindowCapture::initialize(HWND hwnd) { if (!hwnd || !IsWindow(hwnd)) return false; m_hwnd = hwnd; if (!getDwmGetDxSharedSurface()) { $err, "Failed to get DwmGetDxSharedSurface function"; return false; } HRESULT hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); if (FAILED(hr) && hr != RPC_E_CHANGED_MODE) { $err, "Failed to initialize COM", hr; return false; } if (!initializeDirectX()) return false; return true; } bool WindowCapture::initializeDirectX() { HRESULT hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)(&m_pFactory)); if (FAILED(hr) || !m_pFactory) { $err, "CreateDXGIFactory1 failed", hr; return false; } m_pFactory->EnumAdapters(0, &m_pAdapter); if (!m_pAdapter) { $err, "Failed to enumerate adapters"; m_pFactory->Release(); return false; } const D3D_FEATURE_LEVEL featureLevels[] = { 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 }; hr = D3D11CreateDevice(m_pAdapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, D3D11_CREATE_DEVICE_BGRA_SUPPORT, featureLevels, 6, D3D11_SDK_VERSION, &m_pDevice, NULL, &m_pContext); if (FAILED(hr) || !m_pDevice) { $err, "D3D11CreateDevice failed", hr; m_pFactory->Release(); return false; } return true; } bool WindowCapture::createOrUpdateStagingTextures(UINT width, UINT height, DXGI_FORMAT format) { // Reuse existing staging textures if dimensions and format match if (m_pStagingTexture[0] && m_lastWidth == width && m_lastHeight == height && m_lastFormat == format) return true; // Release old staging textures for (int i = 0; i < 2; ++i) { if (m_pStagingTexture[i]) { m_pStagingTexture[i]->Release(); m_pStagingTexture[i] = nullptr; } } // Create new staging textures (double-buffered) D3D11_TEXTURE2D_DESC stagingDesc = {}; stagingDesc.Width = width; stagingDesc.Height = height; stagingDesc.MipLevels = 1; stagingDesc.ArraySize = 1; stagingDesc.Format = format; stagingDesc.SampleDesc.Count = 1; stagingDesc.SampleDesc.Quality = 0; stagingDesc.Usage = D3D11_USAGE_STAGING; stagingDesc.BindFlags = 0; stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; stagingDesc.MiscFlags = 0; for (int i = 0; i < 2; ++i) { HRESULT hr = m_pDevice->CreateTexture2D(&stagingDesc, nullptr, &m_pStagingTexture[i]); if (FAILED(hr)) { $err, "Failed to create staging texture %1", i, hr; for (int j = 0; j < i; ++j) { if (m_pStagingTexture[j]) { m_pStagingTexture[j]->Release(); m_pStagingTexture[j] = nullptr; } } return false; } } // Cache dimensions m_lastWidth = width; m_lastHeight = height; m_lastFormat = format; m_currentStagingIndex = 0; return true; } bool WindowCapture::createOrUpdateDIBSection(UINT width, UINT height) { // Reuse existing DIB
内容来源于stack exchange
相关产品推荐
相关产品推荐

