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

View File

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

View File

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

View File

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

View File

@ -463,7 +463,7 @@ namespace dxvk {
return D3DERR_INVALIDCALL; return D3DERR_INVALIDCALL;
} }
*ppBackBuffer = m_backBuffers[iBackBuffer].ref(); *ppBackBuffer = ref(m_backBuffers[iBackBuffer].get());
return D3D_OK; return D3D_OK;
} }
@ -712,7 +712,7 @@ namespace dxvk {
if (iBackBuffer >= m_presentParams.BackBufferCount) if (iBackBuffer >= m_presentParams.BackBufferCount)
return nullptr; 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 // Rotate swap chain buffers so that the back
// buffer at index 0 becomes the front buffer. // buffer at index 0 becomes the front buffer.
for (uint32_t i = 1; i < m_backBuffers.size(); i++) 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); m_parent->m_flags.set(D3D9DeviceFlag::DirtyFramebuffer);
} }
@ -1035,7 +1035,7 @@ namespace dxvk {
desc.Discard = FALSE; desc.Discard = FALSE;
for (uint32_t i = 0; i < m_backBuffers.size(); i++) 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(); auto swapImage = m_backBuffers[0]->GetCommonTexture()->GetImage();

View File

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

View File

@ -12,6 +12,7 @@ namespace dxvk {
pDevice, pDevice,
new D3D9CommonTexture( pDevice, pDesc, D3DRTYPE_VOLUMETEXTURE ), new D3D9CommonTexture( pDevice, pDesc, D3DRTYPE_VOLUMETEXTURE ),
0, 0, 0, 0,
nullptr,
nullptr) { } nullptr) { }
@ -25,11 +26,14 @@ namespace dxvk {
pDevice, pDevice,
pTexture, pTexture,
Face, MipLevel, Face, MipLevel,
pContainer,
pContainer) { } pContainer) { }
void D3D9Volume::AddRefPrivate() { 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) { if (pContainer != nullptr) {
reinterpret_cast<D3D9Texture3D*> (pContainer)->AddRefPrivate(); reinterpret_cast<D3D9Texture3D*> (pContainer)->AddRefPrivate();
@ -41,7 +45,9 @@ namespace dxvk {
void D3D9Volume::ReleasePrivate() { 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) { if (pContainer != nullptr) {
reinterpret_cast<D3D9Texture3D*> (pContainer)->ReleasePrivate(); reinterpret_cast<D3D9Texture3D*> (pContainer)->ReleasePrivate();