From 20fa9286e799d1396c9566483c8e266170b03398 Mon Sep 17 00:00:00 2001 From: WinterSnowfall Date: Sat, 25 Mar 2023 21:17:50 +0200 Subject: [PATCH] [d3d8] refcount refactoring --- src/d3d8/d3d8_blit.cpp | 2 +- src/d3d8/d3d8_device.h | 72 ++++++++++++++++++++++++++++++----------- src/d3d8/d3d8_texture.h | 2 +- 3 files changed, 56 insertions(+), 20 deletions(-) diff --git a/src/d3d8/d3d8_blit.cpp b/src/d3d8/d3d8_blit.cpp index 8a19b89caff3..6601a17dfe18 100644 --- a/src/d3d8/d3d8_blit.cpp +++ b/src/d3d8/d3d8_blit.cpp @@ -234,7 +234,7 @@ namespace dxvk { case D3DPOOL_SYSTEMMEM: { // RT (DEFAULT) -> SYSTEMMEM: Use GetRenderTargetData as fast path if possible - if ((srcDesc.Usage & D3DUSAGE_RENDERTARGET || m_renderTarget == src)) { + if ((srcDesc.Usage & D3DUSAGE_RENDERTARGET || m_renderTarget.ptr() == src.ptr())) { // GetRenderTargetData works if the formats and sizes match if (srcDesc.MultiSampleType == d3d9::D3DMULTISAMPLE_NONE diff --git a/src/d3d8/d3d8_device.h b/src/d3d8/d3d8_device.h index 81ce708278ca..64e9db0cb530 100644 --- a/src/d3d8/d3d8_device.h +++ b/src/d3d8/d3d8_device.h @@ -151,6 +151,7 @@ namespace dxvk { UINT iBackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface8** ppBackBuffer) { + InitReturnPtr(ppBackBuffer); if (iBackBuffer >= m_backBuffers.size() || m_backBuffers[iBackBuffer] == nullptr) { Com pSurface9; @@ -158,7 +159,7 @@ namespace dxvk { if (FAILED(res)) return res; - m_backBuffers[iBackBuffer] = ref(new D3D8Surface(this, std::move(pSurface9))); + m_backBuffers[iBackBuffer] = new D3D8Surface(this, std::move(pSurface9)); *ppBackBuffer = m_backBuffers[iBackBuffer].ref(); return res; @@ -368,30 +369,60 @@ namespace dxvk { if (pRenderTarget != NULL) { D3D8Surface* surf = static_cast(pRenderTarget); - res = GetD3D9()->SetRenderTarget(0, surf->GetD3D9()); - if (FAILED(res)) return res; + D3DSURFACE_DESC rtDesc; + surf->GetDesc(&rtDesc); - m_renderTarget = ref(surf); - } + if (unlikely(!(rtDesc.Usage & D3DUSAGE_RENDERTARGET))) + return D3DERR_INVALIDCALL; + + if(likely(m_renderTarget.ptr() != surf)) { + res = GetD3D9()->SetRenderTarget(0, surf->GetD3D9()); + + if (FAILED(res)) return res; + // keep a temporary ref on the prev RT, since this could be a swap + D3D8Surface* pRenderTargetSwap = m_renderTargetPrev.ref(); + m_renderTargetPrev = m_renderTarget; + m_renderTarget = surf; + SAFE_RELEASE(pRenderTargetSwap); + } + } + // SetDepthStencilSurface is a separate call D3D8Surface* zStencil = static_cast(pNewZStencil); - res = GetD3D9()->SetDepthStencilSurface(D3D8Surface::GetD3D9Nullable(zStencil)); - if (FAILED(res)) return res; + if(pNewZStencil != NULL) { + D3DSURFACE_DESC zsDesc; + zStencil->GetDesc(&zsDesc); - m_depthStencil = ref(zStencil); - return res; + if (unlikely(!(zsDesc.Usage & D3DUSAGE_DEPTHSTENCIL))) + return D3DERR_INVALIDCALL; + } + + if(likely(m_depthStencil.ptr() != zStencil)) { + res = GetD3D9()->SetDepthStencilSurface(D3D8Surface::GetD3D9Nullable(zStencil)); + + if (FAILED(res)) return res; + + // keep a temporary ref on the prev DS, since this could be a swap + D3D8Surface* pDepthStencilSwap = m_depthStencilPrev.ref(); + m_depthStencilPrev = m_depthStencil; + m_depthStencil = zStencil; + SAFE_RELEASE(pDepthStencilSwap); + } + + return D3D_OK; } HRESULT STDMETHODCALLTYPE GetRenderTarget(IDirect3DSurface8** ppRenderTarget) { + InitReturnPtr(ppRenderTarget); if (unlikely(m_renderTarget == nullptr)) { Com pRT9 = nullptr; HRESULT res = GetD3D9()->GetRenderTarget(0, &pRT9); // use RT index 0 - m_renderTarget = ref(new D3D8Surface(this, std::move(pRT9))); + m_renderTarget = new D3D8Surface(this, std::move(pRT9)); *ppRenderTarget = m_renderTarget.ref(); return res; @@ -402,12 +433,13 @@ namespace dxvk { } HRESULT STDMETHODCALLTYPE GetDepthStencilSurface(IDirect3DSurface8** ppZStencilSurface) { + InitReturnPtr(ppZStencilSurface); if (unlikely(m_depthStencil == nullptr)) { Com pStencil9 = nullptr; HRESULT res = GetD3D9()->GetDepthStencilSurface(&pStencil9); - m_depthStencil = ref(new D3D8Surface(this, std::move(pStencil9))); + m_depthStencil = new D3D8Surface(this, std::move(pStencil9)); *ppZStencilSurface = m_depthStencil.ref(); return res; @@ -567,7 +599,7 @@ namespace dxvk { D3D8Texture2D* tex = static_cast(pTexture); - m_textures[Stage] = ref(tex); + m_textures[Stage] = tex; return GetD3D9()->SetTexture(Stage, D3D8Texture2D::GetD3D9Nullable(tex)); } @@ -831,7 +863,9 @@ namespace dxvk { } m_frontBuffer = nullptr; m_renderTarget = nullptr; + m_renderTargetPrev = nullptr; m_depthStencil = nullptr; + m_depthStencilPrev = nullptr; } friend d3d9::IDirect3DPixelShader9* getPixelShaderPtr(D3D8DeviceEx* device, DWORD Handle); @@ -849,23 +883,25 @@ namespace dxvk { D3D8StateBlock* m_recorder = nullptr; struct D3D8VBO { - Com buffer = nullptr; - UINT stride = 0; + Com buffer = nullptr; + UINT stride = 0; }; // Remember to fill() these in the constructor! - std::array, d8caps::MAX_TEXTURE_STAGES> m_textures; + std::array, d8caps::MAX_TEXTURE_STAGES> m_textures; std::array m_streams; - Com m_indices; - INT m_baseVertexIndex = 0; + Com m_indices; + INT m_baseVertexIndex = 0; // TODO: Which of these should be a private ref std::vector> m_backBuffers; Com m_frontBuffer; - Com m_renderTarget; + Com m_renderTarget; + Com m_renderTargetPrev; Com m_depthStencil; + Com m_depthStencilPrev; std::vector m_vertexShaders; std::vector m_pixelShaders; diff --git a/src/d3d8/d3d8_texture.h b/src/d3d8/d3d8_texture.h index 97570f322bd1..9c1532aac077 100644 --- a/src/d3d8/d3d8_texture.h +++ b/src/d3d8/d3d8_texture.h @@ -103,7 +103,7 @@ namespace dxvk { return ptr; } - std::vector> m_subresources; + std::vector> m_subresources; };