Add proper refcounting to wrapped D3D9 device

This commit is contained in:
baldurk
2016-10-13 11:53:06 +02:00
parent d38ad5e2c9
commit c6a9be6df5
8 changed files with 224 additions and 33 deletions
+58
View File
@@ -0,0 +1,58 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2016 Baldur Karlsson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
#include "d3d9_common.h"
#include "d3d9_device.h"
unsigned int RefCounter9::SoftRef(WrappedD3DDevice9 *device)
{
unsigned int ret = AddRef();
if(device)
device->SoftRef();
else
RDCWARN("No device pointer, is a deleted resource being AddRef()d?");
return ret;
}
unsigned int RefCounter9::SoftRelease(WrappedD3DDevice9 *device)
{
unsigned int ret = Release();
if(device)
device->SoftRelease();
else
RDCWARN("No device pointer, is a deleted resource being Release()d?");
return ret;
}
void RefCounter9::AddDeviceSoftref(WrappedD3DDevice9 *device)
{
if(device)
device->SoftRef();
}
void RefCounter9::ReleaseDeviceSoftref(WrappedD3DDevice9 *device)
{
if(device)
device->SoftRelease();
}
+79
View File
@@ -0,0 +1,79 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2016 Baldur Karlsson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
#pragma once
#include "api/replay/renderdoc_replay.h"
#include "core/core.h"
#include "driver/dx/official/d3d9.h"
class WrappedD3DDevice9;
class RefCounter9
{
private:
IUnknown *m_pReal;
unsigned int m_iRefcount;
bool m_SelfDeleting;
protected:
void SetSelfDeleting(bool selfDelete) { m_SelfDeleting = selfDelete; }
// used for derived classes that need to soft ref but are handling their
// own self-deletion
static void AddDeviceSoftref(WrappedD3DDevice9 *device);
static void ReleaseDeviceSoftref(WrappedD3DDevice9 *device);
public:
RefCounter9(IUnknown *real, bool selfDelete = true)
: m_pReal(real), m_iRefcount(1), m_SelfDeleting(selfDelete)
{
}
virtual ~RefCounter9() {}
unsigned int GetRefCount() { return m_iRefcount; }
//////////////////////////////
// implement IUnknown
HRESULT STDMETHODCALLTYPE QueryInterface(
/* [in] */ REFIID riid,
/* [annotation][iid_is][out] */
__RPC__deref_out void **ppvObject)
{
return E_NOINTERFACE;
}
ULONG STDMETHODCALLTYPE AddRef()
{
InterlockedIncrement(&m_iRefcount);
return m_iRefcount;
}
ULONG STDMETHODCALLTYPE Release()
{
unsigned int ret = InterlockedDecrement(&m_iRefcount);
if(ret == 0 && m_SelfDeleting)
delete this;
return ret;
}
unsigned int SoftRef(WrappedD3DDevice9 *device);
unsigned int SoftRelease(WrappedD3DDevice9 *device);
};
+2 -2
View File
@@ -186,8 +186,8 @@ void D3D9DebugManager::RenderTextInternal(float x, float y, const char *text)
res |= m_WrappedDevice->SetTransform(D3DTS_VIEW, &identity);
// enable fixed function pipeline
res |= m_WrappedDevice->SetVertexShader(nullptr);
res |= m_WrappedDevice->SetPixelShader(nullptr);
res |= m_WrappedDevice->SetVertexShader(NULL);
res |= m_WrappedDevice->SetPixelShader(NULL);
// default render states
res |= m_WrappedDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
+1 -1
View File
@@ -27,9 +27,9 @@
#include <list>
#include <map>
#include <utility>
#include "common/common.h"
#include "driver/dx/official/d3d9.h"
#include "stb/stb_truetype.h"
#include "d3d9_common.h"
#include "d3d9_device.h"
class D3D9DebugManager
+51 -25
View File
@@ -24,18 +24,67 @@
#include "d3d9_device.h"
#include "core/core.h"
#include "serialise/serialiser.h"
#include "d3d9_debug.h"
#include "windows.h" // TODO investigate how else this can be solved
WrappedD3DDevice9::WrappedD3DDevice9(IDirect3DDevice9 *device)
: m_device(device), m_DebugManager(nullptr)
: m_RefCounter(device, false),
m_SoftRefCounter(NULL, false),
m_device(device),
m_DebugManager(NULL)
{
m_FrameCounter = 0;
// refcounters implicitly construct with one reference, but we don't start with any soft
// references.
m_SoftRefCounter.Release();
m_InternalRefcount = 0;
m_Alive = true;
}
void WrappedD3DDevice9::CheckForDeath()
{
if(!m_Alive)
return;
if(m_RefCounter.GetRefCount() == 0)
{
RDCASSERT(m_SoftRefCounter.GetRefCount() >= m_InternalRefcount);
if(m_SoftRefCounter.GetRefCount() <= m_InternalRefcount)
{
m_Alive = false;
delete this;
}
}
}
WrappedD3DDevice9::~WrappedD3DDevice9()
{
SAFE_DELETE(m_DebugManager);
SAFE_RELEASE(m_device);
}
HRESULT WrappedD3DDevice9::QueryInterface(REFIID riid, void **ppvObject)
{
// RenderDoc UUID {A7AA6116-9C8D-4BBA-9083-B4D816B71B78}
static const GUID IRenderDoc_uuid = {
0xa7aa6116, 0x9c8d, 0x4bba, {0x90, 0x83, 0xb4, 0xd8, 0x16, 0xb7, 0x1b, 0x78}};
if(riid == IRenderDoc_uuid)
{
AddRef();
*ppvObject = (IUnknown *)this;
return S_OK;
}
else
{
string guid = ToStr::Get(riid);
RDCWARN("Querying IDirect3DDevice9 for interface: %s", guid.c_str());
}
return m_device->QueryInterface(riid, ppvObject);
}
void WrappedD3DDevice9::LazyInit()
@@ -43,29 +92,6 @@ void WrappedD3DDevice9::LazyInit()
m_DebugManager = new D3D9DebugManager(this);
}
HRESULT __stdcall WrappedD3DDevice9::QueryInterface(REFIID riid, void **ppvObj)
{
return m_device->QueryInterface(riid, ppvObj);
}
ULONG __stdcall WrappedD3DDevice9::AddRef()
{
ULONG refCount;
refCount = m_device->AddRef();
return refCount;
}
ULONG __stdcall WrappedD3DDevice9::Release()
{
ULONG refCount;
refCount = m_device->Release();
if(refCount == 0)
{
delete this;
}
return refCount;
}
HRESULT __stdcall WrappedD3DDevice9::TestCooperativeLevel()
{
return m_device->TestCooperativeLevel();
+25 -5
View File
@@ -23,9 +23,8 @@
******************************************************************************/
#pragma once
#include "common/common.h"
#include "common/timing.h"
#include "driver/dx/official/d3d9.h"
#include "d3d9_common.h"
class D3D9DebugManager;
@@ -37,11 +36,25 @@ public:
void LazyInit();
void InternalRef() { InterlockedIncrement(&m_InternalRefcount); }
void InternalRelease() { InterlockedDecrement(&m_InternalRefcount); }
void SoftRef() { m_SoftRefCounter.AddRef(); }
void SoftRelease()
{
m_SoftRefCounter.Release();
CheckForDeath();
}
D3D9DebugManager *GetDebugManager() { return m_DebugManager; }
/*** IUnknown methods ***/
virtual HRESULT __stdcall QueryInterface(REFIID riid, void **ppvObj);
virtual ULONG __stdcall AddRef();
virtual ULONG __stdcall Release();
ULONG STDMETHODCALLTYPE AddRef() { return m_RefCounter.AddRef(); }
ULONG STDMETHODCALLTYPE Release()
{
unsigned int ret = m_RefCounter.Release();
CheckForDeath();
return ret;
}
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
/*** IDirect3DDevice9 methods ***/
virtual HRESULT __stdcall TestCooperativeLevel();
@@ -229,9 +242,16 @@ public:
virtual HRESULT __stdcall CreateQuery(D3DQUERYTYPE Type, IDirect3DQuery9 **ppQuery);
private:
void CheckForDeath();
IDirect3DDevice9 *m_device;
D3D9DebugManager *m_DebugManager;
unsigned int m_InternalRefcount;
RefCounter9 m_RefCounter;
RefCounter9 m_SoftRefCounter;
bool m_Alive;
uint32_t m_FrameCounter;
};
@@ -184,6 +184,7 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="d3d9_common.cpp" />
<ClCompile Include="d3d9_debug.cpp" />
<ClCompile Include="d3d9_device.cpp" />
<ClCompile Include="d3d9_hooks.cpp" />
@@ -194,6 +195,7 @@
<ClInclude Include="..\dx\official\d3d9types.h" />
<ClInclude Include="..\dx\official\d3dcommon.h" />
<ClInclude Include="..\dx\official\d3dcompiler.h" />
<ClInclude Include="d3d9_common.h" />
<ClInclude Include="d3d9_debug.h" />
<ClInclude Include="d3d9_device.h" />
</ItemGroup>
@@ -24,6 +24,9 @@
<ClCompile Include="d3d9_device.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="d3d9_common.cpp">
<Filter>Common</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\dx\official\d3d9.h">
@@ -47,5 +50,8 @@
<ClInclude Include="d3d9_device.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="d3d9_common.h">
<Filter>Common</Filter>
</ClInclude>
</ItemGroup>
</Project>