From faa1b6ced50c569933c177914b4afe2826ad1d52 Mon Sep 17 00:00:00 2001 From: baldurk Date: Mon, 17 Apr 2017 13:37:19 +0100 Subject: [PATCH] Hold references to used resources on deferred command lists * We need to keep any resources used on deferred contexts alive until the produced command list is released. Otherwise the resource might be destroyed before we replay it, and we'll have lost that information. --- renderdoc/core/resource_manager.cpp | 6 +++--- renderdoc/core/resource_manager.h | 2 +- renderdoc/driver/d3d11/d3d11_context.cpp | 14 +++++++++++++- renderdoc/driver/d3d11/d3d11_context.h | 1 + renderdoc/driver/d3d11/d3d11_context_wrap.cpp | 1 + renderdoc/driver/d3d11/d3d11_resources.h | 11 +++++++++++ 6 files changed, 30 insertions(+), 5 deletions(-) diff --git a/renderdoc/core/resource_manager.cpp b/renderdoc/core/resource_manager.cpp index 6001d5ee2..f43e997c2 100644 --- a/renderdoc/core/resource_manager.cpp +++ b/renderdoc/core/resource_manager.cpp @@ -47,11 +47,11 @@ void SetReplayResourceIDs() } }; -void ResourceRecord::MarkResourceFrameReferenced(ResourceId id, FrameRefType refType) +bool ResourceRecord::MarkResourceFrameReferenced(ResourceId id, FrameRefType refType) { if(id == ResourceId()) - return; - ResourceManager::MarkReferenced(m_FrameRefs, id, refType); + return false; + return ResourceManager::MarkReferenced(m_FrameRefs, id, refType); } void ResourceRecord::AddResourceReferences(ResourceRecordHandler *mgr) diff --git a/renderdoc/core/resource_manager.h b/renderdoc/core/resource_manager.h index d871204d4..93ef26990 100644 --- a/renderdoc/core/resource_manager.h +++ b/renderdoc/core/resource_manager.h @@ -243,7 +243,7 @@ struct ResourceRecord bool HasDataPtr() { return DataPtr != NULL; } void SetDataOffset(uint64_t offs) { DataOffset = offs; } void SetDataPtr(byte *ptr) { DataPtr = ptr; } - void MarkResourceFrameReferenced(ResourceId id, FrameRefType refType); + bool MarkResourceFrameReferenced(ResourceId id, FrameRefType refType); void AddResourceReferences(ResourceRecordHandler *mgr); void AddReferencedIDs(std::set &ids) { diff --git a/renderdoc/driver/d3d11/d3d11_context.cpp b/renderdoc/driver/d3d11/d3d11_context.cpp index 6b74a7d1d..9a835b044 100644 --- a/renderdoc/driver/d3d11/d3d11_context.cpp +++ b/renderdoc/driver/d3d11/d3d11_context.cpp @@ -367,7 +367,19 @@ void WrappedID3D11DeviceContext::MarkResourceReferenced(ResourceId id, FrameRefT } else { - m_ContextRecord->MarkResourceFrameReferenced(id, refType); + bool newRef = m_ContextRecord->MarkResourceFrameReferenced(id, refType); + + // we need to keep this resource alive so that we can insert its record on capture + // if this command list gets executed. + if(newRef) + { + D3D11ResourceRecord *record = m_pDevice->GetResourceManager()->GetResourceRecord(id); + if(record) + { + record->AddRef(); + m_DeferredReferences.insert(id); + } + } } } diff --git a/renderdoc/driver/d3d11/d3d11_context.h b/renderdoc/driver/d3d11/d3d11_context.h index d29f93676..38b8b44e1 100644 --- a/renderdoc/driver/d3d11/d3d11_context.h +++ b/renderdoc/driver/d3d11/d3d11_context.h @@ -170,6 +170,7 @@ private: }; set m_DeferredDirty; + set m_DeferredReferences; set m_HighTrafficResources; map m_OpenMaps; diff --git a/renderdoc/driver/d3d11/d3d11_context_wrap.cpp b/renderdoc/driver/d3d11/d3d11_context_wrap.cpp index c877978f5..732c78ca9 100644 --- a/renderdoc/driver/d3d11/d3d11_context_wrap.cpp +++ b/renderdoc/driver/d3d11/d3d11_context_wrap.cpp @@ -5163,6 +5163,7 @@ HRESULT WrappedID3D11DeviceContext::FinishCommandList(BOOL RestoreDeferredContex RDCASSERT(r); m_ContextRecord->SwapChunks(r); + wrapped->SetReferences(m_DeferredReferences); wrapped->SetDirtyResources(m_DeferredDirty); // if we're supposed to restore, save the state to restore to now diff --git a/renderdoc/driver/d3d11/d3d11_resources.h b/renderdoc/driver/d3d11/d3d11_resources.h index 7e44d2e29..3d0cdffba 100644 --- a/renderdoc/driver/d3d11/d3d11_resources.h +++ b/renderdoc/driver/d3d11/d3d11_resources.h @@ -1252,6 +1252,7 @@ class WrappedID3D11CommandList : public WrappedDeviceChild11 // list set m_Dirty; + set m_References; public: ALLOCATE_WITH_WRAPPED_POOL(WrappedID3D11CommandList); @@ -1264,12 +1265,22 @@ public: } virtual ~WrappedID3D11CommandList() { + D3D11ResourceManager *manager = m_pDevice->GetResourceManager(); + // release the references we were holding + for(ResourceId id : m_References) + { + D3D11ResourceRecord *record = manager->GetResourceRecord(id); + if(record) + record->Delete(manager); + } + // context isn't defined type at this point. Shutdown(); } WrappedID3D11DeviceContext *GetContext() { return m_pContext; } bool IsCaptured() { return m_Successful; } + void SetReferences(set &refs) { m_References.swap(refs); } void SetDirtyResources(set &dirty) { m_Dirty.swap(dirty); } void MarkDirtyResources(D3D11ResourceManager *manager) {