1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-18 20:52:10 +01:00

[d3d9] Fix ref-counting for swapchain surfaces

This commit is contained in:
Joshua Ashton 2020-04-18 20:40:49 +01:00
parent 97cd91885d
commit 42089d73c5
4 changed files with 26 additions and 13 deletions

View File

@ -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<D3D9SwapChainEx*>(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<D3D9SwapChainEx*>(pSwapChain)->ReleasePrivate();

View File

@ -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);

View File

@ -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<D3D9Surface>(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();

View File

@ -129,7 +129,7 @@ namespace dxvk {
DxvkLogicOpState m_loState;
DxvkBlendMode m_blendMode;
std::vector<std::unique_ptr<D3D9Surface>> m_backBuffers;
std::vector<D3D9Surface*> m_backBuffers;
RECT m_srcRect;
RECT m_dstRect;
@ -167,6 +167,8 @@ namespace dxvk {
void CreateRenderTargetViews();
void DestroyBackBuffers();
void CreateBackBuffers(
uint32_t NumBackBuffers);