diff --git a/src/d3d9/d3d9_surface.cpp b/src/d3d9/d3d9_surface.cpp index 7ecbb8fdb..b25381496 100644 --- a/src/d3d9/d3d9_surface.cpp +++ b/src/d3d9/d3d9_surface.cpp @@ -30,7 +30,7 @@ namespace dxvk { pBaseTexture, pBaseTexture) { } - void D3D9Surface::AddRefPrivate() { + void D3D9Surface::AddRefPrivate(bool swapchain) { IDirect3DBaseTexture9* pBaseTexture = this->m_baseTexture; IUnknown* pSwapChain = this->m_container; @@ -43,7 +43,7 @@ namespace dxvk { return; } - else if (pSwapChain != nullptr) { + else if (pSwapChain != nullptr && !swapchain) { // Container must be a swapchain if it isn't a base texture. reinterpret_cast(pSwapChain)->AddRefPrivate(); @@ -53,7 +53,7 @@ namespace dxvk { D3D9SurfaceBase::AddRefPrivate(); } - void D3D9Surface::ReleasePrivate() { + void D3D9Surface::ReleasePrivate(bool swapchain) { IDirect3DBaseTexture9* pBaseTexture = this->m_baseTexture; IUnknown* pSwapChain = this->m_container; @@ -66,7 +66,7 @@ namespace dxvk { return; } - else if (pSwapChain != nullptr) { + else if (pSwapChain != nullptr && !swapchain) { // Container must be a swapchain if it isn't a base texture. reinterpret_cast(pSwapChain)->ReleasePrivate(); diff --git a/src/d3d9/d3d9_surface.h b/src/d3d9/d3d9_surface.h index d7c8f2b94..d921af7c3 100644 --- a/src/d3d9/d3d9_surface.h +++ b/src/d3d9/d3d9_surface.h @@ -29,9 +29,9 @@ namespace dxvk { UINT MipLevel, IDirect3DBaseTexture9* pBaseTexture); - void AddRefPrivate(); + void AddRefPrivate(bool swapchain = false); - void ReleasePrivate(); + void ReleasePrivate(bool swapchain = false); HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject); diff --git a/src/d3d9/d3d9_swapchain.cpp b/src/d3d9/d3d9_swapchain.cpp index 80d1c94d0..5fa24565b 100644 --- a/src/d3d9/d3d9_swapchain.cpp +++ b/src/d3d9/d3d9_swapchain.cpp @@ -463,7 +463,7 @@ namespace dxvk { return D3DERR_INVALIDCALL; } - *ppBackBuffer = ref(m_backBuffers[iBackBuffer].get()); + *ppBackBuffer = ref(m_backBuffers[iBackBuffer]); return D3D_OK; } @@ -712,7 +712,7 @@ namespace dxvk { if (iBackBuffer >= m_presentParams.BackBufferCount) return nullptr; - return m_backBuffers[iBackBuffer].get(); + return m_backBuffers[iBackBuffer]; } @@ -876,7 +876,7 @@ namespace dxvk { // Rotate swap chain buffers so that the back // buffer at index 0 becomes the front buffer. for (uint32_t i = 1; i < m_backBuffers.size(); i++) - m_backBuffers[i]->Swap(m_backBuffers[i - 1].get()); + m_backBuffers[i]->Swap(m_backBuffers[i - 1]); m_parent->m_flags.set(D3D9DeviceFlag::DirtyFramebuffer); } @@ -1010,14 +1010,23 @@ namespace dxvk { } + void D3D9SwapChainEx::DestroyBackBuffers() { + for (auto* backBuffer : m_backBuffers) + backBuffer->ReleasePrivate(true); + + m_backBuffers.clear(); + } + + void D3D9SwapChainEx::CreateBackBuffers(uint32_t NumBackBuffers) { // Explicitly destroy current swap image before // creating a new one to free up resources m_resolveImage = nullptr; m_resolveImageView = nullptr; + DestroyBackBuffers(); + int NumFrontBuffer = m_parent->GetOptions()->noExplicitFrontBuffer ? 0 : 1; - m_backBuffers.clear(); m_backBuffers.resize(NumBackBuffers + NumFrontBuffer); // Create new back buffer @@ -1034,8 +1043,10 @@ namespace dxvk { desc.Usage = D3DUSAGE_RENDERTARGET; desc.Discard = FALSE; - for (uint32_t i = 0; i < m_backBuffers.size(); i++) - m_backBuffers[i] = std::make_unique(m_parent, &desc, this); + for (uint32_t i = 0; i < m_backBuffers.size(); i++) { + m_backBuffers[i] = new D3D9Surface(m_parent, &desc, this); + m_backBuffers[i]->AddRefPrivate(true); + } auto swapImage = m_backBuffers[0]->GetCommonTexture()->GetImage(); diff --git a/src/d3d9/d3d9_swapchain.h b/src/d3d9/d3d9_swapchain.h index 1ed498075..bd5178a3c 100644 --- a/src/d3d9/d3d9_swapchain.h +++ b/src/d3d9/d3d9_swapchain.h @@ -129,7 +129,7 @@ namespace dxvk { DxvkLogicOpState m_loState; DxvkBlendMode m_blendMode; - std::vector> m_backBuffers; + std::vector m_backBuffers; RECT m_srcRect; RECT m_dstRect; @@ -167,6 +167,8 @@ namespace dxvk { void CreateRenderTargetViews(); + void DestroyBackBuffers(); + void CreateBackBuffers( uint32_t NumBackBuffers);