Commit 8a6a40bf authored by Joshua Ashton's avatar Joshua Ashton 🐸

[d3d9] COM Overhaul, fix memory/resource leaks in reset/deletion/stateblocks

Fixes and matches ref-counting for device child resources to native d3d9.
Fixes memory and resource leaks in stateblocks, deletion and device resetting.
parent 2ac6a86c
Pipeline #956 passed with stage
in 4 minutes and 6 seconds
......@@ -64,10 +64,6 @@ namespace dxvk {
};
inline D3D9CommonBuffer* GetCommonBuffer(D3D9VertexBuffer* pResource) {
return pResource != nullptr ? pResource->GetCommonBuffer() : nullptr;
}
using D3D9IndexBufferBase = D3D9Buffer<IDirect3DIndexBuffer9>;
class D3D9IndexBuffer final : public D3D9IndexBufferBase {
......@@ -88,7 +84,8 @@ namespace dxvk {
};
inline D3D9CommonBuffer* GetCommonBuffer(D3D9IndexBuffer* pResource) {
template <typename T>
inline D3D9CommonBuffer* GetCommonBuffer(const T& pResource) {
return pResource != nullptr ? pResource->GetCommonBuffer() : nullptr;
}
......
#include "d3d9_common_buffer.h"
#include "d3d9_device.h"
#include "d3d9_util.h"
namespace dxvk {
......
......@@ -3,6 +3,7 @@
#include "../dxvk/dxvk_device.h"
#include "d3d9_device_child.h"
#include "d3d9_format.h"
namespace dxvk {
......
#include "d3d9_common_texture.h"
#include "d3d9_util.h"
#include "d3d9_device.h"
#include <algorithm>
......@@ -290,6 +292,18 @@ namespace dxvk {
}
void D3D9CommonTexture::RecreateSampledView(UINT Lod) {
// This will be a no-op for SYSTEMMEM types given we
// don't expose the cap to allow texturing with them.
if (unlikely(m_mapMode == D3D9_COMMON_TEXTURE_MAP_MODE_SYSTEMMEM))
return;
const D3D9_VK_FORMAT_MAPPING formatInfo = m_device->LookupFormat(m_desc.Format);
m_views.Sample = CreateColorViewPair(formatInfo, AllLayers, VK_IMAGE_USAGE_SAMPLED_BIT, Lod);
}
BOOL D3D9CommonTexture::DetermineShadowState() const {
static std::array<D3D9Format, 3> blacklist = {
D3D9Format::INTZ, D3D9Format::DF16, D3D9Format::DF24
......
#pragma once
#include "d3d9_device.h"
#include "d3d9_format.h"
#include "d3d9_util.h"
#include "d3d9_caps.h"
#include "../dxvk/dxvk_device.h"
namespace dxvk {
class D3D9DeviceEx;
/**
* \brief Image memory mapping mode
*
......@@ -300,16 +303,7 @@ namespace dxvk {
* Recreates the main view of the sampler w/ a specific LOD.
* SetLOD only works on MANAGED textures so this is A-okay.
*/
void RecreateSampledView(UINT Lod) {
// This will be a no-op for SYSTEMMEM types given we
// don't expose the cap to allow texturing with them.
if (unlikely(m_mapMode == D3D9_COMMON_TEXTURE_MAP_MODE_SYSTEMMEM))
return;
const D3D9_VK_FORMAT_MAPPING formatInfo = m_device->LookupFormat(m_desc.Format);
m_views.Sample = CreateColorViewPair(formatInfo, AllLayers, VK_IMAGE_USAGE_SAMPLED_BIT, Lod);
}
void RecreateSampledView(UINT Lod);
/**
* \brief Extent
......
......@@ -2,6 +2,8 @@
#include "d3d9_caps.h"
#include "../dxvk/dxvk_buffer.h"
#include "../dxso/dxso_isgn.h"
#include "../util/util_math.h"
......
This diff is collapsed.
......@@ -978,7 +978,8 @@ namespace dxvk {
Com<D3D9Surface, false> m_autoDepthStencil;
std::vector<
IDirect3DSwapChain9Ex*> m_swapchains;
Com<D3D9SwapChainEx,
false>> m_swapchains;
std::unordered_map<
D3D9SamplerKey,
......@@ -1031,11 +1032,6 @@ namespace dxvk {
const DWORD* pShaderBytecode,
const DxsoModuleInfo* pModuleInfo);
template<typename T>
static const D3D9CommonShader* GetCommonShader(T* pShader) {
return pShader != nullptr ? pShader->GetCommonShader() : nullptr;
}
// So we don't do OOB.
template <DxsoProgramType ProgramType,
D3D9ConstantType ConstantType>
......
#pragma once
#include "d3d9_device.h"
#include "d3d9_include.h"
namespace dxvk {
template <typename... Base>
class D3D9DeviceChild : public ComObjectClamp<Base...> {
class D3D9DeviceEx;
template <typename Base>
class D3D9DeviceChild : public ComObjectClamp<Base> {
public:
D3D9DeviceChild(D3D9DeviceEx* pDevice)
: m_parent( pDevice ) { }
ULONG STDMETHODCALLTYPE AddRef() {
uint32_t refCount = this->m_refCount++;
if (unlikely(!refCount)) {
this->AddRefPrivate();
GetDevice()->AddRef();
}
return refCount + 1;
}
ULONG STDMETHODCALLTYPE Release() {
uint32_t refCount = --this->m_refCount;
if (unlikely(!refCount)) {
auto* pDevice = GetDevice();
this->ReleasePrivate();
pDevice->Release();
}
return refCount;
}
HRESULT STDMETHODCALLTYPE GetDevice(IDirect3DDevice9** ppDevice) {
InitReturnPtr(ppDevice);
if (ppDevice == nullptr)
return D3DERR_INVALIDCALL;
*ppDevice = ref(static_cast<IDirect3DDevice9Ex*>(m_parent));
*ppDevice = ref(GetDevice());
return D3D_OK;
}
IDirect3DDevice9Ex* GetDevice() {
return reinterpret_cast<IDirect3DDevice9Ex*>(m_parent);
}
D3D9DeviceEx* GetParent() {
return m_parent;
}
......
#include "d3d9_query.h"
#include "d3d9_device.h"
namespace dxvk {
D3D9Query::D3D9Query(
......
......@@ -2,6 +2,8 @@
#include "d3d9_device_child.h"
#include "../dxvk/dxvk_context.h"
namespace dxvk {
enum D3D9_VK_QUERY_STATE : uint32_t {
......
#include "d3d9_shader.h"
#include "d3d9_device.h"
#include "d3d9_util.h"
namespace dxvk {
......
......@@ -185,6 +185,11 @@ namespace dxvk {
D3D9CommonShader,
DxvkHash, DxvkEq> m_modules;
};
};
template<typename T>
const D3D9CommonShader* GetCommonShader(const T& pShader) {
return pShader != nullptr ? pShader->GetCommonShader() : nullptr;
}
}
\ No newline at end of file
#include "d3d9_state.h"
#include "d3d9_texture.h"
namespace dxvk {
D3D9CapturableState::D3D9CapturableState() {
for (uint32_t i = 0; i < textures.size(); i++)
textures[i] = nullptr;
for (uint32_t i = 0; i < clipPlanes.size(); i++)
clipPlanes[i] = D3D9ClipPlane();
for (uint32_t i = 0; i < streamFreq.size(); i++)
streamFreq[i] = 1;
for (uint32_t i = 0; i < enabledLightIndices.size(); i++)
enabledLightIndices[i] = UINT32_MAX;
}
D3D9CapturableState::~D3D9CapturableState() {
for (uint32_t i = 0; i < textures.size(); i++)
TextureChangePrivate(textures[i], nullptr);
}
}
\ No newline at end of file
......@@ -5,6 +5,11 @@
#include "../dxso/dxso_common.h"
#include "../util/util_matrix.h"
#include "d3d9_surface.h"
#include "d3d9_shader.h"
#include "d3d9_vertex_declaration.h"
#include "d3d9_buffer.h"
#include <array>
#include <bitset>
#include <optional>
......@@ -20,17 +25,11 @@ namespace dxvk {
static constexpr DWORD AlphaToCoverageDisabled = MAKEFOURCC('A', '2', 'M', '0');
static constexpr DWORD AlphaToCoverageEnabled = MAKEFOURCC('A', '2', 'M', '1');;
}
class D3D9Surface;
class D3D9VertexShader;
class D3D9PixelShader;
class D3D9VertexDecl;
class D3D9VertexBuffer;
class D3D9IndexBuffer;
struct D3D9ClipPlane {
float coeff[4];
};
struct D3D9RenderStateInfo {
std::array<float, 3> fogColor = { };
float fogScale = 0.0f;
......@@ -161,7 +160,8 @@ namespace dxvk {
};
struct D3D9VBO {
D3D9VertexBuffer* vertexBuffer = nullptr;
Com<D3D9VertexBuffer, false> vertexBuffer;
UINT offset = 0;
UINT stride = 0;
};
......@@ -181,22 +181,12 @@ namespace dxvk {
};
struct D3D9CapturableState {
D3D9CapturableState() {
for (uint32_t i = 0; i < textures.size(); i++)
textures[i] = nullptr;
D3D9CapturableState();
for (uint32_t i = 0; i < clipPlanes.size(); i++)
clipPlanes[i] = D3D9ClipPlane();
~D3D9CapturableState();
for (uint32_t i = 0; i < streamFreq.size(); i++)
streamFreq[i] = 1;
for (uint32_t i = 0; i < enabledLightIndices.size(); i++)
enabledLightIndices[i] = UINT32_MAX;
}
D3D9VertexDecl* vertexDecl = nullptr;
D3D9IndexBuffer* indices = nullptr;
Com<D3D9VertexDecl, false> vertexDecl;
Com<D3D9IndexBuffer, false> indices;
std::array<DWORD, RenderStateCount> renderStates = { 0 };
......@@ -210,8 +200,8 @@ namespace dxvk {
IDirect3DBaseTexture9*,
SamplerCount> textures;
D3D9VertexShader* vertexShader = nullptr;
D3D9PixelShader* pixelShader = nullptr;
Com<D3D9VertexShader, false> vertexShader;
Com<D3D9PixelShader, false> pixelShader;
D3DVIEWPORT9 viewport;
RECT scissorRect;
......@@ -346,15 +336,10 @@ namespace dxvk {
};
struct Direct3DState9 : public D3D9CapturableState {
Direct3DState9() {
for (uint32_t i = 0; i < renderTargets.size(); i++)
renderTargets[i] = nullptr;
}
std::array<D3D9Surface*, caps::MaxSimultaneousRenderTargets> renderTargets;
std::array<Com<D3D9Surface, false>, caps::MaxSimultaneousRenderTargets> renderTargets;
Com<D3D9Surface, false> depthStencil;
D3D9Surface* depthStencil = nullptr;
};
......
#include "d3d9_stateblock.h"
#include "d3d9_device.h"
#include "d3d9_vertex_declaration.h"
#include "d3d9_buffer.h"
#include "d3d9_shader.h"
......@@ -53,7 +54,7 @@ namespace dxvk {
HRESULT D3D9StateBlock::SetVertexDeclaration(D3D9VertexDecl* pDecl) {
changePrivate(m_state.vertexDecl, pDecl);
m_state.vertexDecl = pDecl;
m_captures.flags.set(D3D9CapturedStateFlag::VertexDecl);
return D3D_OK;
......@@ -61,7 +62,7 @@ namespace dxvk {
HRESULT D3D9StateBlock::SetIndices(D3D9IndexBuffer* pIndexData) {
changePrivate(m_state.indices, pIndexData);
m_state.indices = pIndexData;
m_captures.flags.set(D3D9CapturedStateFlag::Indices);
return D3D_OK;
......@@ -95,7 +96,8 @@ namespace dxvk {
D3D9VertexBuffer* pStreamData,
UINT OffsetInBytes,
UINT Stride) {
changePrivate(m_state.vertexBuffers[StreamNumber].vertexBuffer, pStreamData);
m_state.vertexBuffers[StreamNumber].vertexBuffer = pStreamData;
m_state.vertexBuffers[StreamNumber].offset = OffsetInBytes;
m_state.vertexBuffers[StreamNumber].stride = Stride;
......@@ -124,7 +126,7 @@ namespace dxvk {
HRESULT D3D9StateBlock::SetVertexShader(D3D9VertexShader* pShader) {
changePrivate(m_state.vertexShader, pShader);
m_state.vertexShader = pShader;
m_captures.flags.set(D3D9CapturedStateFlag::VertexShader);
return D3D_OK;
......@@ -132,7 +134,7 @@ namespace dxvk {
HRESULT D3D9StateBlock::SetPixelShader(D3D9PixelShader* pShader) {
changePrivate(m_state.pixelShader, pShader);
m_state.pixelShader = pShader;
m_captures.flags.set(D3D9CapturedStateFlag::PixelShader);
return D3D_OK;
......
#pragma once
#include "d3d9_device_child.h"
#include "d3d9_device.h"
#include "d3d9_state.h"
namespace dxvk {
......@@ -117,7 +118,7 @@ namespace dxvk {
template <typename Dst, typename Src>
void ApplyOrCapture(Dst* dst, const Src* src) {
if (m_captures.flags.test(D3D9CapturedStateFlag::VertexDecl))
dst->SetVertexDeclaration(src->vertexDecl);
dst->SetVertexDeclaration(src->vertexDecl.ptr());
if (m_captures.flags.test(D3D9CapturedStateFlag::StreamFreq)) {
for (uint32_t i = 0; i < caps::MaxStreams; i++) {
......@@ -127,7 +128,7 @@ namespace dxvk {
}
if (m_captures.flags.test(D3D9CapturedStateFlag::Indices))
dst->SetIndices(src->indices);
dst->SetIndices(src->indices.ptr());
if (m_captures.flags.test(D3D9CapturedStateFlag::RenderStates)) {
for (uint32_t i = 0; i < m_captures.renderStates.size(); i++) {
......@@ -153,7 +154,7 @@ namespace dxvk {
const auto& vbo = src->vertexBuffers[i];
dst->SetStreamSource(
i,
vbo.vertexBuffer,
vbo.vertexBuffer.ptr(),
vbo.offset,
vbo.stride);
}
......@@ -171,10 +172,10 @@ namespace dxvk {
}
if (m_captures.flags.test(D3D9CapturedStateFlag::VertexShader))
dst->SetVertexShader(src->vertexShader);
dst->SetVertexShader(src->vertexShader.ptr());
if (m_captures.flags.test(D3D9CapturedStateFlag::PixelShader))
dst->SetPixelShader(src->pixelShader);
dst->SetPixelShader(src->pixelShader.ptr());
if (m_captures.flags.test(D3D9CapturedStateFlag::Transforms)) {
for (uint32_t i = 0; i < m_captures.transforms.size(); i++) {
......
......@@ -46,7 +46,7 @@ namespace dxvk {
if (m_container != nullptr)
return m_container->QueryInterface(riid, ppContainer);
return this->m_parent->QueryInterface(riid, ppContainer);
return this->GetDevice()->QueryInterface(riid, ppContainer);
}
D3D9CommonTexture* GetCommonTexture() {
......
#include "d3d9_surface.h"
#include "d3d9_texture.h"
#include "d3d9_device.h"
namespace dxvk {
D3D9Surface::D3D9Surface(
......
......@@ -61,9 +61,6 @@ namespace dxvk {
m_device->waitForSubmission(&m_presentStatus);
m_device->waitForIdle();
if (m_backBuffer)
m_backBuffer->ReleasePrivate();
}
......@@ -165,7 +162,7 @@ namespace dxvk {
return D3DERR_INVALIDCALL;
}
*ppBackBuffer = ref(m_backBuffer);
*ppBackBuffer = m_backBuffer.ref();
return D3D_OK;
}
......@@ -278,7 +275,7 @@ namespace dxvk {
}
HRESULT D3D9SwapChainEx::Reset(
void D3D9SwapChainEx::Reset(
D3DPRESENT_PARAMETERS* pPresentParams,
D3DDISPLAYMODEEX* pFullscreenDisplayMode) {
auto lock = m_parent->LockDevice();
......@@ -339,8 +336,6 @@ namespace dxvk {
if (FAILED(hr))
SetDialogBoxMode(false);
return D3D_OK;
}
......@@ -418,6 +413,11 @@ namespace dxvk {
}
D3D9Surface* D3D9SwapChainEx::GetBackBuffer(UINT iBackBuffer) {
return m_backBuffer.ptr();
}
void D3D9SwapChainEx::NormalizePresentParameters(D3DPRESENT_PARAMETERS* pPresentParams) {
if (pPresentParams->hDeviceWindow == nullptr)
pPresentParams->hDeviceWindow = m_parent->GetWindow();
......@@ -684,9 +684,6 @@ namespace dxvk {
void D3D9SwapChainEx::CreateBackBuffer() {
// Explicitly destroy current swap image before
// creating a new one to free up resources
if (m_backBuffer)
m_backBuffer->ReleasePrivate();
m_swapImage = nullptr;
m_swapImageResolve = nullptr;
m_swapImageView = nullptr;
......@@ -709,7 +706,6 @@ namespace dxvk {
auto mapping = m_parent->LookupFormat(desc.Format);
m_backBuffer = new D3D9Surface(m_parent, &desc, mapping);
m_backBuffer->AddRefPrivate();
m_swapImage = m_backBuffer->GetCommonTexture()->GetImage();
......
#pragma once
#include "d3d9_device_child.h"
#include "d3d9_device.h"
#include "d3d9_format.h"
#include "../dxvk/hud/dxvk_hud.h"
......@@ -64,7 +65,7 @@ namespace dxvk {
HRESULT STDMETHODCALLTYPE GetDisplayModeEx(D3DDISPLAYMODEEX* pMode, D3DDISPLAYROTATION* pRotation);
HRESULT Reset(
void Reset(
D3DPRESENT_PARAMETERS* pPresentParams,
D3DDISPLAYMODEEX* pFullscreenDisplayMode);
......@@ -80,6 +81,8 @@ namespace dxvk {
HRESULT SetDialogBoxMode(bool bEnableDialogs);
D3D9Surface* GetBackBuffer(UINT iBackBuffer);
private:
enum BindingIds : uint32_t {
......@@ -125,7 +128,7 @@ namespace dxvk {
DxvkLogicOpState m_loState;
DxvkBlendMode m_blendMode;
D3D9Surface* m_backBuffer = nullptr;
Com<D3D9Surface, false> m_backBuffer = nullptr;
RECT m_srcRect;
RECT m_dstRect;
......
#include "d3d9_swvp_emu.h"
#include "d3d9_device.h"
#include "d3d9_vertex_declaration.h"
#include "../spirv/spirv_module.h"
......
#pragma once
#include "d3d9_device.h"
#include "d3d9_surface.h"
#include "d3d9_volume.h"
#include "d3d9_util.h"
......
......@@ -98,17 +98,6 @@ namespace dxvk {
VkImageUsageFlags GetImageUsageFlags(DWORD Usage);
template <typename T>
void changePrivate(T*& srcPtr, T* newPtr) {
if (srcPtr != nullptr)
srcPtr->ReleasePrivate();
if (newPtr != nullptr)
newPtr->AddRefPrivate();
srcPtr = newPtr;
}
inline void DecodeD3DCOLOR(D3DCOLOR color, float* rgba) {
// Encoded in D3DCOLOR as argb
rgba[3] = (float)((color & 0xff000000) >> 24) / 255.0f;
......
#pragma once
#include "d3d9_device_child.h"
#include "d3d9_util.h"
#include <vector>
......
#include "d3d9_volume.h"
#include "d3d9_device.h"
#include "d3d9_texture.h"
namespace dxvk {
......
......@@ -12,6 +12,7 @@ d3d9_src = [
'd3d9_adapter.cpp',
'd3d9_monitor.cpp',
'd3d9_device.cpp',
'd3d9_state.cpp',
'd3d9_cursor.cpp',
'd3d9_swapchain.cpp',
'd3d9_format.cpp',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment