[d3d12on7] Refactor backbuffer indexing and handle resizes
Instead of counting Present() calls, do a reverse lookup in the known backbuffer list to accurately determine the buffer index
If the lookup failed, assume the window was resized and do a delayed D3D12 reinitialize with the new buffers after 3 have been found
@@ -159,12 +159,28 @@ HRESULT Overlay::PresentD3D12Downlevel(ID3D12CommandQueueDownlevel* pCommandQueu
{
auto& overlay = Get();
- // On Windows 7 there is no swap chain to query the current backbuffer index, so instead we simply count to 3 and wrap around.
- // Increment the buffer index here even if the overlay is not enabled, so we stay in sync with the game's present calls.
- // TODO: investigate if there isn't a better way of doing this (finding the current index in the game exe?)
- overlay.m_downlevelBufferIndex = (!overlay.m_initialized || overlay.m_downlevelBufferIndex == 2) ? 0 : overlay.m_downlevelBufferIndex + 1;
+ // On Windows 7 there is no swap chain to query the current backbuffer index. Instead do a reverse lookup in the known backbuffer list
+ const auto it = std::find(overlay.m_downlevelBackbuffers.cbegin(), overlay.m_downlevelBackbuffers.cend(), pSourceTex2D);
+ bool resizing = false;
+ if (it == overlay.m_downlevelBackbuffers.cend())
+ {
+ if (overlay.m_initialized)
+ {
+ spdlog::warn("\tOverlay::PresentD3D12Downlevel() - buffer at {0} not found in backbuffer list! Assuming window was resized - note that support for resizing is experimental.", (void*)pSourceTex2D);
+ overlay.ResetD3D12State();
+ }
+
+ overlay.m_downlevelBackbuffers.emplace_back(pSourceTex2D);
+
+ // If we don't have a full backbuffer list, do not attempt to reinitialize yet
+ resizing = overlay.m_downlevelBackbuffers.size() < 3;
+ }
+ else
+ {
+ overlay.m_downlevelBufferIndex = static_cast<uint32_t>(std::distance(overlay.m_downlevelBackbuffers.cbegin(), it));
+ }
- if (overlay.InitializeD3D12Downlevel(overlay.m_pCommandQueue, pSourceTex2D, hWindow))
+ if (!resizing && overlay.InitializeD3D12Downlevel(overlay.m_pCommandQueue, pSourceTex2D, hWindow))
{
overlay.Render(nullptr);
}
@@ -183,7 +199,6 @@ HRESULT Overlay::CreateCommittedResourceD3D12(ID3D12Device* pDevice, const D3D12
pDesc != NULL && pDesc->Flags == D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET && InitialResourceState == D3D12_RESOURCE_STATE_COMMON &&
pOptimizedClearValue == NULL && riidResource != NULL && IsEqualGUID(*riidResource, __uuidof(ID3D12Resource)))
{
- spdlog::debug("\tOverlay::CreateCommittedResourceD3D12() - found valid backbuffer target.");
isBackBuffer = true;
}
@@ -193,6 +208,7 @@ HRESULT Overlay::CreateCommittedResourceD3D12(ID3D12Device* pDevice, const D3D12
{
// Store the returned resource
overlay.m_downlevelBackbuffers.emplace_back(static_cast<ID3D12Resource*>(*ppvResource));
+ spdlog::debug("\tOverlay::CreateCommittedResourceD3D12() - found valid backbuffer target at {0}.", *ppvResource);
}
// If D3D12 has been initialized, there is no need to continue hooking this function since the backbuffers are only created once.
