调整D3D11程序窗口大小后关闭出现资源泄漏警告如何解决?
问题根因定位
你代码的核心泄漏点是每次窗口调整大小时,旧的深度模板视图(pZBuffer)没有被释放,每次resize都会新建一个深度模板视图对象,旧对象的引用计数始终不为0,所以调整窗口次数越多,泄漏的D3D对象越多,退出时的Live Object警告也会对应增多。
另外还有两个潜在问题需要同步修正:
- 调用
ResizeBuffers前需要确保GPU已经完成了所有渲染指令,避免对象被GPU占用导致释放失败 - 释放旧对象前要做空指针判断,避免空指针访问崩溃
修复步骤
- 在
ResizeBuffers调用前,除了释放后缓冲渲染视图pBackBufferRTView,还要同步释放旧的深度模板视图pZBuffer - 释放对象前做空指针有效性判断,释放后把指针置空避免野指针
- 添加
Flush指令清空GPU队列,确保所有资源引用都被解除
修正后的窗口调整核心代码
if (pSwapChain) { // 先解绑渲染目标,清空GPU指令队列,确保资源没有被占用 pImmediateContex->OMSetRenderTargets(0, 0, 0); pImmediateContex->Flush(); // 释放旧的后缓冲渲染视图 if (pBackBufferRTView) { pBackBufferRTView->Release(); pBackBufferRTView = nullptr; } // 释放旧的深度模板视图【这是之前漏掉的核心步骤】 if (pZBuffer) { pZBuffer->Release(); pZBuffer = nullptr; } HRESULT hr = S_OK; //if 0, DXGI will use the width of the client area hr = pSwapChain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN, 0); if (FAILED(hr)) return hr; //Get buffer and create a render-target-view ID3D11Texture2D* pBackBufferTexture; //Returns pointer to the back buffer hr = pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&pBackBufferTexture); if (FAILED(hr)) return hr; //Use back buffer texture pointer to create the renedr target view hr = pD3DDevice->CreateRenderTargetView(pBackBufferTexture, NULL, &pBackBufferRTView); if (FAILED(hr)) return hr; //Clean up pBackBufferTexture->Release(); pBackBufferTexture = nullptr; RECT rc; GetClientRect(hWnd, &rc); screenWidth = rc.right - rc.left; screenHeight = rc.bottom - rc.top; stringstream a; a << std::to_string(screenWidth) << " " << std::to_string(screenHeight) << "\n"; OutputDebugString(a.str().c_str()); camera->SetProjectionValues(90.0f, static_cast<float>(screenWidth) / static_cast<float>(screenHeight), 0.01f, 1000.0f); //Create a Z buffer texture D3D11_TEXTURE2D_DESC tex2DDesc; ZeroMemory(&tex2DDesc, sizeof(tex2DDesc)); tex2DDesc.Width = screenWidth; tex2DDesc.Height = screenHeight; tex2DDesc.ArraySize = 1; tex2DDesc.MipLevels = 1; tex2DDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; //24 bits of each pixel tex2DDesc.SampleDesc.Count = 1; tex2DDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; tex2DDesc.Usage = D3D11_USAGE_DEFAULT; ID3D11Texture2D* pZBufferTexture; hr = pD3DDevice->CreateTexture2D(&tex2DDesc, NULL, &pZBufferTexture); if (FAILED(hr)) return hr; //Create the Z buffer D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; ZeroMemory(&dsvDesc, sizeof(dsvDesc)); dsvDesc.Format = tex2DDesc.Format; dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; pD3DDevice->CreateDepthStencilView(pZBufferTexture, &dsvDesc, &pZBuffer); pZBufferTexture->Release(); pZBufferTexture = nullptr; // 新建完深度缓冲后再执行清空操作 pImmediateContex->ClearDepthStencilView(pZBuffer, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); //Set the render target view pImmediateContex->OMSetRenderTargets(1, &pBackBufferRTView, pZBuffer); //Set the viewport D3D11_VIEWPORT viewport; viewport.TopLeftX = 0; viewport.TopLeftY = 0; viewport.Width = (FLOAT)screenWidth; viewport.Height = (FLOAT)screenHeight; viewport.MinDepth = .0f; viewport.MaxDepth = 1.0f; pImmediateContex->RSSetViewports(1, &viewport); }
内容的提问来源于stack exchange,提问作者Adamska_01
相关产品推荐
相关产品推荐

