mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-10-13 07:39:22 +00:00
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:
32 files changed
+1933
-816
No files matched your search
@@ -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> \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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> \
|
||||
|
||||
Reference in new issue
Block a user