1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-02 01:24:11 +01:00

[d3d9] Implement swapchain containers for surfaces

Fixes a crash in L.A. Noire.

Closes #1564
This commit is contained in:
Joshua Ashton 2020-04-13 01:42:04 +01:00
parent 4d8940957c
commit 4699d4162a
7 changed files with 59 additions and 31 deletions

View File

@ -3318,7 +3318,7 @@ namespace dxvk {
return D3DERR_INVALIDCALL;
try {
const Com<D3D9Surface> surface = new D3D9Surface(this, &desc);
const Com<D3D9Surface> surface = new D3D9Surface(this, &desc, nullptr);
m_initializer->InitTexture(surface->GetCommonTexture());
*ppSurface = surface.ref();
return D3D_OK;
@ -3361,7 +3361,7 @@ namespace dxvk {
return D3DERR_INVALIDCALL;
try {
const Com<D3D9Surface> surface = new D3D9Surface(this, &desc);
const Com<D3D9Surface> surface = new D3D9Surface(this, &desc, nullptr);
m_initializer->InitTexture(surface->GetCommonTexture());
*ppSurface = surface.ref();
return D3D_OK;
@ -3406,7 +3406,7 @@ namespace dxvk {
return D3DERR_INVALIDCALL;
try {
const Com<D3D9Surface> surface = new D3D9Surface(this, &desc);
const Com<D3D9Surface> surface = new D3D9Surface(this, &desc, nullptr);
m_initializer->InitTexture(surface->GetCommonTexture());
*ppSurface = surface.ref();
return D3D_OK;
@ -6695,7 +6695,7 @@ namespace dxvk {
if (FAILED(D3D9CommonTexture::NormalizeTextureProperties(this, &desc)))
return D3DERR_NOTAVAILABLE;
m_autoDepthStencil = new D3D9Surface(this, &desc);
m_autoDepthStencil = new D3D9Surface(this, &desc, nullptr);
m_initializer->InitTexture(m_autoDepthStencil->GetCommonTexture());
SetDepthStencilSurface(m_autoDepthStencil.ptr());
}

View File

@ -15,8 +15,10 @@ namespace dxvk {
D3D9CommonTexture* pTexture,
UINT Face,
UINT MipLevel,
IDirect3DBaseTexture9* pContainer)
IDirect3DBaseTexture9* pBaseTexture,
IUnknown* pContainer)
: D3D9Resource<Type...> ( pDevice )
, m_baseTexture ( pBaseTexture )
, m_container ( pContainer )
, m_texture ( pTexture )
, m_face ( Face )
@ -25,7 +27,7 @@ namespace dxvk {
~D3D9Subresource() {
// We own the texture!
if (m_container == nullptr)
if (m_baseTexture == nullptr)
delete m_texture;
}
@ -108,7 +110,7 @@ namespace dxvk {
}
IDirect3DBaseTexture9* GetBaseTexture() {
return m_container;
return m_baseTexture;
}
void Swap(D3D9Subresource* Other) {
@ -121,7 +123,8 @@ namespace dxvk {
protected:
IDirect3DBaseTexture9* m_container;
IUnknown* m_container;
IDirect3DBaseTexture9* m_baseTexture;
D3D9CommonTexture* m_texture;
UINT m_face;

View File

@ -1,5 +1,6 @@
#include "d3d9_surface.h"
#include "d3d9_texture.h"
#include "d3d9_swapchain.h"
#include "d3d9_device.h"
@ -7,34 +8,44 @@ namespace dxvk {
D3D9Surface::D3D9Surface(
D3D9DeviceEx* pDevice,
const D3D9_COMMON_TEXTURE_DESC* pDesc)
const D3D9_COMMON_TEXTURE_DESC* pDesc,
IUnknown* pContainer)
: D3D9SurfaceBase(
pDevice,
new D3D9CommonTexture( pDevice, pDesc, D3DRTYPE_TEXTURE),
0, 0,
nullptr) { }
nullptr,
pContainer) { }
D3D9Surface::D3D9Surface(
D3D9DeviceEx* pDevice,
D3D9CommonTexture* pTexture,
UINT Face,
UINT MipLevel,
IDirect3DBaseTexture9* pContainer)
IDirect3DBaseTexture9* pBaseTexture)
: D3D9SurfaceBase(
pDevice,
pTexture,
Face, MipLevel,
pContainer) { }
pBaseTexture,
pBaseTexture) { }
void D3D9Surface::AddRefPrivate() {
IDirect3DBaseTexture9* pContainer = this->m_container;
IDirect3DBaseTexture9* pBaseTexture = this->m_baseTexture;
IUnknown* pSwapChain = this->m_container;
if (pContainer != nullptr) {
D3DRESOURCETYPE type = pContainer->GetType();
if (pBaseTexture != nullptr) {
D3DRESOURCETYPE type = pBaseTexture->GetType();
if (type == D3DRTYPE_TEXTURE)
reinterpret_cast<D3D9Texture2D*> (pContainer)->AddRefPrivate();
reinterpret_cast<D3D9Texture2D*> (pBaseTexture)->AddRefPrivate();
else //if (type == D3DRTYPE_CUBETEXTURE)
reinterpret_cast<D3D9TextureCube*>(pContainer)->AddRefPrivate();
reinterpret_cast<D3D9TextureCube*>(pBaseTexture)->AddRefPrivate();
return;
}
else if (pSwapChain != nullptr) {
// Container must be a swapchain if it isn't a base texture.
reinterpret_cast<D3D9SwapChainEx*>(pSwapChain)->AddRefPrivate();
return;
}
@ -43,14 +54,21 @@ namespace dxvk {
}
void D3D9Surface::ReleasePrivate() {
IDirect3DBaseTexture9* pContainer = this->m_container;
IDirect3DBaseTexture9* pBaseTexture = this->m_baseTexture;
IUnknown* pSwapChain = this->m_container;
if (pContainer != nullptr) {
D3DRESOURCETYPE type = pContainer->GetType();
if (pBaseTexture != nullptr) {
D3DRESOURCETYPE type = pBaseTexture->GetType();
if (type == D3DRTYPE_TEXTURE)
reinterpret_cast<D3D9Texture2D*> (pContainer)->ReleasePrivate();
reinterpret_cast<D3D9Texture2D*> (pBaseTexture)->ReleasePrivate();
else //if (type == D3DRTYPE_CUBETEXTURE)
reinterpret_cast<D3D9TextureCube*>(pContainer)->ReleasePrivate();
reinterpret_cast<D3D9TextureCube*>(pBaseTexture)->ReleasePrivate();
return;
}
else if (pSwapChain != nullptr) {
// Container must be a swapchain if it isn't a base texture.
reinterpret_cast<D3D9SwapChainEx*>(pSwapChain)->ReleasePrivate();
return;
}

View File

@ -19,14 +19,15 @@ namespace dxvk {
D3D9Surface(
D3D9DeviceEx* pDevice,
const D3D9_COMMON_TEXTURE_DESC* pDesc);
const D3D9_COMMON_TEXTURE_DESC* pDesc,
IUnknown* pContainer);
D3D9Surface(
D3D9DeviceEx* pDevice,
D3D9CommonTexture* pTexture,
UINT Face,
UINT MipLevel,
IDirect3DBaseTexture9* pContainer);
IDirect3DBaseTexture9* pBaseTexture);
void AddRefPrivate();

View File

@ -463,7 +463,7 @@ namespace dxvk {
return D3DERR_INVALIDCALL;
}
*ppBackBuffer = m_backBuffers[iBackBuffer].ref();
*ppBackBuffer = ref(m_backBuffers[iBackBuffer].get());
return D3D_OK;
}
@ -712,7 +712,7 @@ namespace dxvk {
if (iBackBuffer >= m_presentParams.BackBufferCount)
return nullptr;
return m_backBuffers[iBackBuffer].ptr();
return m_backBuffers[iBackBuffer].get();
}
@ -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].ptr());
m_backBuffers[i]->Swap(m_backBuffers[i - 1].get());
m_parent->m_flags.set(D3D9DeviceFlag::DirtyFramebuffer);
}
@ -1035,7 +1035,7 @@ namespace dxvk {
desc.Discard = FALSE;
for (uint32_t i = 0; i < m_backBuffers.size(); i++)
m_backBuffers[i] = new D3D9Surface(m_parent, &desc);
m_backBuffers[i] = std::make_unique<D3D9Surface>(m_parent, &desc, this);
auto swapImage = m_backBuffers[0]->GetCommonTexture()->GetImage();

View File

@ -129,7 +129,7 @@ namespace dxvk {
DxvkLogicOpState m_loState;
DxvkBlendMode m_blendMode;
std::vector<Com<D3D9Surface, false>> m_backBuffers;
std::vector<std::unique_ptr<D3D9Surface>> m_backBuffers;
RECT m_srcRect;
RECT m_dstRect;

View File

@ -12,6 +12,7 @@ namespace dxvk {
pDevice,
new D3D9CommonTexture( pDevice, pDesc, D3DRTYPE_VOLUMETEXTURE ),
0, 0,
nullptr,
nullptr) { }
@ -25,11 +26,14 @@ namespace dxvk {
pDevice,
pTexture,
Face, MipLevel,
pContainer,
pContainer) { }
void D3D9Volume::AddRefPrivate() {
IDirect3DBaseTexture9* pContainer = this->m_container;
IDirect3DBaseTexture9* pContainer = this->m_baseTexture;
// Can't have a swapchain container for a volume.
if (pContainer != nullptr) {
reinterpret_cast<D3D9Texture3D*> (pContainer)->AddRefPrivate();
@ -41,7 +45,9 @@ namespace dxvk {
void D3D9Volume::ReleasePrivate() {
IDirect3DBaseTexture9* pContainer = this->m_container;
IDirect3DBaseTexture9* pContainer = this->m_baseTexture;
// Can't have a swapchain container for a volume.
if (pContainer != nullptr) {
reinterpret_cast<D3D9Texture3D*> (pContainer)->ReleasePrivate();