- Status
- Offline
- Joined
- Mar 3, 2026
- Messages
- 546
- Reaction score
- 7
Ran into a classic headache while messing with a DX11 hook for an internal project. Whenever the game state shifts or the window toggles to fullscreen, the IDXGISwapChain::ResizeBuffers call throws a fit.
The debug layer is screaming about non-zero reference counts. Basically, D3D refuses to resize the buffers because something is still holding on to the backbuffer resources. If you've been working on an ImGui-based menu, you know this usually means the Render Target View (RTV) or some leaked resource is locking the chain.
The Hook Logic
I'm using a standard VTable hook for ResizeBuffers. The goal is to release the RTV, let the original function do its thing, and then recreate the view so the menu keeps rendering.
The Bottleneck
Even with the release check, it's still failing on fullscreen transitions. Usually, this points to one of two things:
If you're hitting this error, make sure you aren't just releasing the RTV but also clearing the state of the context. DX11 is notoriously picky about the OMSetRenderTargets state during a swapchain resize. You can't just null the pointer; you need the device to acknowledge the transition.
Anyone else dealt with this specific reference leak when jumping between Windowed and Fullscreen? Dropping the full error log if needed.
The debug layer is screaming about non-zero reference counts. Basically, D3D refuses to resize the buffers because something is still holding on to the backbuffer resources. If you've been working on an ImGui-based menu, you know this usually means the Render Target View (RTV) or some leaked resource is locking the chain.
The Hook Logic
I'm using a standard VTable hook for ResizeBuffers. The goal is to release the RTV, let the original function do its thing, and then recreate the view so the menu keeps rendering.
Code:
HRESULT WINAPI hkResize(IDXGISwapChain* This, UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags)
{
if (mainRenderTargetView) {
mainRenderTargetView->Release();
mainRenderTargetView = nullptr;
}
HRESULT hr = oResize(This, BufferCount, Width, Height, NewFormat, SwapChainFlags);
ID3D11Texture2D* pBackBuffer = nullptr;
hr = This->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
hr = pDevice->CreateRenderTargetView(pBackBuffer, nullptr, &mainRenderTargetView);
pBackBuffer->Release();
PContext->OMSetRenderTargets(1, &mainRenderTargetView, NULL);
D3D11_VIEWPORT viewport = {};
viewport.Width = static_cast<FLOAT>(Width);
viewport.Height = static_cast<FLOAT>(Height);
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
viewport.TopLeftX = 0.0f;
viewport.TopLeftY = 0.0f;
PContext->RSSetViewports(1, &viewport);
return hr;
}
The Bottleneck
Even with the release check, it's still failing on fullscreen transitions. Usually, this points to one of two things:
- Something else in the pipeline is still bound (SRVs or other views).
- The PContext state isn't being cleared properly before the resize.
- Internal ImGui resources might still have a handle on the device context.
If you're hitting this error, make sure you aren't just releasing the RTV but also clearing the state of the context. DX11 is notoriously picky about the OMSetRenderTargets state during a swapchain resize. You can't just null the pointer; you need the device to acknowledge the transition.
Anyone else dealt with this specific reference leak when jumping between Windowed and Fullscreen? Dropping the full error log if needed.