Refactor and optimise D3D11 refcounting implementation

* In heavy D3D11 workloads the refcounting overhead especially during fast
  binding changes was significant. Refactoring the refcounting to work on a
  different model and deferring destruction of objects removes most of the
  overhead.
This commit is contained in:
baldurk committed 2020-09-10 13:35:32 +01:00
1 parent fb19ccb535
commit fdeea5204d
32 files changed
+1933 -816

No files matched your search

+24 -53
View File
@@ -219,62 +219,33 @@ inline rdcstr GetDebugName(T *pObj)
return rdcstr();
}
class RefCounter
{
private:
IUnknown *m_pReal;
unsigned int m_iRefcount;
bool m_SelfDeleting;
#define SAFE_INTADDREF(p) \
do \
{ \
if(p) \
{ \
IntAddRef(p); \
} \
} while((void)0, 0)
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(WrappedID3D11Device *device);
static void ReleaseDeviceSoftref(WrappedID3D11Device *device);
#define SAFE_INTRELEASE(p) \
do \
{ \
if(p) \
{ \
IntRelease(p); \
(p) = NULL; \
} \
} while((void)0, 0)
public:
RefCounter(IUnknown *real, bool selfDelete = true)
: m_pReal(real), m_iRefcount(1), m_SelfDeleting(selfDelete)
{
}
virtual ~RefCounter() {}
unsigned int GetRefCount() { return m_iRefcount; }
//////////////////////////////
// implement IUnknown
HRESULT STDMETHODCALLTYPE QueryInterface(
/* [in] */ REFIID riid,
/* [annotation][iid_is][out] */
__RPC__deref_out void **ppvObject);
#if ENABLED(RDOC_DEVEL)
#define ASSERT_REFCOUNT(refcount) \
if(refcount < 0) \
RDCERR("Unbalanced refcounting, refcount has dropped below 0");
#else
#define ASSERT_REFCOUNT(refcount)
#endif
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(WrappedID3D11Device *device);
unsigned int SoftRelease(WrappedID3D11Device *device);
};
#define IMPLEMENT_IUNKNOWN_WITH_REFCOUNTER \
ULONG STDMETHODCALLTYPE AddRef() { return RefCounter::AddRef(); } \
ULONG STDMETHODCALLTYPE Release() { return RefCounter::Release(); } \
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) \
{ \
return RefCounter::QueryInterface(riid, ppvObject); \
}
#define IMPLEMENT_IUNKNOWN_WITH_REFCOUNTER_CUSTOMQUERY \
ULONG STDMETHODCALLTYPE AddRef() { return RefCounter::AddRef(); } \
ULONG STDMETHODCALLTYPE Release() { return RefCounter::Release(); }
#define IMPLEMENT_FUNCTION_SERIALISED(ret, func, ...) \
ret func(__VA_ARGS__); \
template <typename SerialiserType> \
+71 -26
View File
@@ -37,37 +37,33 @@ WRAPPED_POOL_INST(WrappedID3D11CommandList);
INT STDMETHODCALLTYPE WrappedID3DUserDefinedAnnotation::BeginEvent(LPCWSTR Name)
{
if(m_Context)
return m_Context->PushMarker(0, Name);
return -1;
return m_Context->PushMarker(0, Name);
}
INT STDMETHODCALLTYPE WrappedID3DUserDefinedAnnotation::EndEvent()
{
if(m_Context)
return m_Context->PopMarker();
return -1;
return m_Context->PopMarker();
}
void STDMETHODCALLTYPE WrappedID3DUserDefinedAnnotation::SetMarker(LPCWSTR Name)
{
if(m_Context)
return m_Context->SetMarker(0, Name);
return m_Context->SetMarker(0, Name);
}
ULONG STDMETHODCALLTYPE WrappedID3DUserDefinedAnnotation::AddRef()
{
return m_Context->AddRef();
}
ULONG STDMETHODCALLTYPE WrappedID3DUserDefinedAnnotation::Release()
{
return m_Context->Release();
}
HRESULT STDMETHODCALLTYPE WrappedID3DUserDefinedAnnotation::QueryInterface(REFIID riid,
void **ppvObject)
{
if(riid == __uuidof(ID3DUserDefinedAnnotation))
{
*ppvObject = (ID3DUserDefinedAnnotation *)this;
AddRef();
return S_OK;
}
return E_NOINTERFACE;
return m_Context->QueryInterface(riid, ppvObject);
}
extern uint32_t NullCBOffsets[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT];
@@ -75,8 +71,7 @@ extern uint32_t NullCBCounts[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT];
WrappedID3D11DeviceContext::WrappedID3D11DeviceContext(WrappedID3D11Device *realDevice,
ID3D11DeviceContext *context)
: RefCounter(context),
m_pDevice(realDevice),
: m_pDevice(realDevice),
m_pRealContext(context),
m_ScratchSerialiser(new StreamWriter(1024), Ownership::Stream)
{
@@ -129,6 +124,8 @@ WrappedID3D11DeviceContext::WrappedID3D11DeviceContext(WrappedID3D11Device *real
m_pRealContext->QueryInterface(__uuidof(ID3D11VideoContext2), (void **)&m_WrappedVideo.m_pReal2);
}
m_UserAnnotation.SetContext(this);
m_NeedUpdateSubWorkaround = false;
if(m_pRealContext)
{
@@ -177,12 +174,18 @@ WrappedID3D11DeviceContext::WrappedID3D11DeviceContext(WrappedID3D11Device *real
m_CurDrawcallID = 1;
m_MarkerIndentLevel = 0;
m_UserAnnotation.SetContext(this);
m_CurrentPipelineState = new D3D11RenderState(D3D11RenderState::Empty);
m_DeferredSavedState = NULL;
m_DoStateVerify = IsCaptureMode(m_State);
// take a reference on the device, as with all ID3D11DeviceChild objects.
m_pDevice->AddRef();
// start with 1 ext ref and 0 int refs
m_ExtRef = 1;
m_IntRef = 0;
if(!context || GetType() == D3D11_DEVICE_CONTEXT_IMMEDIATE)
{
m_CurrentPipelineState->SetImmediatePipeline(m_pDevice);
@@ -192,7 +195,6 @@ WrappedID3D11DeviceContext::WrappedID3D11DeviceContext(WrappedID3D11Device *real
else
{
m_CurrentPipelineState->SetDevice(m_pDevice);
m_pDevice->SoftRef();
// we haven't actually marked active, but this makes the check much easier - just look at this
// bool flag rather than "if immediate and not flagged"
@@ -240,8 +242,11 @@ WrappedID3D11DeviceContext::~WrappedID3D11DeviceContext()
void WrappedID3D11DeviceContext::GetDevice(ID3D11Device **ppDevice)
{
*ppDevice = (ID3D11Device *)m_pDevice;
(*ppDevice)->AddRef();
if(ppDevice)
{
*ppDevice = (ID3D11Device *)m_pDevice;
(*ppDevice)->AddRef();
}
}
bool WrappedID3D11DeviceContext::HasNonMarkerEvents()
@@ -1360,6 +1365,46 @@ void WrappedID3D11DeviceContext::ClearMaps()
m_OpenMaps.clear();
}
void WrappedID3D11DeviceContext::IntAddRef()
{
Atomic::Inc32(&m_IntRef);
}
void WrappedID3D11DeviceContext::IntRelease()
{
Atomic::Dec32(&m_IntRef);
ASSERT_REFCOUNT(m_IntRef);
// don't defer destruction of device contexts, delete them immediately.
if(m_IntRef + m_ExtRef == 0)
delete this;
}
ULONG STDMETHODCALLTYPE WrappedID3D11DeviceContext::AddRef()
{
// if we're about to create a new external reference on this object, add back our reference on
// the device
if(m_ExtRef == 0)
m_pDevice->AddRef();
Atomic::Inc32(&m_ExtRef);
return (ULONG)m_ExtRef;
}
ULONG STDMETHODCALLTYPE WrappedID3D11DeviceContext::Release()
{
Atomic::Dec32(&m_ExtRef);
ASSERT_REFCOUNT(m_ExtRef);
// if we just released the last external reference on this object, release our reference on the
// device.
if(m_ExtRef == 0)
m_pDevice->Release();
if(m_IntRef + m_ExtRef == 0)
{
delete this;
return 0;
}
return (ULONG)m_ExtRef;
}
HRESULT STDMETHODCALLTYPE WrappedID3D11DeviceContext::QueryInterface(REFIID riid, void **ppvObject)
{
if(riid == __uuidof(IUnknown))
@@ -1443,7 +1488,7 @@ HRESULT STDMETHODCALLTYPE WrappedID3D11DeviceContext::QueryInterface(REFIID riid
else if(riid == __uuidof(ID3DUserDefinedAnnotation))
{
*ppvObject = (ID3DUserDefinedAnnotation *)&m_UserAnnotation;
m_UserAnnotation.AddRef();
AddRef();
return S_OK;
}
else if(riid == __uuidof(ID3D11InfoQueue))
@@ -1461,7 +1506,7 @@ HRESULT STDMETHODCALLTYPE WrappedID3D11DeviceContext::QueryInterface(REFIID riid
WarnUnknownGUID("ID3D11DeviceContext", riid);
}
return RefCounter::QueryInterface(riid, ppvObject);
return RefCountDXGIObject::WrapQueryInterface(m_pRealContext, riid, ppvObject);
}
#pragma region Record Statistics
+16 -9
View File
@@ -69,14 +69,13 @@ struct MapIntercept
class WrappedID3D11DeviceContext;
// ID3DUserDefinedAnnotation
class WrappedID3DUserDefinedAnnotation : public RefCounter, public ID3DUserDefinedAnnotation
class WrappedID3DUserDefinedAnnotation : public ID3DUserDefinedAnnotation
{
public:
WrappedID3DUserDefinedAnnotation() : RefCounter(NULL), m_Context(NULL) {}
WrappedID3DUserDefinedAnnotation() : m_Context(NULL) {}
void SetContext(WrappedID3D11DeviceContext *ctx) { m_Context = ctx; }
// doesn't need to soft-ref the device, for once!
IMPLEMENT_IUNKNOWN_WITH_REFCOUNTER_CUSTOMQUERY;
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
virtual INT STDMETHODCALLTYPE BeginEvent(LPCWSTR Name);
@@ -94,7 +93,7 @@ enum CaptureFailReason
CaptureFailed_UncappedCmdlist,
};
class WrappedID3D11DeviceContext : public RefCounter, public ID3D11DeviceContext4
class WrappedID3D11DeviceContext : public ID3D11DeviceContext4
{
private:
friend class WrappedID3D11DeviceContext;
@@ -116,6 +115,10 @@ private:
}
};
// we manually implement ID3D11DeviceChild instead of using WrappedID3D11DeviceChild because the
// device contexts can be special
int32_t m_ExtRef;
int32_t m_IntRef;
std::set<ResourceId> m_DeferredDirty;
std::set<ResourceId> m_DeferredReferences;
@@ -325,14 +328,18 @@ public:
int ThreadSafe_BeginEvent(uint32_t col, const wchar_t *name);
int ThreadSafe_EndEvent();
// internal addref/release
void IntAddRef();
void IntRelease();
//////////////////////////////
// implement IUnknown
ULONG STDMETHODCALLTYPE AddRef() { return RefCounter::SoftRef(m_pDevice); }
ULONG STDMETHODCALLTYPE Release() { return RefCounter::SoftRelease(m_pDevice); }
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
//////////////////////////////
// implement IDXGIDeviceChild
// implement ID3D11DeviceChild
virtual HRESULT STDMETHODCALLTYPE SetPrivateData(REFGUID Name, UINT DataSize, const void *pData)
{
@@ -5533,6 +5533,8 @@ void WrappedID3D11DeviceContext::Flush()
m_EmptyCommandList = false;
m_pDevice->FlushPendingDead();
SERIALISE_TIME_CALL(m_pRealContext->Flush());
if(IsActiveCapturing(m_State))
+37 -35
View File
@@ -37,6 +37,23 @@
#include "data/hlsl/hlsl_cbuffers.h"
static void InternalRef(ID3D11DeviceChild *child)
{
if(child)
{
// we don't want any of our internal resources to show up as external references but we do
// certainly want to keep them alive.
// To solve this, we add an internal refcount and remove the implicit external refcount.
// Removing the external refcount means the device will also have no refcount so it will still
// be destroyed at the same time regardless of these objects. The internal ref will keep them
// alive even if the user doesn't have any pointers to them and they aren't bound anywhere.
// Effectively you can think of this as the same as if they were bound to some unknown undefined
// pipeline slot
IntAddRef(child);
child->Release();
}
}
D3D11DebugManager::D3D11DebugManager(WrappedID3D11Device *wrapper)
{
if(RenderDoc::Inst().GetCrashHandler())
@@ -142,31 +159,24 @@ void D3D11DebugManager::InitCommonResources()
{
CopyMSToArrayPS =
shaderCache->MakePShader(multisamplehlsl.c_str(), "RENDERDOC_CopyMSToArray", "ps_5_0");
if(CopyMSToArrayPS)
m_pDevice->InternalRef();
InternalRef(CopyMSToArrayPS);
CopyArrayToMSPS =
shaderCache->MakePShader(multisamplehlsl.c_str(), "RENDERDOC_CopyArrayToMS", "ps_5_0");
if(CopyArrayToMSPS)
m_pDevice->InternalRef();
InternalRef(CopyArrayToMSPS);
FloatCopyMSToArrayPS =
shaderCache->MakePShader(multisamplehlsl.c_str(), "RENDERDOC_FloatCopyMSToArray", "ps_5_0");
if(FloatCopyMSToArrayPS)
m_pDevice->InternalRef();
InternalRef(FloatCopyMSToArrayPS);
FloatCopyArrayToMSPS =
shaderCache->MakePShader(multisamplehlsl.c_str(), "RENDERDOC_FloatCopyArrayToMS", "ps_5_0");
if(FloatCopyArrayToMSPS)
m_pDevice->InternalRef();
InternalRef(FloatCopyArrayToMSPS);
DepthCopyMSToArrayPS =
shaderCache->MakePShader(multisamplehlsl.c_str(), "RENDERDOC_DepthCopyMSToArray", "ps_5_0");
if(DepthCopyMSToArrayPS)
m_pDevice->InternalRef();
InternalRef(DepthCopyMSToArrayPS);
DepthCopyArrayToMSPS =
shaderCache->MakePShader(multisamplehlsl.c_str(), "RENDERDOC_DepthCopyArrayToMS", "ps_5_0");
if(DepthCopyArrayToMSPS)
m_pDevice->InternalRef();
InternalRef(DepthCopyArrayToMSPS);
MSArrayCopyVS = shaderCache->MakeVShader(hlsl.c_str(), "RENDERDOC_FullscreenVS", "vs_4_0");
if(MSArrayCopyVS)
m_pDevice->InternalRef();
InternalRef(MSArrayCopyVS);
}
else
{
@@ -191,7 +201,7 @@ void D3D11DebugManager::InitCommonResources()
for(int i = 0; i < ARRAY_COUNT(PublicCBuffers); i++)
{
PublicCBuffers[i] = MakeCBuffer(PublicCBufferSize);
m_pDevice->InternalRef();
InternalRef(PublicCBuffers[i]);
rm->SetInternalResource(PublicCBuffers[i]);
}
@@ -327,25 +337,18 @@ void D3D11DebugManager::ShutdownResources()
SAFE_RELEASE(PredicateDSV);
SAFE_RELEASE(CopyMSToArrayPS);
m_pDevice->InternalRelease();
SAFE_RELEASE(CopyArrayToMSPS);
m_pDevice->InternalRelease();
SAFE_RELEASE(FloatCopyMSToArrayPS);
m_pDevice->InternalRelease();
SAFE_RELEASE(FloatCopyArrayToMSPS);
m_pDevice->InternalRelease();
SAFE_RELEASE(DepthCopyMSToArrayPS);
m_pDevice->InternalRelease();
SAFE_RELEASE(DepthCopyArrayToMSPS);
m_pDevice->InternalRelease();
SAFE_RELEASE(PixelHistoryUnusedCS);
m_pDevice->InternalRelease();
SAFE_RELEASE(PixelHistoryCopyCS);
m_pDevice->InternalRelease();
// the objects we added with an internal ref, because they're used during capture, should also be
// released with an internal ref.
SAFE_INTRELEASE(CopyMSToArrayPS);
SAFE_INTRELEASE(CopyArrayToMSPS);
SAFE_INTRELEASE(FloatCopyMSToArrayPS);
SAFE_INTRELEASE(FloatCopyArrayToMSPS);
SAFE_INTRELEASE(DepthCopyMSToArrayPS);
SAFE_INTRELEASE(DepthCopyArrayToMSPS);
SAFE_INTRELEASE(MSArrayCopyVS);
SAFE_RELEASE(MSArrayCopyVS);
m_pDevice->InternalRelease();
SAFE_RELEASE(PixelHistoryUnusedCS);
SAFE_RELEASE(PixelHistoryCopyCS);
for(auto it = m_DiscardPatterns.begin(); it != m_DiscardPatterns.end(); it++)
if(it->second)
@@ -358,8 +361,7 @@ void D3D11DebugManager::ShutdownResources()
for(int i = 0; i < ARRAY_COUNT(PublicCBuffers); i++)
{
SAFE_RELEASE(PublicCBuffers[i]);
m_pDevice->InternalRelease();
SAFE_INTRELEASE(PublicCBuffers[i]);
}
}
+155 -98
View File
@@ -42,27 +42,19 @@ WRAPPED_POOL_INST(WrappedID3D11Device);
WrappedID3D11Device *WrappedID3D11Device::m_pCurrentWrappedDevice = NULL;
void WrappedID3D11Device::NewSwapchainBuffer(IUnknown *backbuffer)
{
WrappedID3D11Texture2D1 *wrapped = (WrappedID3D11Texture2D1 *)backbuffer;
if(wrapped)
{
// keep ref as a 'view' (invisible to user)
wrapped->ViewAddRef();
wrapped->Release();
}
}
WrappedID3D11Device::WrappedID3D11Device(ID3D11Device *realDevice, D3D11InitParams params)
: m_RefCounter(realDevice, false),
m_SoftRefCounter(NULL, false),
m_pDevice(realDevice),
m_ScratchSerialiser(new StreamWriter(1024), Ownership::Stream)
: m_pDevice(realDevice), m_ScratchSerialiser(new StreamWriter(1024), Ownership::Stream)
{
if(RenderDoc::Inst().GetCrashHandler())
RenderDoc::Inst().GetCrashHandler()->RegisterMemoryRegion(this, sizeof(WrappedID3D11Device));
// if there's no other device, claim it!
if(m_pCurrentWrappedDevice == NULL)
m_pCurrentWrappedDevice = this;
// start with a refcount of 1
m_RefCount = 1;
m_SectionVersion = D3D11InitParams::CurrentVersion;
uint32_t flags = WriteSerialiser::ChunkDuration | WriteSerialiser::ChunkTimestamp |
@@ -90,13 +82,8 @@ WrappedID3D11Device::WrappedID3D11Device(ID3D11Device *realDevice, D3D11InitPara
m_pDevice->QueryInterface(__uuidof(ID3D11Device5), (void **)&m_pDevice5);
}
// refcounters implicitly construct with one reference, but we don't start with any soft
// references.
m_SoftRefCounter.Release();
m_InternalRefcount = 0;
m_Alive = true;
m_DummyInfoQueue.m_pDevice = this;
m_WrappedInfoQueue.m_pDevice = this;
m_DummyDebug.m_pDevice = this;
m_WrappedDebug.m_pDevice = this;
m_WrappedMultithread.m_pDevice = this;
@@ -183,6 +170,11 @@ WrappedID3D11Device::WrappedID3D11Device(ID3D11Device *realDevice, D3D11InitPara
m_pImmediateContext = new WrappedID3D11DeviceContext(this, context);
// add an internal reference to keep the immediate context always alive until we destroy it, and
// remove the implicit external ref from when any device child is created
m_pImmediateContext->IntAddRef();
m_pImmediateContext->Release();
m_pImmediateContext->GetScratchSerialiser().SetChunkMetadataRecording(
m_ScratchSerialiser.GetChunkMetadataRecording());
@@ -192,6 +184,7 @@ WrappedID3D11Device::WrappedID3D11Device(ID3D11Device *realDevice, D3D11InitPara
if(realDevice)
{
realDevice->QueryInterface(__uuidof(ID3D11InfoQueue), (void **)&m_pInfoQueue);
realDevice->QueryInterface(__uuidof(ID3D11InfoQueue), (void **)&m_WrappedInfoQueue.m_pReal);
realDevice->QueryInterface(__uuidof(ID3D11Debug), (void **)&m_WrappedDebug.m_pDebug);
realDevice->QueryInterface(__uuidof(ID3D11Multithread), (void **)&m_WrappedMultithread.m_pReal);
realDevice->QueryInterface(__uuidof(ID3D11VideoDevice), (void **)&m_WrappedVideo.m_pReal);
@@ -240,6 +233,7 @@ WrappedID3D11Device::WrappedID3D11Device(ID3D11Device *realDevice, D3D11InitPara
// ATI workaround - these dlls can get unloaded and cause a crash.
/*
if(GetModuleHandleA("aticfx32.dll"))
LoadLibraryA("aticfx32.dll");
if(GetModuleHandleA("atiuxpag.dll"))
@@ -258,6 +252,7 @@ WrappedID3D11Device::WrappedID3D11Device(ID3D11Device *realDevice, D3D11InitPara
if(GetModuleHandleA("nvwgf2umx.dll"))
LoadLibraryA("nvwgf2umx.dll");
*/
}
WrappedID3D11Device::~WrappedID3D11Device()
@@ -271,7 +266,7 @@ WrappedID3D11Device::~WrappedID3D11Device()
for(auto it = m_CachedStateObjects.begin(); it != m_CachedStateObjects.end(); ++it)
if(*it)
(*it)->Release();
IntRelease(*it);
m_CachedStateObjects.clear();
@@ -285,7 +280,8 @@ WrappedID3D11Device::~WrappedID3D11Device()
SAFE_RELEASE(m_RealAnnotations);
SAFE_RELEASE(m_pImmediateContext);
m_pImmediateContext->IntRelease();
m_pImmediateContext = NULL;
for(auto it = m_SwapChains.begin(); it != m_SwapChains.end(); ++it)
SAFE_RELEASE(it->second);
@@ -312,6 +308,7 @@ WrappedID3D11Device::~WrappedID3D11Device()
SAFE_DELETE(m_ResourceManager);
SAFE_RELEASE(m_pInfoQueue);
SAFE_RELEASE(m_WrappedInfoQueue.m_pReal);
SAFE_RELEASE(m_WrappedMultithread.m_pReal);
SAFE_RELEASE(m_WrappedVideo.m_pReal);
SAFE_RELEASE(m_WrappedVideo.m_pReal1);
@@ -327,40 +324,40 @@ WrappedID3D11Device::~WrappedID3D11Device()
RDCASSERT(WrappedID3D11Texture3D1::m_TextureList.empty());
}
delete m_Replay;
SAFE_DELETE(m_Replay);
if(RenderDoc::Inst().GetCrashHandler())
RenderDoc::Inst().GetCrashHandler()->UnregisterMemoryRegion(this);
}
void WrappedID3D11Device::CheckForDeath()
HRESULT STDMETHODCALLTYPE DummyID3D11InfoQueue::QueryInterface(REFIID riid, void **ppvObject)
{
if(!m_Alive)
return;
if(m_RefCounter.GetRefCount() == 0)
{
RDCASSERT(m_SoftRefCounter.GetRefCount() >= m_InternalRefcount);
// MEGA HACK
if(m_SoftRefCounter.GetRefCount() <= m_InternalRefcount || IsReplayMode(m_State))
{
m_Alive = false;
delete this;
}
}
return m_pDevice->QueryInterface(riid, ppvObject);
}
ULONG STDMETHODCALLTYPE DummyID3D11InfoQueue::AddRef()
{
m_pDevice->AddRef();
return 1;
return m_pDevice->AddRef();
}
ULONG STDMETHODCALLTYPE DummyID3D11InfoQueue::Release()
{
m_pDevice->Release();
return 1;
return m_pDevice->Release();
}
HRESULT STDMETHODCALLTYPE WrappedID3D11InfoQueue::QueryInterface(REFIID riid, void **ppvObject)
{
return m_pDevice->QueryInterface(riid, ppvObject);
}
ULONG STDMETHODCALLTYPE WrappedID3D11InfoQueue::AddRef()
{
return m_pDevice->AddRef();
}
ULONG STDMETHODCALLTYPE WrappedID3D11InfoQueue::Release()
{
return m_pDevice->Release();
}
HRESULT STDMETHODCALLTYPE DummyID3D11Debug::QueryInterface(REFIID riid, void **ppvObject)
@@ -370,43 +367,27 @@ HRESULT STDMETHODCALLTYPE DummyID3D11Debug::QueryInterface(REFIID riid, void **p
ULONG STDMETHODCALLTYPE DummyID3D11Debug::AddRef()
{
m_pDevice->AddRef();
return 1;
return m_pDevice->AddRef();
}
ULONG STDMETHODCALLTYPE DummyID3D11Debug::Release()
{
m_pDevice->Release();
return 1;
return m_pDevice->Release();
}
HRESULT STDMETHODCALLTYPE WrappedD3D11Multithread::QueryInterface(REFIID riid, void **ppvObject)
{
if(riid == __uuidof(IUnknown))
{
*ppvObject = (IUnknown *)this;
AddRef();
return S_OK;
}
if(riid == __uuidof(ID3D11Multithread))
{
*ppvObject = (ID3D11Multithread *)this;
AddRef();
return S_OK;
}
return E_NOINTERFACE;
return m_pDevice->QueryInterface(riid, ppvObject);
}
ULONG STDMETHODCALLTYPE WrappedD3D11Multithread::AddRef()
{
m_pDevice->AddRef();
return 1;
return m_pDevice->AddRef();
}
ULONG STDMETHODCALLTYPE WrappedD3D11Multithread::Release()
{
m_pDevice->Release();
return 1;
return m_pDevice->Release();
}
void STDMETHODCALLTYPE WrappedD3D11Multithread::Enter()
@@ -693,8 +674,8 @@ HRESULT WrappedID3D11Device::QueryInterface(REFIID riid, void **ppvObject)
}
else if(riid == __uuidof(ID3D11Multithread))
{
AddRef();
*ppvObject = (ID3D11Multithread *)&m_WrappedMultithread;
m_WrappedMultithread.AddRef();
return S_OK;
}
else if(riid == ID3D11ShaderTraceFactory_uuid)
@@ -727,8 +708,8 @@ HRESULT WrappedID3D11Device::QueryInterface(REFIID riid, void **ppvObject)
{
if(m_pInfoQueue)
{
*ppvObject = m_pInfoQueue;
m_pInfoQueue->AddRef();
*ppvObject = (ID3D11InfoQueue *)&m_WrappedInfoQueue;
m_WrappedInfoQueue.AddRef();
return S_OK;
}
else
@@ -749,8 +730,8 @@ HRESULT WrappedID3D11Device::QueryInterface(REFIID riid, void **ppvObject)
// return our wrapper
if(m_WrappedDebug.m_pDebug)
{
AddRef();
*ppvObject = (ID3D11Debug *)&m_WrappedDebug;
m_WrappedDebug.AddRef();
return S_OK;
}
else
@@ -775,7 +756,7 @@ HRESULT WrappedID3D11Device::QueryInterface(REFIID riid, void **ppvObject)
WarnUnknownGUID("ID3D11Device", riid);
return m_RefCounter.QueryInterface(riid, ppvObject);
return RefCountDXGIObject::WrapQueryInterface(m_pDevice, riid, ppvObject);
}
rdcstr WrappedID3D11Device::GetChunkName(uint32_t idx)
@@ -1444,6 +1425,16 @@ void WrappedID3D11Device::ReplayLog(uint32_t startEventID, uint32_t endEventID,
D3D11MarkerRegion::Set("!!!!RenderDoc Internal: Done replay");
}
void WrappedID3D11Device::NewSwapchainBuffer(IUnknown *backbuffer)
{
WrappedID3D11Texture2D1 *wrapped = (WrappedID3D11Texture2D1 *)backbuffer;
// add internal reference to keep this texture alive
SAFE_INTADDREF(wrapped);
// release the external reference
wrapped->Release();
}
void WrappedID3D11Device::ReleaseSwapchainResources(IDXGISwapper *swapper, UINT QueueCount,
IUnknown *const *ppPresentQueue,
IUnknown **unwrappedQueues)
@@ -1476,7 +1467,7 @@ void WrappedID3D11Device::ReleaseSwapchainResources(IDXGISwapper *swapper, UINT
}
}
wrapped11->ViewRelease();
SAFE_INTRELEASE(wrapped11);
}
wrapped11 = NULL;
@@ -1488,6 +1479,8 @@ void WrappedID3D11Device::ReleaseSwapchainResources(IDXGISwapper *swapper, UINT
SAFE_RELEASE(it->second);
m_SwapChains.erase(it);
}
FlushPendingDead();
}
template <typename SerialiserType>
@@ -1633,6 +1626,88 @@ IDXGIResource *WrappedID3D11Device::WrapExternalDXGIResource(IDXGIResource *res)
return (IDXGIResource *)voidRes;
}
void WrappedID3D11Device::ReportDeath(ID3D11DeviceChild *obj)
{
SCOPED_LOCK(m_D3DLock);
m_DeadObjects.push_back(obj);
// if we're shutting down, immediately flush the object as dead. This isn't super efficient but
// it's not the end of the world
if(m_RefCount == 0)
FlushPendingDead();
}
void WrappedID3D11Device::FlushPendingDead()
{
SCOPED_LOCK(m_D3DLock);
// to be safe, don't destroy anything while active capturing
if(IsActiveCapturing(m_State))
return;
D3D11ResourceManager *rm = GetResourceManager();
int pass = 0;
do
{
rdcarray<ID3D11DeviceChild *> objs;
objs.swap(m_DeadObjects);
for(ID3D11DeviceChild *child : objs)
{
// only wrapped objects are reported for death
WrappedDeviceChild11<ID3D11DeviceChild> *wrapped =
(WrappedDeviceChild11<ID3D11DeviceChild> *)child;
// is this object still dead? If so delete it, otherwise ignore it.
if(wrapped->GetIntRefCount() == 0 && wrapped->GetExtRefCount() == 0)
{
ResourceId id = wrapped->GetResourceID();
// clean up book-keeping
rm->RemoveWrapper(wrapped->GetReal());
rm->ReleaseCurrentResource(id);
D3D11ResourceRecord *record = GetResourceManager()->GetResourceRecord(id);
if(record)
record->Delete(GetResourceManager());
if(GetResourceManager()->HasLiveResource(id))
GetResourceManager()->EraseLiveResource(id);
// this is a bit of a hack. the vtable for e.g. a wrapped blend state will have:
//
// [IUnknown][ID3D11DeviceChild][ID3D11BlendState]
//
// but a buffer will have
//
// [IUnknown][ID3D11DeviceChild][ID3D11Resource][ID3D11Buffer]
//
// If we have WrappedDeviceChild11 having a virtual descructor then because it's templated
// it will insert it in a variable location after all the I* functions. Even if we avoided
// that with another base class we'd then need two vtable pointers or we'd need to know the
// type to custom offset into the vtable (i.e. do the proper type cast to get the compiler
// to do that).
//
// Instead we hijack ID3D11DeviceChild's SetPrivateData with a custom GUID to get the object
// to delete itself.
wrapped->SetPrivateData(RENDERDOC_DeleteSelf, 0, NULL);
}
}
objs.clear();
// loop again if m_DeadObjects has had some things added - e.g. if we destroyed a view and that
// caused a texture to be added to the dead objects list. Technically this isn't needed, but to
// keep behaviour consistent with the D3D runtime in testing we do this. It should only require
// at most three passes since we only have two layers of dependency (context free'd destroys a
// view, view free'd destroys a resource, resource free'd).
pass++;
if(pass > 3)
break;
} while(!m_DeadObjects.empty());
}
void WrappedID3D11Device::SetMarker(uint32_t col, const wchar_t *name)
{
if(m_pCurrentWrappedDevice == NULL)
@@ -2314,6 +2389,8 @@ HRESULT WrappedID3D11Device::Present(IDXGISwapper *swapper, UINT SyncInterval, U
if(IsBackgroundCapturing(m_State))
RenderDoc::Inst().Tick();
FlushPendingDead();
m_pImmediateContext->EndFrame();
m_FrameCounter++; // first present becomes frame #1, this function is at the end of the frame
@@ -2406,13 +2483,14 @@ void WrappedID3D11Device::CachedObjectsGarbageCollect()
{
ID3D11DeviceChild *o = *it;
o->AddRef();
if(o->Release() == 1)
// if there are no external references and only one internal reference then this object should
// have been deleted because that internal reference is the one we added at creation to keep the
// object alive.
if(GetExtRefCount(o) == 0 && GetIntRefCount(o) == 1)
{
auto eraseit = it;
++it;
o->Release();
InternalRelease();
IntRelease(o);
m_CachedStateObjects.erase(eraseit);
}
else
@@ -2420,6 +2498,8 @@ void WrappedID3D11Device::CachedObjectsGarbageCollect()
++it;
}
}
FlushPendingDead();
}
void WrappedID3D11Device::AddDeferredContext(WrappedID3D11DeviceContext *defctx)
@@ -2590,29 +2670,6 @@ void WrappedID3D11Device::SetResourceName(ID3D11DeviceChild *pResource, const ch
}
}
void WrappedID3D11Device::ReleaseResource(ID3D11DeviceChild *res)
{
ResourceId idx = GetIDForResource(res);
// wrapped resources get released all the time, we don't want to
// try and slerp in a resource release. Just the explicit ones
if(!IsCaptureMode(m_State))
{
if(GetResourceManager()->HasLiveResource(idx))
GetResourceManager()->EraseLiveResource(idx);
return;
}
SCOPED_LOCK(m_D3DLock);
if(WrappedID3D11DeviceContext::IsAlloc(res))
RemoveDeferredContext((WrappedID3D11DeviceContext *)res);
D3D11ResourceRecord *record = GetResourceManager()->GetResourceRecord(idx);
if(record)
record->Delete(GetResourceManager());
}
WrappedID3D11DeviceContext *WrappedID3D11Device::GetDeferredContext(size_t idx)
{
auto it = m_DeferredContexts.begin();
+170 -20
View File
@@ -154,7 +154,7 @@ struct DummyID3D11InfoQueue : public ID3D11InfoQueue
DummyID3D11InfoQueue() : m_pDevice(NULL) {}
//////////////////////////////
// implement IUnknown
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) { return E_NOINTERFACE; }
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
@@ -242,6 +242,152 @@ struct DummyID3D11InfoQueue : public ID3D11InfoQueue
virtual BOOL STDMETHODCALLTYPE GetMuteDebugOutput() { return TRUE; }
};
// This one actually works and requires a special GUID to access. We only wrap it
// so we can keep the refcounting on our own device
struct WrappedID3D11InfoQueue : public ID3D11InfoQueue
{
WrappedID3D11Device *m_pDevice;
ID3D11InfoQueue *m_pReal;
WrappedID3D11InfoQueue() : m_pDevice(NULL) {}
//////////////////////////////
// implement IUnknown
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
//////////////////////////////
// implement ID3D11InfoQueue
virtual HRESULT STDMETHODCALLTYPE SetMessageCountLimit(UINT64 MessageCountLimit)
{
return m_pReal->SetMessageCountLimit(MessageCountLimit);
}
virtual void STDMETHODCALLTYPE ClearStoredMessages() { return m_pReal->ClearStoredMessages(); }
virtual HRESULT STDMETHODCALLTYPE GetMessage(UINT64 MessageIndex, D3D11_MESSAGE *pMessage,
SIZE_T *pMessageByteLength)
{
return m_pReal->GetMessage(MessageIndex, pMessage, pMessageByteLength);
}
virtual UINT64 STDMETHODCALLTYPE GetNumMessagesAllowedByStorageFilter()
{
return m_pReal->GetNumMessagesAllowedByStorageFilter();
}
virtual UINT64 STDMETHODCALLTYPE GetNumMessagesDeniedByStorageFilter()
{
return m_pReal->GetNumMessagesDeniedByStorageFilter();
}
virtual UINT64 STDMETHODCALLTYPE GetNumStoredMessages()
{
return m_pReal->GetNumStoredMessages();
}
virtual UINT64 STDMETHODCALLTYPE GetNumStoredMessagesAllowedByRetrievalFilter()
{
return m_pReal->GetNumStoredMessagesAllowedByRetrievalFilter();
}
virtual UINT64 STDMETHODCALLTYPE GetNumMessagesDiscardedByMessageCountLimit()
{
return m_pReal->GetNumMessagesDiscardedByMessageCountLimit();
}
virtual UINT64 STDMETHODCALLTYPE GetMessageCountLimit()
{
return m_pReal->GetMessageCountLimit();
}
virtual HRESULT STDMETHODCALLTYPE AddStorageFilterEntries(D3D11_INFO_QUEUE_FILTER *pFilter)
{
return m_pReal->AddStorageFilterEntries(pFilter);
}
virtual HRESULT STDMETHODCALLTYPE GetStorageFilter(D3D11_INFO_QUEUE_FILTER *pFilter,
SIZE_T *pFilterByteLength)
{
return m_pReal->GetStorageFilter(pFilter, pFilterByteLength);
}
virtual void STDMETHODCALLTYPE ClearStorageFilter() { return m_pReal->ClearStorageFilter(); }
virtual HRESULT STDMETHODCALLTYPE PushEmptyStorageFilter()
{
return m_pReal->PushEmptyStorageFilter();
}
virtual HRESULT STDMETHODCALLTYPE PushCopyOfStorageFilter()
{
return m_pReal->PushCopyOfStorageFilter();
}
virtual HRESULT STDMETHODCALLTYPE PushStorageFilter(D3D11_INFO_QUEUE_FILTER *pFilter)
{
return m_pReal->PushStorageFilter(pFilter);
}
virtual void STDMETHODCALLTYPE PopStorageFilter() { return m_pReal->PopStorageFilter(); }
virtual UINT STDMETHODCALLTYPE GetStorageFilterStackSize()
{
return m_pReal->GetStorageFilterStackSize();
}
virtual HRESULT STDMETHODCALLTYPE AddRetrievalFilterEntries(D3D11_INFO_QUEUE_FILTER *pFilter)
{
return m_pReal->AddRetrievalFilterEntries(pFilter);
}
virtual HRESULT STDMETHODCALLTYPE GetRetrievalFilter(D3D11_INFO_QUEUE_FILTER *pFilter,
SIZE_T *pFilterByteLength)
{
return m_pReal->GetRetrievalFilter(pFilter, pFilterByteLength);
}
virtual void STDMETHODCALLTYPE ClearRetrievalFilter() { return m_pReal->ClearRetrievalFilter(); }
virtual HRESULT STDMETHODCALLTYPE PushEmptyRetrievalFilter()
{
return m_pReal->PushEmptyRetrievalFilter();
}
virtual HRESULT STDMETHODCALLTYPE PushCopyOfRetrievalFilter()
{
return m_pReal->PushCopyOfRetrievalFilter();
}
virtual HRESULT STDMETHODCALLTYPE PushRetrievalFilter(D3D11_INFO_QUEUE_FILTER *pFilter)
{
return m_pReal->PushRetrievalFilter(pFilter);
}
virtual void STDMETHODCALLTYPE PopRetrievalFilter() { return m_pReal->PopRetrievalFilter(); }
virtual UINT STDMETHODCALLTYPE GetRetrievalFilterStackSize()
{
return m_pReal->GetRetrievalFilterStackSize();
}
virtual HRESULT STDMETHODCALLTYPE AddMessage(D3D11_MESSAGE_CATEGORY Category,
D3D11_MESSAGE_SEVERITY Severity, D3D11_MESSAGE_ID ID,
LPCSTR pDescription)
{
return m_pReal->AddMessage(Category, Severity, ID, pDescription);
}
virtual HRESULT STDMETHODCALLTYPE AddApplicationMessage(D3D11_MESSAGE_SEVERITY Severity,
LPCSTR pDescription)
{
return m_pReal->AddApplicationMessage(Severity, pDescription);
}
virtual HRESULT STDMETHODCALLTYPE SetBreakOnCategory(D3D11_MESSAGE_CATEGORY Category, BOOL bEnable)
{
return m_pReal->SetBreakOnCategory(Category, bEnable);
}
virtual HRESULT STDMETHODCALLTYPE SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY Severity, BOOL bEnable)
{
return m_pReal->SetBreakOnSeverity(Severity, bEnable);
}
virtual HRESULT STDMETHODCALLTYPE SetBreakOnID(D3D11_MESSAGE_ID ID, BOOL bEnable)
{
return m_pReal->SetBreakOnID(ID, bEnable);
}
virtual BOOL STDMETHODCALLTYPE GetBreakOnCategory(D3D11_MESSAGE_CATEGORY Category)
{
return m_pReal->GetBreakOnCategory(Category);
}
virtual BOOL STDMETHODCALLTYPE GetBreakOnSeverity(D3D11_MESSAGE_SEVERITY Severity)
{
return m_pReal->GetBreakOnSeverity(Severity);
}
virtual BOOL STDMETHODCALLTYPE GetBreakOnID(D3D11_MESSAGE_ID ID)
{
return m_pReal->GetBreakOnID(ID);
}
virtual void STDMETHODCALLTYPE SetMuteDebugOutput(BOOL bMute)
{
return m_pReal->SetMuteDebugOutput(bMute);
}
virtual BOOL STDMETHODCALLTYPE GetMuteDebugOutput() { return m_pReal->GetMuteDebugOutput(); }
};
// give every impression of working but do nothing.
// Same idea as DummyID3D11InfoQueue above, a dummy interface so that users
// expecting a ID3D11Debug don't get confused if we have turned off the debug
@@ -295,6 +441,7 @@ private:
WrappedD3D11Multithread m_WrappedMultithread;
DummyID3D11InfoQueue m_DummyInfoQueue;
WrappedID3D11InfoQueue m_WrappedInfoQueue;
DummyID3D11Debug m_DummyDebug;
WrappedID3D11Debug m_WrappedDebug;
WrappedID3D11VideoDevice2 m_WrappedVideo;
@@ -302,10 +449,12 @@ private:
ID3DUserDefinedAnnotation *m_RealAnnotations;
int m_ReplayEventCount;
unsigned int m_InternalRefcount;
RefCounter m_RefCounter;
RefCounter m_SoftRefCounter;
bool m_Alive;
// the device only has one refcount, all device childs take precisely one when they have external
// references (if they lose their external references they release it) and when it reaches 0 the
// device is deleted.
int32_t m_RefCount;
rdcarray<ID3D11DeviceChild *> m_DeadObjects;
int32_t m_ChunkAtomic;
@@ -430,8 +579,6 @@ public:
void RemoveDeferredContext(WrappedID3D11DeviceContext *defctx);
WrappedID3D11DeviceContext *GetDeferredContext(size_t idx);
void ReleaseResource(ID3D11DeviceChild *pResource);
ResourceId GetResourceID() { return m_ResourceID; }
const DrawcallDescription *GetDrawcall(uint32_t eventId);
ResourceDescription &GetResourceDesc(ResourceId id);
@@ -557,15 +704,8 @@ public:
virtual IDXGIResource *WrapExternalDXGIResource(IDXGIResource *res);
ResourceId GetBackbufferResourceID() { return m_BBID; }
void InternalRef() { InterlockedIncrement(&m_InternalRefcount); }
void InternalRelease() { InterlockedDecrement(&m_InternalRefcount); }
void SoftRef() { m_SoftRefCounter.AddRef(); }
void SoftRelease()
{
m_SoftRefCounter.Release();
CheckForDeath();
}
void CheckForDeath();
void ReportDeath(ID3D11DeviceChild *obj);
void FlushPendingDead();
////////////////////////////////////////////////////////////////
// Functions for D3D9 hooks to call into (D3DPERF api)
@@ -576,12 +716,22 @@ public:
//////////////////////////////
// implement IUnknown
ULONG STDMETHODCALLTYPE AddRef() { return m_RefCounter.AddRef(); }
ULONG STDMETHODCALLTYPE AddRef()
{
Atomic::Inc32(&m_RefCount);
return (ULONG)m_RefCount;
}
ULONG STDMETHODCALLTYPE Release()
{
unsigned int ret = m_RefCounter.Release();
CheckForDeath();
return ret;
Atomic::Dec32(&m_RefCount);
ASSERT_REFCOUNT(m_RefCount);
if(m_RefCount == 0)
{
FlushPendingDead();
delete this;
return 0;
}
return (ULONG)m_RefCount;
}
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
@@ -147,8 +147,7 @@ HRESULT WrappedID3D11Device::CreateBlendState1(const D3D11_BLEND_DESC1 *pBlendSt
{
RDCASSERT(m_CachedStateObjects.find(wrapped) == m_CachedStateObjects.end());
wrapped->AddRef();
InternalRef();
IntAddRef(wrapped);
m_CachedStateObjects.insert(wrapped);
}
@@ -256,8 +255,7 @@ HRESULT WrappedID3D11Device::CreateRasterizerState1(const D3D11_RASTERIZER_DESC1
{
RDCASSERT(m_CachedStateObjects.find(wrapped) == m_CachedStateObjects.end());
wrapped->AddRef();
InternalRef();
IntAddRef(wrapped);
m_CachedStateObjects.insert(wrapped);
}
@@ -819,8 +819,7 @@ HRESULT WrappedID3D11Device::CreateRasterizerState2(const D3D11_RASTERIZER_DESC2
{
RDCASSERT(m_CachedStateObjects.find(wrapped) == m_CachedStateObjects.end());
wrapped->AddRef();
InternalRef();
IntAddRef(wrapped);
m_CachedStateObjects.insert(wrapped);
}
+34 -8
View File
@@ -210,6 +210,7 @@ HRESULT WrappedID3D11Device::CreateBuffer(const D3D11_BUFFER_DESC *pDesc,
{
SCOPED_LOCK(m_D3DLock);
FlushPendingDead();
wrapped = new WrappedID3D11Buffer(real, pDesc->ByteWidth, this);
if(IsCaptureMode(m_State))
@@ -463,6 +464,7 @@ HRESULT WrappedID3D11Device::CreateTexture1D(const D3D11_TEXTURE1D_DESC *pDesc,
{
SCOPED_LOCK(m_D3DLock);
FlushPendingDead();
wrapped = new WrappedID3D11Texture1D(real, this);
if(IsCaptureMode(m_State))
@@ -598,6 +600,7 @@ HRESULT WrappedID3D11Device::CreateTexture2D(const D3D11_TEXTURE2D_DESC *pDesc,
{
SCOPED_LOCK(m_D3DLock);
FlushPendingDead();
wrapped = new WrappedID3D11Texture2D1(real, this);
if(IsCaptureMode(m_State))
@@ -732,6 +735,7 @@ HRESULT WrappedID3D11Device::CreateTexture3D(const D3D11_TEXTURE3D_DESC *pDesc,
{
SCOPED_LOCK(m_D3DLock);
FlushPendingDead();
wrapped = new WrappedID3D11Texture3D1(real, this);
if(IsCaptureMode(m_State))
@@ -860,6 +864,7 @@ HRESULT WrappedID3D11Device::CreateShaderResourceView(ID3D11Resource *pResource,
{
SCOPED_LOCK(m_D3DLock);
FlushPendingDead();
wrapped = new WrappedID3D11ShaderResourceView1(real, pResource, this);
Chunk *chunk = NULL;
@@ -1006,6 +1011,7 @@ HRESULT WrappedID3D11Device::CreateUnorderedAccessView(ID3D11Resource *pResource
{
SCOPED_LOCK(m_D3DLock);
FlushPendingDead();
wrapped = new WrappedID3D11UnorderedAccessView1(real, pResource, this);
Chunk *chunk = NULL;
@@ -1148,6 +1154,7 @@ HRESULT WrappedID3D11Device::CreateRenderTargetView(ID3D11Resource *pResource,
{
SCOPED_LOCK(m_D3DLock);
FlushPendingDead();
wrapped = new WrappedID3D11RenderTargetView1(real, pResource, this);
Chunk *chunk = NULL;
@@ -1252,6 +1259,7 @@ HRESULT WrappedID3D11Device::CreateDepthStencilView(ID3D11Resource *pResource,
{
SCOPED_LOCK(m_D3DLock);
FlushPendingDead();
wrapped = new WrappedID3D11DepthStencilView(real, pResource, this);
Chunk *chunk = NULL;
@@ -1373,6 +1381,7 @@ HRESULT WrappedID3D11Device::CreateInputLayout(const D3D11_INPUT_ELEMENT_DESC *p
{
SCOPED_LOCK(m_D3DLock);
FlushPendingDead();
wrapped = new WrappedID3D11InputLayout(real, this);
if(IsCaptureMode(m_State))
@@ -1461,6 +1470,7 @@ HRESULT WrappedID3D11Device::CreateVertexShader(const void *pShaderBytecode, SIZ
{
SCOPED_LOCK(m_D3DLock);
FlushPendingDead();
wrapped = new WrappedID3D11Shader<ID3D11VertexShader>(
real, ResourceId(), (const byte *)pShaderBytecode, BytecodeLength, this);
@@ -1557,6 +1567,7 @@ HRESULT WrappedID3D11Device::CreateGeometryShader(const void *pShaderBytecode, S
{
SCOPED_LOCK(m_D3DLock);
FlushPendingDead();
wrapped = new WrappedID3D11Shader<ID3D11GeometryShader>(
real, ResourceId(), (const byte *)pShaderBytecode, BytecodeLength, this);
@@ -1663,6 +1674,7 @@ HRESULT WrappedID3D11Device::CreateGeometryShaderWithStreamOutput(
{
SCOPED_LOCK(m_D3DLock);
FlushPendingDead();
wrapped = new WrappedID3D11Shader<ID3D11GeometryShader>(
real, ResourceId(), (const byte *)pShaderBytecode, BytecodeLength, this);
@@ -1760,6 +1772,7 @@ HRESULT WrappedID3D11Device::CreatePixelShader(const void *pShaderBytecode, SIZE
{
SCOPED_LOCK(m_D3DLock);
FlushPendingDead();
wrapped = new WrappedID3D11Shader<ID3D11PixelShader>(
real, ResourceId(), (const byte *)pShaderBytecode, BytecodeLength, this);
@@ -1853,6 +1866,7 @@ HRESULT WrappedID3D11Device::CreateHullShader(const void *pShaderBytecode, SIZE_
{
SCOPED_LOCK(m_D3DLock);
FlushPendingDead();
wrapped = new WrappedID3D11Shader<ID3D11HullShader>(
real, ResourceId(), (const byte *)pShaderBytecode, BytecodeLength, this);
@@ -1948,6 +1962,7 @@ HRESULT WrappedID3D11Device::CreateDomainShader(const void *pShaderBytecode, SIZ
{
SCOPED_LOCK(m_D3DLock);
FlushPendingDead();
wrapped = new WrappedID3D11Shader<ID3D11DomainShader>(
real, ResourceId(), (const byte *)pShaderBytecode, BytecodeLength, this);
@@ -2044,6 +2059,7 @@ HRESULT WrappedID3D11Device::CreateComputeShader(const void *pShaderBytecode, SI
{
SCOPED_LOCK(m_D3DLock);
FlushPendingDead();
wrapped = new WrappedID3D11Shader<ID3D11ComputeShader>(
real, ResourceId(), (const byte *)pShaderBytecode, BytecodeLength, this);
@@ -2117,6 +2133,7 @@ bool WrappedID3D11Device::Serialise_CreateClassInstance(SerialiserType &ser, LPC
}
else
{
FlushPendingDead();
wrapped = new WrappedID3D11ClassInstance(real, pClassLinkage, this);
GetResourceManager()->AddLiveResource(pInstance, wrapped);
@@ -2139,6 +2156,7 @@ ID3D11ClassInstance *WrappedID3D11Device::CreateClassInstance(
{
SCOPED_LOCK(m_D3DLock);
FlushPendingDead();
wrapped = new WrappedID3D11ClassInstance(*ppInstance, pClassLinkage, this);
{
@@ -2188,6 +2206,7 @@ bool WrappedID3D11Device::Serialise_GetClassInstance(SerialiserType &ser, LPCSTR
}
else
{
FlushPendingDead();
wrapped = new WrappedID3D11ClassInstance(real, pClassLinkage, this);
GetResourceManager()->AddLiveResource(pInstance, wrapped);
@@ -2211,6 +2230,7 @@ ID3D11ClassInstance *WrappedID3D11Device::GetClassInstance(LPCSTR pClassInstance
{
SCOPED_LOCK(m_D3DLock);
FlushPendingDead();
wrapped = new WrappedID3D11ClassInstance(*ppInstance, pClassLinkage, this);
{
@@ -2275,6 +2295,7 @@ HRESULT WrappedID3D11Device::CreateClassLinkage(ID3D11ClassLinkage **ppLinkage)
{
SCOPED_LOCK(m_D3DLock);
FlushPendingDead();
wrapped = new WrappedID3D11ClassLinkage(real, this);
if(IsCaptureMode(m_State))
@@ -2361,14 +2382,16 @@ HRESULT WrappedID3D11Device::CreateBlendState(const D3D11_BLEND_DESC *pBlendStat
return ret;
}
FlushPendingDead();
ID3D11BlendState *wrapped = new WrappedID3D11BlendState1(real, this);
CachedObjectsGarbageCollect();
{
RDCASSERT(m_CachedStateObjects.find(wrapped) == m_CachedStateObjects.end());
wrapped->AddRef();
InternalRef();
// add an internal reference too just so if the application creates and destroys state objects
// at high frequency we keep it around.
IntAddRef(wrapped);
m_CachedStateObjects.insert(wrapped);
}
@@ -2465,14 +2488,14 @@ HRESULT WrappedID3D11Device::CreateDepthStencilState(const D3D11_DEPTH_STENCIL_D
return ret;
}
FlushPendingDead();
ID3D11DepthStencilState *wrapped = new WrappedID3D11DepthStencilState(real, this);
CachedObjectsGarbageCollect();
{
RDCASSERT(m_CachedStateObjects.find(wrapped) == m_CachedStateObjects.end());
wrapped->AddRef();
InternalRef();
IntAddRef(wrapped);
m_CachedStateObjects.insert(wrapped);
}
@@ -2569,14 +2592,14 @@ HRESULT WrappedID3D11Device::CreateRasterizerState(const D3D11_RASTERIZER_DESC *
return ret;
}
FlushPendingDead();
ID3D11RasterizerState *wrapped = new WrappedID3D11RasterizerState2(real, this);
CachedObjectsGarbageCollect();
{
RDCASSERT(m_CachedStateObjects.find(wrapped) == m_CachedStateObjects.end());
wrapped->AddRef();
InternalRef();
IntAddRef(wrapped);
m_CachedStateObjects.insert(wrapped);
}
@@ -2673,14 +2696,14 @@ HRESULT WrappedID3D11Device::CreateSamplerState(const D3D11_SAMPLER_DESC *pSampl
return ret;
}
FlushPendingDead();
ID3D11SamplerState *wrapped = new WrappedID3D11SamplerState(real, this);
CachedObjectsGarbageCollect();
{
RDCASSERT(m_CachedStateObjects.find(wrapped) == m_CachedStateObjects.end());
wrapped->AddRef();
InternalRef();
IntAddRef(wrapped);
m_CachedStateObjects.insert(wrapped);
}
@@ -2756,6 +2779,7 @@ HRESULT WrappedID3D11Device::CreateQuery(const D3D11_QUERY_DESC *pQueryDesc, ID3
{
SCOPED_LOCK(m_D3DLock);
FlushPendingDead();
wrapped = new WrappedID3D11Query1(real, this);
if(IsCaptureMode(m_State))
@@ -2842,6 +2866,7 @@ HRESULT WrappedID3D11Device::CreatePredicate(const D3D11_QUERY_DESC *pPredicateD
{
SCOPED_LOCK(m_D3DLock);
FlushPendingDead();
wrapped = new WrappedID3D11Predicate(real, this);
if(IsCaptureMode(m_State))
@@ -2923,6 +2948,7 @@ HRESULT WrappedID3D11Device::CreateCounter(const D3D11_COUNTER_DESC *pCounterDes
{
SCOPED_LOCK(m_D3DLock);
FlushPendingDead();
wrapped = new WrappedID3D11Counter(real, this);
if(IsCaptureMode(m_State))
+3 -9
View File
@@ -225,9 +225,8 @@ private:
dummyUsed = true;
}
HRESULT ret =
real(pAdapter, DriverType, Software, Flags, pFeatureLevels, FeatureLevels, SDKVersion,
pUsedSwapDesc, ppSwapChain, ppDevice, pFeatureLevel, ppImmediateContext);
HRESULT ret = real(pAdapter, DriverType, Software, Flags, pFeatureLevels, FeatureLevels,
SDKVersion, pUsedSwapDesc, ppSwapChain, ppDevice, pFeatureLevel, NULL);
SAFE_RELEASE(dummydev);
if(dummyUsed)
@@ -263,12 +262,7 @@ private:
*ppDevice = wrap;
if(ppImmediateContext)
{
if(*ppImmediateContext)
(*ppImmediateContext)->Release();
wrap->GetImmediateContext(ppImmediateContext);
}
wrap->GetImmediateContext(ppImmediateContext);
if(ppSwapChain && *ppSwapChain)
*ppSwapChain = new WrappedIDXGISwapChain4(
+43 -115
View File
@@ -100,54 +100,54 @@ D3D11RenderState::~D3D11RenderState()
void D3D11RenderState::ReleaseRefs()
{
ReleaseRef(IA.IndexBuffer);
ReleaseRef(IA.Layout);
IntRelease(IA.IndexBuffer);
IntRelease(IA.Layout);
for(UINT i = 0; i < D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; i++)
ReleaseRef(IA.VBs[i]);
IntRelease(IA.VBs[i]);
Shader *stages[] = {&VS, &HS, &DS, &GS, &PS, &CS};
for(int s = 0; s < 6; s++)
{
Shader *sh = stages[s];
ReleaseRef(sh->Object);
IntRelease(sh->Object);
for(UINT i = 0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; i++)
ReleaseRef(sh->ConstantBuffers[i]);
IntRelease(sh->ConstantBuffers[i]);
for(UINT i = 0; i < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; i++)
ReleaseRef(sh->Samplers[i]);
IntRelease(sh->Samplers[i]);
for(UINT i = 0; i < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; i++)
ReleaseRef(sh->SRVs[i]);
IntRelease(sh->SRVs[i]);
for(UINT i = 0; i < D3D11_SHADER_MAX_INTERFACES; i++)
ReleaseRef(sh->Instances[i]);
IntRelease(sh->Instances[i]);
sh++;
}
for(UINT i = 0; i < D3D11_1_UAV_SLOT_COUNT; i++)
ReleaseRef(CSUAVs[i]);
IntRelease(CSUAVs[i]);
for(UINT i = 0; i < D3D11_SO_BUFFER_SLOT_COUNT; i++)
ReleaseRef(SO.Buffers[i]);
IntRelease(SO.Buffers[i]);
ReleaseRef(RS.State);
IntRelease(RS.State);
ReleaseRef(OM.BlendState);
ReleaseRef(OM.DepthStencilState);
IntRelease(OM.BlendState);
IntRelease(OM.DepthStencilState);
for(UINT i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
ReleaseRef(OM.RenderTargets[i]);
IntRelease(OM.RenderTargets[i]);
for(UINT i = 0; i < D3D11_1_UAV_SLOT_COUNT; i++)
ReleaseRef(OM.UAVs[i]);
IntRelease(OM.UAVs[i]);
ReleaseRef(OM.DepthView);
IntRelease(OM.DepthView);
ReleaseRef(Predicate);
IntRelease(Predicate);
RDCEraseEl(IA);
RDCEraseEl(VS);
@@ -276,54 +276,54 @@ void D3D11RenderState::MarkReferenced(WrappedID3D11DeviceContext *ctx, bool init
void D3D11RenderState::AddRefs()
{
TakeRef(IA.IndexBuffer);
TakeRef(IA.Layout);
IntAddRef(IA.IndexBuffer);
IntAddRef(IA.Layout);
for(UINT i = 0; i < D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; i++)
TakeRef(IA.VBs[i]);
IntAddRef(IA.VBs[i]);
Shader *stages[] = {&VS, &HS, &DS, &GS, &PS, &CS};
for(int s = 0; s < 6; s++)
{
Shader *sh = stages[s];
TakeRef(sh->Object);
IntAddRef(sh->Object);
for(UINT i = 0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; i++)
TakeRef(sh->ConstantBuffers[i]);
IntAddRef(sh->ConstantBuffers[i]);
for(UINT i = 0; i < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; i++)
TakeRef(sh->Samplers[i]);
IntAddRef(sh->Samplers[i]);
for(UINT i = 0; i < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; i++)
TakeRef(sh->SRVs[i]);
IntAddRef(sh->SRVs[i]);
for(UINT i = 0; i < D3D11_SHADER_MAX_INTERFACES; i++)
TakeRef(sh->Instances[i]);
IntAddRef(sh->Instances[i]);
sh++;
}
for(UINT i = 0; i < D3D11_1_UAV_SLOT_COUNT; i++)
TakeRef(CSUAVs[i]);
IntAddRef(CSUAVs[i]);
for(UINT i = 0; i < D3D11_SO_BUFFER_SLOT_COUNT; i++)
TakeRef(SO.Buffers[i]);
IntAddRef(SO.Buffers[i]);
TakeRef(RS.State);
IntAddRef(RS.State);
TakeRef(OM.BlendState);
TakeRef(OM.DepthStencilState);
IntAddRef(OM.BlendState);
IntAddRef(OM.DepthStencilState);
for(UINT i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
TakeRef(OM.RenderTargets[i]);
IntAddRef(OM.RenderTargets[i]);
for(UINT i = 0; i < D3D11_1_UAV_SLOT_COUNT; i++)
TakeRef(OM.UAVs[i]);
IntAddRef(OM.UAVs[i]);
TakeRef(OM.DepthView);
IntAddRef(OM.DepthView);
TakeRef(Predicate);
IntAddRef(Predicate);
}
D3D11RenderState::D3D11RenderState(WrappedID3D11DeviceContext *context)
@@ -561,78 +561,6 @@ void D3D11RenderState::ApplyState(WrappedID3D11DeviceContext *context) const
context->SetPredication(Predicate, PredicateValue);
}
void D3D11RenderState::TakeRef(ID3D11DeviceChild *p)
{
if(p)
{
p->AddRef();
if(m_ImmediatePipeline)
{
if(WrappedID3D11RenderTargetView1::IsAlloc(p) || WrappedID3D11ShaderResourceView1::IsAlloc(p) ||
WrappedID3D11DepthStencilView::IsAlloc(p) || WrappedID3D11UnorderedAccessView1::IsAlloc(p))
m_pDevice->InternalRef();
m_pDevice->InternalRef();
// we can use any specialisation of device child here, as all that is templated
// is the nested pointer type. Saves having another class in the inheritance
// heirarchy :(
((WrappedDeviceChild11<ID3D11Buffer> *)p)->PipelineAddRef();
}
}
}
void D3D11RenderState::ReleaseRef(ID3D11DeviceChild *p)
{
if(p)
{
p->Release();
if(m_ImmediatePipeline)
{
if(WrappedID3D11RenderTargetView1::IsAlloc(p) || WrappedID3D11ShaderResourceView1::IsAlloc(p) ||
WrappedID3D11DepthStencilView::IsAlloc(p) || WrappedID3D11UnorderedAccessView1::IsAlloc(p))
m_pDevice->InternalRelease();
m_pDevice->InternalRelease();
// see above
((WrappedDeviceChild11<ID3D11Buffer> *)p)->PipelineRelease();
}
}
}
// these are overloads that take a buffer to skip the view IsAlloc checks
void D3D11RenderState::TakeRef(ID3D11Buffer *p)
{
if(p)
{
p->AddRef();
if(m_ImmediatePipeline)
{
m_pDevice->InternalRef();
// see above
((WrappedDeviceChild11<ID3D11Buffer> *)p)->PipelineAddRef();
}
}
}
void D3D11RenderState::ReleaseRef(ID3D11Buffer *p)
{
if(p)
{
p->Release();
if(m_ImmediatePipeline)
{
m_pDevice->InternalRelease();
// see above
((WrappedDeviceChild11<ID3D11Buffer> *)p)->PipelineRelease();
}
}
}
bool D3D11RenderState::IsRangeBoundForWrite(const ResourceRange &range)
{
for(UINT i = 0; i < D3D11_1_UAV_SLOT_COUNT; i++)
@@ -707,7 +635,7 @@ void D3D11RenderState::UnbindRangeForWrite(const ResourceRange &range)
{
if(CSUAVs[i] && range.Intersects(GetResourceRange(CSUAVs[i])))
{
ReleaseRef(CSUAVs[i]);
IntRelease(CSUAVs[i]);
CSUAVs[i] = NULL;
}
}
@@ -716,7 +644,7 @@ void D3D11RenderState::UnbindRangeForWrite(const ResourceRange &range)
{
if(SO.Buffers[i] && range.Intersects(ResourceRange(SO.Buffers[i])))
{
ReleaseRef(SO.Buffers[i]);
IntRelease(SO.Buffers[i]);
SO.Buffers[i] = NULL;
}
}
@@ -725,7 +653,7 @@ void D3D11RenderState::UnbindRangeForWrite(const ResourceRange &range)
{
if(OM.RenderTargets[i] && range.Intersects(GetResourceRange(OM.RenderTargets[i])))
{
ReleaseRef(OM.RenderTargets[i]);
IntRelease(OM.RenderTargets[i]);
OM.RenderTargets[i] = NULL;
}
}
@@ -734,14 +662,14 @@ void D3D11RenderState::UnbindRangeForWrite(const ResourceRange &range)
{
if(OM.UAVs[i] && range.Intersects(GetResourceRange(OM.UAVs[i])))
{
ReleaseRef(OM.UAVs[i]);
IntRelease(OM.UAVs[i]);
OM.UAVs[i] = NULL;
}
}
if(OM.DepthView && range.Intersects(GetResourceRange(OM.DepthView)))
{
ReleaseRef(OM.DepthView);
IntRelease(OM.DepthView);
OM.DepthView = NULL;
}
}
@@ -753,7 +681,7 @@ void D3D11RenderState::UnbindRangeForRead(const ResourceRange &range)
if(IA.VBs[i] && range.Intersects(ResourceRange(IA.VBs[i])))
{
// RDCDEBUG("Resource was bound on IA VB %u", i);
ReleaseRef(IA.VBs[i]);
IntRelease(IA.VBs[i]);
IA.VBs[i] = NULL;
}
}
@@ -761,7 +689,7 @@ void D3D11RenderState::UnbindRangeForRead(const ResourceRange &range)
if(IA.IndexBuffer && range.Intersects(ResourceRange(IA.IndexBuffer)))
{
// RDCDEBUG("Resource was bound on IA IB");
ReleaseRef(IA.IndexBuffer);
IntRelease(IA.IndexBuffer);
IA.IndexBuffer = NULL;
}
@@ -776,7 +704,7 @@ void D3D11RenderState::UnbindRangeForRead(const ResourceRange &range)
if(sh->ConstantBuffers[i] && range.Intersects(ResourceRange(sh->ConstantBuffers[i])))
{
// RDCDEBUG("Resource was bound on %s CB %u", names[s], i);
ReleaseRef(sh->ConstantBuffers[i]);
IntRelease(sh->ConstantBuffers[i]);
sh->ConstantBuffers[i] = NULL;
}
}
@@ -803,7 +731,7 @@ void D3D11RenderState::UnbindRangeForRead(const ResourceRange &range)
else
{
// RDCDEBUG("Unbinding.");
ReleaseRef(sh->SRVs[i]);
IntRelease(sh->SRVs[i]);
sh->SRVs[i] = NULL;
}
}
+15 -32
View File
@@ -94,12 +94,6 @@ struct D3D11RenderState
/////////////////////////////////////////////////////////////////////////
// Utility functions to swap resources around, removing and adding refs
void TakeRef(ID3D11DeviceChild *p);
void ReleaseRef(ID3D11DeviceChild *p);
void TakeRef(ID3D11Buffer *p);
void ReleaseRef(ID3D11Buffer *p);
template <typename T>
void ChangeRefRead(T *&stateItem, T *newItem)
{
@@ -110,7 +104,7 @@ struct D3D11RenderState
// release the old item, which may destroy it but we won't use it again as we know is not the
// same as the new item.
ReleaseRef(stateItem);
IntRelease(stateItem);
// assign the new item, but don't ref it yet
stateItem = newItem;
@@ -123,37 +117,36 @@ struct D3D11RenderState
}
// finally we take the ref on the new item
TakeRef(stateItem);
IntAddRef(stateItem);
}
template <typename T>
void ChangeRefRead(T **stateArray, T *const *newArray, size_t offset, size_t num)
{
// addref the whole array so none of it can be destroyed during processing
for(size_t i = 0; i < num; i++)
if(newArray[i])
newArray[i]->AddRef();
// we don't really care if some objects temporarily hit 0 ext and int refcounts while changing
// hands. Consider the case:
//
// previous: [0] = A [1] = B
// bind: [0] = B [1] = A
//
// after processing slot 0, B has two refs (leftover [1] and updated [0]) and A has no refs. If
// A also has no external references this may look like it can be deleted, but all that will
// happen is the death will be reported to the device. By the time the device actually processes
// it the object will have an intref again.
for(size_t i = 0; i < num; i++)
ChangeRefRead(stateArray[offset + i], newArray[i]);
// release the ref we added above
for(size_t i = 0; i < num; i++)
if(newArray[i])
newArray[i]->Release();
}
template <typename T>
void ChangeRefWrite(T *&stateItem, T *newItem)
{
// don't do anything for redundant changes. This prevents the object from bouncing off refcount
// 0 during the changeover if it's only bound once, has no external refcount.
// don't do anything for redundant changes
if(stateItem == newItem)
return;
// release the old item, which may destroy it but we won't use it again as we know is not the
// same as the new item. We NULL it out so that it doesn't get unbound again below
ReleaseRef(stateItem);
IntRelease(stateItem);
stateItem = NULL;
// if we're not binding NULL, then unbind any other conflicting uses
@@ -166,24 +159,14 @@ struct D3D11RenderState
// now bind the new item and ref it
stateItem = newItem;
TakeRef(stateItem);
IntAddRef(stateItem);
}
template <typename T>
void ChangeRefWrite(T **stateArray, T *const *newArray, size_t offset, size_t num)
{
// addref the whole array so none of it can be destroyed during processing
for(size_t i = 0; i < num; i++)
if(newArray[i])
newArray[i]->AddRef();
for(size_t i = 0; i < num; i++)
ChangeRefWrite(stateArray[offset + i], newArray[i]);
// release the ref we added above
for(size_t i = 0; i < num; i++)
if(newArray[i])
newArray[i]->Release();
}
template <typename T>
+34 -47
View File
@@ -37,6 +37,16 @@ static Vec2f quadPos[] = {
Vec2f(0.0f, 0.0f), Vec2f(1.0f, 0.0f), Vec2f(0.0f, 1.0f), Vec2f(1.0f, 1.0f),
};
// see d3d11_debug.cpp D3D11DebugManager::D3D11DebugManager for why we use this helper like this
static void InternalRef(ID3D11DeviceChild *child)
{
if(child)
{
IntAddRef(child);
child->Release();
}
}
D3D11TextRenderer::D3D11TextRenderer(WrappedID3D11Device *wrapper)
{
if(RenderDoc::Inst().GetCrashHandler())
@@ -68,8 +78,7 @@ D3D11TextRenderer::D3D11TextRenderer(WrappedID3D11Device *wrapper)
if(FAILED(hr))
RDCERR("Failed to create font blendstate HRESULT: %s", ToStr(hr).c_str());
if(BlendState)
m_pDevice->InternalRef();
InternalRef(BlendState);
rm->SetInternalResource(BlendState);
D3D11_SAMPLER_DESC sampDesc;
@@ -87,8 +96,7 @@ D3D11TextRenderer::D3D11TextRenderer(WrappedID3D11Device *wrapper)
if(FAILED(hr))
RDCERR("Failed to create linear sampler state HRESULT: %s", ToStr(hr).c_str());
if(LinearSampler)
m_pDevice->InternalRef();
InternalRef(LinearSampler);
rm->SetInternalResource(LinearSampler);
D3D11_TEXTURE2D_DESC desc;
@@ -145,8 +153,7 @@ D3D11TextRenderer::D3D11TextRenderer(WrappedID3D11Device *wrapper)
if(FAILED(hr))
RDCERR("Failed to create debugTex HRESULT: %s", ToStr(hr).c_str());
if(debugTex)
m_pDevice->InternalRef();
InternalRef(debugTex);
rm->SetInternalResource(debugTex);
delete[] buf;
@@ -156,11 +163,10 @@ D3D11TextRenderer::D3D11TextRenderer(WrappedID3D11Device *wrapper)
if(FAILED(hr))
RDCERR("Failed to create Tex HRESULT: %s", ToStr(hr).c_str());
if(Tex)
m_pDevice->InternalRef();
InternalRef(Tex);
rm->SetInternalResource(Tex);
SAFE_RELEASE(debugTex);
SAFE_INTRELEASE(debugTex);
Vec4f glyphData[2 * (numChars + 1)];
@@ -178,8 +184,7 @@ D3D11TextRenderer::D3D11TextRenderer(WrappedID3D11Device *wrapper)
if(FAILED(hr))
RDCERR("Failed to create font GlyphData HRESULT: %s", ToStr(hr).c_str());
if(GlyphData)
m_pDevice->InternalRef();
InternalRef(GlyphData);
rm->SetInternalResource(GlyphData);
for(int i = 0; i < numChars; i++)
@@ -215,8 +220,7 @@ D3D11TextRenderer::D3D11TextRenderer(WrappedID3D11Device *wrapper)
if(FAILED(hr))
RDCERR("Failed to create font CBuffer HRESULT: %s", ToStr(hr).c_str());
if(CBuffer)
m_pDevice->InternalRef();
InternalRef(CBuffer);
rm->SetInternalResource(CBuffer);
cbufDesc.ByteWidth = (2 + FONT_MAX_CHARS) * sizeof(uint32_t) * 4;
@@ -225,8 +229,7 @@ D3D11TextRenderer::D3D11TextRenderer(WrappedID3D11Device *wrapper)
if(FAILED(hr))
RDCERR("Failed to create font CharBuffer HRESULT: %s", ToStr(hr).c_str());
if(CharBuffer)
m_pDevice->InternalRef();
InternalRef(CharBuffer);
rm->SetInternalResource(CharBuffer);
rdcstr hlsl = GetEmbeddedResource(text_hlsl);
@@ -239,14 +242,12 @@ D3D11TextRenderer::D3D11TextRenderer(WrappedID3D11Device *wrapper)
{
VS = shaderCache->MakeVShader(hlsl.c_str(), "RENDERDOC_TextVS", "vs_4_0");
if(VS)
m_pDevice->InternalRef();
InternalRef(VS);
rm->SetInternalResource(VS);
PS = shaderCache->MakePShader(hlsl.c_str(), "RENDERDOC_TextPS", "ps_4_0");
if(PS)
m_pDevice->InternalRef();
InternalRef(PS);
rm->SetInternalResource(PS);
}
else
@@ -261,18 +262,15 @@ D3D11TextRenderer::D3D11TextRenderer(WrappedID3D11Device *wrapper)
VS = shaderCache->MakeVShader(hlsl.c_str(), "RENDERDOC_Text9VS", "vs_4_0_level_9_0", 1, inputs,
&Layout);
if(VS)
m_pDevice->InternalRef();
InternalRef(VS);
rm->SetInternalResource(VS);
if(Layout)
m_pDevice->InternalRef();
InternalRef(Layout);
rm->SetInternalResource(Layout);
PS = shaderCache->MakePShader(hlsl.c_str(), "RENDERDOC_TextPS", "ps_4_0_level_9_0");
if(PS)
m_pDevice->InternalRef();
InternalRef(PS);
rm->SetInternalResource(PS);
// these buffers are immutable because they're just replacing the fixed shader generation on
@@ -290,8 +288,7 @@ D3D11TextRenderer::D3D11TextRenderer(WrappedID3D11Device *wrapper)
if(FAILED(hr))
RDCERR("Failed to create FL9 text PosBuffer HRESULT: %s", ToStr(hr).c_str());
if(FL9Buffer)
m_pDevice->InternalRef();
InternalRef(FL9Buffer);
rm->SetInternalResource(FL9Buffer);
}
@@ -300,27 +297,17 @@ D3D11TextRenderer::D3D11TextRenderer(WrappedID3D11Device *wrapper)
D3D11TextRenderer::~D3D11TextRenderer()
{
SAFE_RELEASE(Tex);
m_pDevice->InternalRelease();
SAFE_RELEASE(LinearSampler);
m_pDevice->InternalRelease();
SAFE_RELEASE(BlendState);
m_pDevice->InternalRelease();
SAFE_RELEASE(CBuffer);
m_pDevice->InternalRelease();
SAFE_RELEASE(GlyphData);
m_pDevice->InternalRelease();
SAFE_RELEASE(CharBuffer);
m_pDevice->InternalRelease();
SAFE_RELEASE(VS);
m_pDevice->InternalRelease();
SAFE_RELEASE(PS);
m_pDevice->InternalRelease();
SAFE_INTRELEASE(Tex);
SAFE_INTRELEASE(LinearSampler);
SAFE_INTRELEASE(BlendState);
SAFE_INTRELEASE(CBuffer);
SAFE_INTRELEASE(GlyphData);
SAFE_INTRELEASE(CharBuffer);
SAFE_INTRELEASE(VS);
SAFE_INTRELEASE(PS);
SAFE_RELEASE(Layout);
m_pDevice->InternalRelease();
SAFE_RELEASE(FL9Buffer);
m_pDevice->InternalRelease();
SAFE_INTRELEASE(Layout);
SAFE_INTRELEASE(FL9Buffer);
if(RenderDoc::Inst().GetCrashHandler())
RenderDoc::Inst().GetCrashHandler()->UnregisterMemoryRegion(this);
+6 -41
View File
@@ -70,6 +70,12 @@ rdcarray<WrappedID3DDeviceContextState *> WrappedID3DDeviceContextState::m_List;
Threading::CriticalSection WrappedID3DDeviceContextState::m_Lock;
const GUID RENDERDOC_ID3D11ShaderGUID_ShaderDebugMagicValue = RENDERDOC_ShaderDebugMagicValue_struct;
const GUID RENDERDOC_DeleteSelf = {
0x1e4bf855,
0xcc83,
0x4b7a,
{0x91, 0x8a, 0xd6, 0x64, 0x56, 0x7c, 0xdd, 0x40},
};
void WrappedShader::ShaderEntry::BuildReflection()
{
@@ -708,46 +714,6 @@ void GetDXTextureProperties(void *dxObject, ResourceFormat &fmt, uint32_t &width
RDCERR("Getting DX texture properties for unknown/unhandled objects %p", dxObject);
}
HRESULT STDMETHODCALLTYPE RefCounter::QueryInterface(
/* [in] */ REFIID riid,
/* [annotation][iid_is][out] */
__RPC__deref_out void **ppvObject)
{
return RefCountDXGIObject::WrapQueryInterface(m_pReal, riid, ppvObject);
}
unsigned int RefCounter::SoftRef(WrappedID3D11Device *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 RefCounter::SoftRelease(WrappedID3D11Device *device)
{
unsigned int ret = Release();
if(device)
device->SoftRelease();
else
RDCWARN("No device pointer, is a deleted resource being Release()d?");
return ret;
}
void RefCounter::AddDeviceSoftref(WrappedID3D11Device *device)
{
if(device)
device->SoftRef();
}
void RefCounter::ReleaseDeviceSoftref(WrappedID3D11Device *device)
{
if(device)
device->SoftRelease();
}
WrappedID3DDeviceContextState::WrappedID3DDeviceContextState(ID3DDeviceContextState *real,
WrappedID3D11Device *device)
: WrappedDeviceChild11(real, device)
@@ -763,7 +729,6 @@ WrappedID3DDeviceContextState::WrappedID3DDeviceContextState(ID3DDeviceContextSt
WrappedID3DDeviceContextState::~WrappedID3DDeviceContextState()
{
SAFE_DELETE(state);
Shutdown();
{
SCOPED_LOCK(WrappedID3DDeviceContextState::m_Lock);
+150 -118
View File
@@ -74,32 +74,61 @@ bool CanQuery(base *b)
return SUCCEEDED(check) && d != NULL;
}
class TrackedResource
{
public:
TrackedResource() { m_ID = ResourceIDGen::GetNewUniqueID(); }
ResourceId GetResourceID() { return m_ID; }
private:
TrackedResource(const TrackedResource &);
TrackedResource &operator=(const TrackedResource &);
ResourceId m_ID;
};
extern const GUID RENDERDOC_ID3D11ShaderGUID_ShaderDebugMagicValue;
extern const GUID RENDERDOC_DeleteSelf;
template <typename NestedType, typename NestedType1 = NestedType, typename NestedType2 = NestedType1>
class WrappedDeviceChild11 : public RefCounter, public NestedType2, public TrackedResource
class WrappedDeviceChild11 : public NestedType2
{
private:
ResourceId m_ID;
//////////////////////////////////////////////////////////////////////////
// D3D11's refcounting behaviour is incredibly messy, with several cycles possible:
//
// All ID3D11DeviceChild objects can query back the device.
// The device can query its immediate context
// Contexts can query objects currently bound to them
// Views can query out the resource they point to
//
// Adding to this, some games check the refcount on objects expecting it to be a certain value,
// which restricts how we can refcount. E.g. the immediate context can't have a refcount on its
// bound objects that applications can see, or some will break.
//
// By experimentation, all ID3D11DeviceChild objects that have a reference held by the application
// also hold one reference on the device. This means there's surprising behaviour where the device
// refcount can bounce up and down when child objects hit refcount 0 while still being alive
// (which is quite possible - bind a VB and then release it, its refcount is 0 but it's alive and
// will come back to 1 if you query it out again). This reference is externally visible so the
// ID3D11Device has more refcounts than the application "knows" about.
//
// All other references seem invisible to the application - views on the resource, context on
// bound objects, device on the immediate context.
//
// So we clone D3D's internal implementation of having an external ref (user facing) and an
// internal ref. Objects are only deleted when both are zero, and even then we defer destruction
// to avoid needing excessive extra refcounting when temporarily changing bindings.
//
// This also means the device is released if and only if its external ref count hits 0. That means
// that the user has no access to the device or any of its children so the whole cycle can be
// cleaned up
//
// See D3D11RenderState and the D3D11_Refcount_Check test.
int32_t m_ExtRef;
int32_t m_IntRef;
protected:
WrappedID3D11Device *m_pDevice;
NestedType *m_pReal;
unsigned int m_PipelineRefs;
WrappedDeviceChild11(NestedType *real, WrappedID3D11Device *device)
: RefCounter(real), m_pDevice(device), m_pReal(real), m_PipelineRefs(0)
: m_pDevice(device), m_pReal(real), m_ExtRef(1), m_IntRef(0)
{
m_pDevice->SoftRef();
m_ID = ResourceIDGen::GetNewUniqueID();
// start off with a strong reference on the device.
m_pDevice->AddRef();
bool ret = m_pDevice->GetResourceManager()->AddWrapper(this, real);
if(!ret)
@@ -108,20 +137,11 @@ protected:
m_pDevice->GetResourceManager()->AddCurrentResource(GetResourceID(), this);
}
void Shutdown()
{
m_pDevice->GetResourceManager()->RemoveWrapper(m_pReal);
m_pDevice->GetResourceManager()->ReleaseCurrentResource(GetResourceID());
m_pDevice->ReleaseResource((NestedType *)this);
SAFE_RELEASE(m_pReal);
m_pDevice = NULL;
}
virtual ~WrappedDeviceChild11()
{
// should have already called shutdown (needs to be called from child class to ensure
// vtables are still in place when we call ReleaseResource)
RDCASSERT(m_pDevice == NULL && m_pReal == NULL);
SAFE_RELEASE(m_pReal);
// we removed the reference to the device before releasing ourselves, so just NULL it out.
m_pDevice = NULL;
}
public:
@@ -129,16 +149,55 @@ public:
typedef NestedType1 InnerType1;
typedef NestedType2 InnerType2;
ResourceId GetResourceID() { return m_ID; }
NestedType *GetReal() { return m_pReal; }
ULONG STDMETHODCALLTYPE AddRef() { return RefCounter::SoftRef(m_pDevice) - m_PipelineRefs; }
// internal addref/release
void IntAddRef() { Atomic::Inc32(&m_IntRef); }
void IntRelease()
{
Atomic::Dec32(&m_IntRef);
ASSERT_REFCOUNT(m_IntRef);
// due to deferred destruction, report our death but don't immediately delete ourselves. If
// we're still dead when the device reaps the list of deaths, we'll be deleted.
if(m_IntRef + m_ExtRef == 0)
m_pDevice->ReportDeath(this);
}
int32_t GetExtRefCount() { return m_ExtRef; }
int32_t GetIntRefCount() { return m_IntRef; }
//////////////////////////////
// implement IUnknown
ULONG STDMETHODCALLTYPE AddRef()
{
// if we're about to create a new external reference on this object, add back our reference on
// the device
if(m_ExtRef == 0)
m_pDevice->AddRef();
Atomic::Inc32(&m_ExtRef);
return (ULONG)m_ExtRef;
}
ULONG STDMETHODCALLTYPE Release()
{
unsigned int piperefs = m_PipelineRefs;
return RefCounter::SoftRelease(m_pDevice) - piperefs;
}
Atomic::Dec32(&m_ExtRef);
ASSERT_REFCOUNT(m_ExtRef);
void PipelineAddRef() { InterlockedIncrement(&m_PipelineRefs); }
void PipelineRelease() { InterlockedDecrement(&m_PipelineRefs); }
WrappedID3D11Device *dev = m_pDevice;
int32_t intRef = m_IntRef;
int32_t extRef = m_ExtRef;
// report our own death first, so that if we're about to release the last external reference on
// the device below that we are ready to be cleaned up.
if(intRef + extRef == 0)
dev->ReportDeath(this);
// if we just released the last external reference on this object, release our reference on the
// device.
if(extRef == 0)
dev->Release();
return (ULONG)extRef;
}
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject)
{
if(riid == __uuidof(IUnknown))
@@ -260,7 +319,7 @@ public:
return S_OK;
}
return RefCounter::QueryInterface(riid, ppvObject);
return RefCountDXGIObject::WrapQueryInterface(m_pReal, riid, ppvObject);
}
//////////////////////////////
@@ -299,6 +358,12 @@ public:
if(guid == RENDERDOC_ID3D11ShaderGUID_ShaderDebugMagicValue)
return m_pDevice->SetShaderDebugPath(this, (const char *)pData);
if(guid == RENDERDOC_DeleteSelf)
{
delete this;
return S_OK;
}
if(guid == WKPDID_D3DDebugObjectName)
{
const char *pStrData = (const char *)pData;
@@ -333,66 +398,52 @@ public:
}
};
inline void IntAddRef(ID3D11DeviceChild *child)
{
// assume it's wrapped, do a default cast with template parameters (the exact type doesn't matter)
if(child)
((WrappedDeviceChild11<ID3D11DeviceChild> *)child)->IntAddRef();
}
inline void IntRelease(ID3D11DeviceChild *child)
{
if(child)
((WrappedDeviceChild11<ID3D11DeviceChild> *)child)->IntRelease();
}
inline int32_t GetIntRefCount(ID3D11DeviceChild *child)
{
if(child)
return ((WrappedDeviceChild11<ID3D11DeviceChild> *)child)->GetIntRefCount();
return -1;
}
inline int32_t GetExtRefCount(ID3D11DeviceChild *child)
{
if(child)
return ((WrappedDeviceChild11<ID3D11DeviceChild> *)child)->GetExtRefCount();
return -1;
}
template <typename NestedType, typename DescType, typename NestedType1 = NestedType>
class WrappedResource11 : public WrappedDeviceChild11<NestedType, NestedType1>
{
private:
unsigned int m_ViewRefcount; // refcount from views (invisible to the end-user)
protected:
#if ENABLED(RDOC_DEVEL)
DescType m_Desc;
#endif
WrappedResource11(NestedType *real, WrappedID3D11Device *device)
: WrappedDeviceChild11(real, device), m_ViewRefcount(0)
: WrappedDeviceChild11(real, device)
{
#if ENABLED(RDOC_DEVEL)
real->GetDesc(&m_Desc);
#endif
// we'll handle deleting on release, so we can check against m_ViewRefcount
RefCounter::SetSelfDeleting(false);
}
virtual ~WrappedResource11() {}
public:
void ViewAddRef()
{
InterlockedIncrement(&m_ViewRefcount);
RefCounter::AddDeviceSoftref(m_pDevice);
}
void ViewRelease()
{
InterlockedDecrement(&m_ViewRefcount);
unsigned int extRefCount = RefCounter::GetRefCount();
WrappedID3D11Device *dev = m_pDevice;
if(extRefCount == 0 && m_ViewRefcount == 0)
delete this;
RefCounter::ReleaseDeviceSoftref(dev);
}
ULONG STDMETHODCALLTYPE AddRef() { return RefCounter::SoftRef(m_pDevice) - m_PipelineRefs; }
ULONG STDMETHODCALLTYPE Release()
{
unsigned int extRefCount = RefCounter::Release();
unsigned int pipeRefs = m_PipelineRefs;
WrappedID3D11Device *dev = m_pDevice;
if(extRefCount == 0 && m_ViewRefcount == 0)
delete this;
RefCounter::ReleaseDeviceSoftref(dev);
return extRefCount - pipeRefs;
}
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject)
{
if(riid == __uuidof(ID3D11Resource))
@@ -459,8 +510,6 @@ public:
{
if(RenderDoc::Inst().IsReplayApp())
{
SCOPED_LOCK(m_pDevice->D3DLock());
RDCASSERT(m_BufferList.find(GetResourceID()) == m_BufferList.end());
m_BufferList[GetResourceID()] = BufferEntry(this, byteLength);
}
@@ -477,15 +526,11 @@ public:
virtual ~WrappedID3D11Buffer()
{
SCOPED_LOCK(m_pDevice->D3DLock());
if(RenderDoc::Inst().IsReplayApp())
{
if(m_BufferList.find(GetResourceID()) != m_BufferList.end())
m_BufferList.erase(GetResourceID());
}
Shutdown();
}
virtual void STDMETHODCALLTYPE GetType(D3D11_RESOURCE_DIMENSION *pResourceDimension)
@@ -520,8 +565,6 @@ public:
{
if(RenderDoc::Inst().IsReplayApp())
{
SCOPED_LOCK(m_pDevice->D3DLock());
RDCASSERT(m_TextureList.find(GetResourceID()) == m_TextureList.end());
m_TextureList[GetResourceID()] = TextureEntry(this, type);
}
@@ -530,15 +573,11 @@ public:
virtual ~WrappedTexture()
{
SCOPED_LOCK(m_pDevice->D3DLock());
if(RenderDoc::Inst().IsReplayApp())
{
if(m_TextureList.find(GetResourceID()) != m_TextureList.end())
m_TextureList.erase(GetResourceID());
}
Shutdown();
}
};
@@ -648,7 +687,7 @@ public:
: WrappedDeviceChild11<ID3D11InputLayout>(real, device)
{
}
virtual ~WrappedID3D11InputLayout() { Shutdown(); }
virtual ~WrappedID3D11InputLayout() {}
};
class WrappedID3D11RasterizerState2
@@ -661,7 +700,7 @@ public:
: WrappedDeviceChild11(real, device)
{
}
virtual ~WrappedID3D11RasterizerState2() { Shutdown(); }
virtual ~WrappedID3D11RasterizerState2() {}
//////////////////////////////
// implement ID3D11RasterizerState
@@ -702,8 +741,7 @@ public:
: WrappedDeviceChild11(real, device)
{
}
virtual ~WrappedID3D11BlendState1() { Shutdown(); }
static bool IsState1(ID3D11BlendState *state) { return CanQuery<ID3D11BlendState1>(state); }
virtual ~WrappedID3D11BlendState1() {}
//////////////////////////////
// implement ID3D11BlendState
@@ -731,7 +769,7 @@ public:
: WrappedDeviceChild11<ID3D11DepthStencilState>(real, device)
{
}
virtual ~WrappedID3D11DepthStencilState() { Shutdown(); }
virtual ~WrappedID3D11DepthStencilState() {}
//////////////////////////////
// implement ID3D11DepthStencilState
@@ -750,7 +788,7 @@ public:
: WrappedDeviceChild11<ID3D11SamplerState>(real, device)
{
}
virtual ~WrappedID3D11SamplerState() { Shutdown(); }
virtual ~WrappedID3D11SamplerState() {}
//////////////////////////////
// implement ID3D11SamplerState
@@ -769,14 +807,12 @@ protected:
: WrappedDeviceChild11(real, device), m_pResource(res), m_ResourceRange(this)
{
m_ResourceResID = GetIDForResource(m_pResource);
// cast is potentially invalid but functions in WrappedResource will be identical across each
((WrappedID3D11Buffer *)m_pResource)->ViewAddRef();
::IntAddRef(m_pResource);
}
virtual ~WrappedView1()
{
// cast is potentially invalid but functions in WrappedResource will be identical across each
((WrappedID3D11Buffer *)m_pResource)->ViewRelease();
::IntRelease(m_pResource);
m_pResource = NULL;
}
@@ -804,8 +840,10 @@ public:
{
RDCASSERT(m_pResource);
if(pResource)
{
*pResource = m_pResource;
m_pResource->AddRef();
m_pResource->AddRef();
}
}
//////////////////////////////
@@ -830,7 +868,7 @@ public:
: WrappedView1(real, device, res)
{
}
virtual ~WrappedID3D11RenderTargetView1() { Shutdown(); }
virtual ~WrappedID3D11RenderTargetView1() {}
//////////////////////////////
// implement ID3D11RenderTargetView1
virtual void STDMETHODCALLTYPE GetDesc1(D3D11_RENDER_TARGET_VIEW_DESC1 *pDesc1)
@@ -856,7 +894,7 @@ public:
: WrappedView1(real, device, res)
{
}
virtual ~WrappedID3D11ShaderResourceView1() { Shutdown(); }
virtual ~WrappedID3D11ShaderResourceView1() {}
//////////////////////////////
// implement ID3D11ShaderResourceView1
virtual void STDMETHODCALLTYPE GetDesc1(D3D11_SHADER_RESOURCE_VIEW_DESC1 *pDesc1)
@@ -882,7 +920,7 @@ public:
: WrappedView1(real, device, res)
{
}
virtual ~WrappedID3D11DepthStencilView() { Shutdown(); }
virtual ~WrappedID3D11DepthStencilView() {}
};
class WrappedID3D11UnorderedAccessView1
@@ -897,7 +935,7 @@ public:
: WrappedView1(real, device, res)
{
}
virtual ~WrappedID3D11UnorderedAccessView1() { Shutdown(); }
virtual ~WrappedID3D11UnorderedAccessView1() {}
//////////////////////////////
// implement ID3D11UnorderedAccessView1
virtual void STDMETHODCALLTYPE GetDesc1(D3D11_UNORDERED_ACCESS_VIEW_DESC1 *pDesc1)
@@ -1034,7 +1072,7 @@ public:
WrappedShader(device, origId, GetResourceID(), code, codeLen)
{
}
virtual ~WrappedID3D11Shader() { Shutdown(); }
virtual ~WrappedID3D11Shader() {}
};
class WrappedID3D11Counter : public WrappedDeviceChild11<ID3D11Counter>
@@ -1046,7 +1084,7 @@ public:
: WrappedDeviceChild11(real, device)
{
}
virtual ~WrappedID3D11Counter() { Shutdown(); }
virtual ~WrappedID3D11Counter() {}
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject)
{
if(riid == __uuidof(ID3D11Asynchronous))
@@ -1078,7 +1116,7 @@ public:
: WrappedDeviceChild11(real, device)
{
}
virtual ~WrappedID3D11Query1() { Shutdown(); }
virtual ~WrappedID3D11Query1() {}
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject)
{
if(riid == __uuidof(ID3D11Asynchronous))
@@ -1122,7 +1160,7 @@ public:
: WrappedDeviceChild11(real, device)
{
}
virtual ~WrappedID3D11Predicate() { Shutdown(); }
virtual ~WrappedID3D11Predicate() {}
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject)
{
if(riid == __uuidof(ID3D11Asynchronous))
@@ -1159,12 +1197,7 @@ public:
{
SAFE_ADDREF(m_pLinkage);
}
virtual ~WrappedID3D11ClassInstance()
{
SAFE_RELEASE(m_pLinkage);
Shutdown();
}
virtual ~WrappedID3D11ClassInstance() { SAFE_RELEASE(m_pLinkage); }
//////////////////////////////
// implement ID3D11ClassInstance
@@ -1174,8 +1207,8 @@ public:
{
if(ppLinkage)
{
SAFE_ADDREF(m_pLinkage);
*ppLinkage = m_pLinkage;
AddRef();
}
}
@@ -1214,7 +1247,7 @@ public:
: WrappedDeviceChild11(real, device)
{
}
virtual ~WrappedID3D11ClassLinkage() { Shutdown(); }
virtual ~WrappedID3D11ClassLinkage() {}
//////////////////////////////
// implement ID3D11ClassLinkage
@@ -1313,7 +1346,6 @@ public:
}
// context isn't defined type at this point.
Shutdown();
}
WrappedID3D11DeviceContext *GetContext() { return m_pContext; }
@@ -1359,7 +1391,7 @@ public:
: WrappedDeviceChild11(real, device)
{
}
virtual ~WrappedID3D11Fence() { Shutdown(); }
virtual ~WrappedID3D11Fence() {}
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject)
{
return WrappedDeviceChild11<ID3D11Fence>::QueryInterface(riid, ppvObject);
+19 -6
View File
@@ -1357,28 +1357,41 @@ void STDMETHODCALLTYPE WrappedID3D11VideoProcessorOutputView::GetResource(
template <typename NestedType, typename NestedType1>
Wrapped11VideoDeviceChild<NestedType, NestedType1>::Wrapped11VideoDeviceChild(
NestedType *real, WrappedID3D11Device *device)
: RefCounter(real), m_pDevice(device), m_pReal(real)
: m_pDevice(device), m_pReal(real), m_ExtRef(1)
{
m_pDevice->SoftRef();
m_pDevice->AddRef();
}
template <typename NestedType, typename NestedType1>
Wrapped11VideoDeviceChild<NestedType, NestedType1>::~Wrapped11VideoDeviceChild()
{
SAFE_RELEASE(m_pReal);
m_pDevice = NULL;
// remove our device ref here as we don't have IntRef counter to keep the device alive when it
// hits ExtRef 0, which is when we'd normally release the device ref.
SAFE_RELEASE(m_pDevice);
}
template <typename NestedType, typename NestedType1>
ULONG STDMETHODCALLTYPE Wrapped11VideoDeviceChild<NestedType, NestedType1>::AddRef()
{
return RefCounter::SoftRef(m_pDevice);
if(m_ExtRef == 0)
m_pDevice->AddRef();
Atomic::Inc32(&m_ExtRef);
return m_ExtRef;
}
template <typename NestedType, typename NestedType1>
ULONG STDMETHODCALLTYPE Wrapped11VideoDeviceChild<NestedType, NestedType1>::Release()
{
return RefCounter::SoftRelease(m_pDevice);
Atomic::Dec32(&m_ExtRef);
ASSERT_REFCOUNT(m_ExtRef);
// don't defer destruction of video objects, delete them immediately.
if(m_ExtRef == 0)
{
delete this;
return 0;
}
return (ULONG)m_ExtRef;
}
template <typename NestedType, typename NestedType1>
@@ -1424,7 +1437,7 @@ Wrapped11VideoDeviceChild<NestedType, NestedType1>::QueryInterface(REFIID riid,
return m_pDevice->QueryInterface(riid, ppvObject);
}
return RefCounter::QueryInterface(riid, ppvObject);
return RefCountDXGIObject::WrapQueryInterface(m_pReal, riid, ppvObject);
}
template <typename NestedType, typename NestedType1>
+6 -1
View File
@@ -1033,8 +1033,13 @@ struct WrappedID3D11VideoContext2 : public ID3D11VideoContext2
// we don't want to depend on d3d11_resources.h in this header, so replicate
// WrappedID3D11DeviceChild here (and it's simpler because these are pure pass-through wrappers)
template <typename NestedType, typename NestedType1 = NestedType>
struct Wrapped11VideoDeviceChild : public RefCounter, public NestedType1
struct Wrapped11VideoDeviceChild : public NestedType1
{
private:
// we don't need internal references because nothing holds internal references on these video
// objects
int32_t m_ExtRef;
protected:
WrappedID3D11Device *m_pDevice;
NestedType *m_pReal;
-3
View File
@@ -361,9 +361,6 @@ struct D3D12CommandSignature
rdcarray<D3D12_INDIRECT_ARGUMENT_DESC> arguments;
};
#define IMPLEMENT_IUNKNOWN_WITH_REFCOUNTER_CUSTOMQUERY \
ULONG STDMETHODCALLTYPE AddRef() { return RefCounter12::AddRef(); } \
ULONG STDMETHODCALLTYPE Release() { return RefCounter12::Release(); }
#define IMPLEMENT_FUNCTION_SERIALISED(ret, func, ...) \
ret func(__VA_ARGS__); \
template <typename SerialiserType> \