Add remaining parent and dependency tracking to serialise frame

This commit is contained in:
baldurk
2016-07-07 15:33:16 +03:00
parent 4d394bcdce
commit 297fe80b79
11 changed files with 319 additions and 78 deletions
@@ -93,6 +93,13 @@ class WrappedID3D12GraphicsCommandList : public RefCounter12<ID3D12GraphicsComma
DummyID3D12DebugCommandList m_DummyDebug;
struct
{
IID riid;
UINT nodeMask;
D3D12_COMMAND_LIST_TYPE type;
} m_Init;
const char *GetChunkName(uint32_t idx) { return m_pDevice->GetChunkName(idx); }
D3D12ResourceManager *GetResourceManager() { return m_pDevice->GetResourceManager(); }
public:
@@ -106,8 +113,16 @@ public:
ResourceId GetResourceID() { return m_ResourceID; }
ID3D12GraphicsCommandList *GetReal() { return m_pReal; }
WrappedID3D12Device *GetWrappedDevice() { return m_pDevice; }
D3D12ResourceRecord *GetResourceRecord() { return m_ListRecord; }
ID3D12GraphicsCommandList *GetList(ResourceId id);
void SetInitParams(REFIID riid, UINT nodeMask, D3D12_COMMAND_LIST_TYPE type)
{
m_Init.riid = riid;
m_Init.nodeMask = nodeMask;
m_Init.type = type;
}
//////////////////////////////
// implement IUnknown
@@ -402,3 +417,8 @@ template <>
ResourceId GetResID(ID3D12GraphicsCommandList *obj);
template <>
ResourceId GetResID(ID3D12CommandList *obj);
template <>
D3D12ResourceRecord *GetRecord(ID3D12GraphicsCommandList *obj);
template <>
D3D12ResourceRecord *GetRecord(ID3D12CommandList *obj);
@@ -43,10 +43,14 @@ HRESULT WrappedID3D12GraphicsCommandList::Close()
{
if(m_State >= WRITING)
{
SCOPED_SERIALISE_CONTEXT(CLOSE_LIST);
Serialise_Close();
{
SCOPED_SERIALISE_CONTEXT(CLOSE_LIST);
Serialise_Close();
m_ListRecord->AddChunk(scope.Get());
m_ListRecord->AddChunk(scope.Get());
}
m_ListRecord->Bake();
}
// bake m_ListRecord to somewhere else
@@ -57,6 +61,11 @@ HRESULT WrappedID3D12GraphicsCommandList::Close()
bool WrappedID3D12GraphicsCommandList::Serialise_Reset(ID3D12CommandAllocator *pAllocator,
ID3D12PipelineState *pInitialState)
{
// parameters to create the list with if needed
SERIALISE_ELEMENT(IID, riid, m_Init.riid);
SERIALISE_ELEMENT(UINT, nodeMask, m_Init.nodeMask);
SERIALISE_ELEMENT(D3D12_COMMAND_LIST_TYPE, type, m_Init.type);
SERIALISE_ELEMENT(ResourceId, CommandList, GetResourceID());
SERIALISE_ELEMENT(ResourceId, Allocator, GetResID(pAllocator));
SERIALISE_ELEMENT(ResourceId, State, GetResID(pInitialState));
@@ -67,6 +76,12 @@ bool WrappedID3D12GraphicsCommandList::Serialise_Reset(ID3D12CommandAllocator *p
pInitialState =
State == ResourceId() ? NULL : GetResourceManager()->GetLiveAs<ID3D12PipelineState>(State);
if(m_State == READING && !GetResourceManager()->HasLiveResource(CommandList))
{
ID3D12GraphicsCommandList *list = NULL;
m_pDevice->CreateCommandList(nodeMask, type, pAllocator, pInitialState, riid, (void **)&list);
}
GetList(CommandList)->Reset(Unwrap(pAllocator), Unwrap(pInitialState));
}
@@ -84,10 +99,21 @@ HRESULT WrappedID3D12GraphicsCommandList::Reset(ID3D12CommandAllocator *pAllocat
// free parents
m_ListRecord->FreeParents(GetResourceManager());
SCOPED_SERIALISE_CONTEXT(RESET_LIST);
Serialise_Reset(pAllocator, pInitialState);
// free any baked commands
if(m_ListRecord->bakedCommands)
m_ListRecord->bakedCommands->Delete(GetResourceManager());
m_ListRecord->AddChunk(scope.Get());
m_ListRecord->bakedCommands =
GetResourceManager()->AddResourceRecord(ResourceIDGen::GetNewUniqueID());
m_ListRecord->bakedCommands->SpecialResource = true;
m_ListRecord->bakedCommands->cmdInfo = new CmdListRecordingInfo();
{
SCOPED_SERIALISE_CONTEXT(RESET_LIST);
Serialise_Reset(pAllocator, pInitialState);
m_ListRecord->AddChunk(scope.Get());
}
// add allocator and initial state (if there is one) as parents
m_ListRecord->AddParent(GetRecord(pAllocator));
@@ -216,6 +242,8 @@ void WrappedID3D12GraphicsCommandList::CopyBufferRegion(ID3D12Resource *pDstBuff
Serialise_CopyBufferRegion(pDstBuffer, DstOffset, pSrcBuffer, SrcOffset, NumBytes);
m_ListRecord->AddChunk(scope.Get());
m_ListRecord->MarkResourceFrameReferenced(GetResID(pDstBuffer), eFrameRef_Write);
m_ListRecord->MarkResourceFrameReferenced(GetResID(pSrcBuffer), eFrameRef_Read);
}
}
@@ -379,6 +407,7 @@ void WrappedID3D12GraphicsCommandList::SetPipelineState(ID3D12PipelineState *pPi
Serialise_SetPipelineState(pPipelineState);
m_ListRecord->AddChunk(scope.Get());
m_ListRecord->MarkResourceFrameReferenced(GetResID(pPipelineState), eFrameRef_Read);
}
}
@@ -422,6 +451,9 @@ void WrappedID3D12GraphicsCommandList::ResourceBarrier(UINT NumBarriers,
Serialise_ResourceBarrier(NumBarriers, pBarriers);
m_ListRecord->AddChunk(scope.Get());
m_ListRecord->cmdInfo->barriers.insert(m_ListRecord->cmdInfo->barriers.end(), pBarriers,
pBarriers + NumBarriers);
}
}
@@ -467,6 +499,7 @@ void WrappedID3D12GraphicsCommandList::SetGraphicsRootSignature(ID3D12RootSignat
Serialise_SetGraphicsRootSignature(pRootSignature);
m_ListRecord->AddChunk(scope.Get());
m_ListRecord->MarkResourceFrameReferenced(GetResID(pRootSignature), eFrameRef_Read);
}
}
@@ -548,6 +581,7 @@ void WrappedID3D12GraphicsCommandList::SetGraphicsRootConstantBufferView(
Serialise_SetGraphicsRootConstantBufferView(RootParameterIndex, BufferLocation);
m_ListRecord->AddChunk(scope.Get());
m_ListRecord->MarkResourceFrameReferenced(GetResID(BufferLocation), eFrameRef_Read);
}
}
@@ -612,6 +646,8 @@ void WrappedID3D12GraphicsCommandList::IASetIndexBuffer(const D3D12_INDEX_BUFFER
Serialise_IASetIndexBuffer(pView);
m_ListRecord->AddChunk(scope.Get());
if(pView)
m_ListRecord->MarkResourceFrameReferenced(GetResID(pView->BufferLocation), eFrameRef_Read);
}
}
@@ -654,6 +690,8 @@ void WrappedID3D12GraphicsCommandList::IASetVertexBuffers(UINT StartSlot, UINT N
Serialise_IASetVertexBuffers(StartSlot, NumViews, pViews);
m_ListRecord->AddChunk(scope.Get());
for(UINT i = 0; i < NumViews; i++)
m_ListRecord->MarkResourceFrameReferenced(GetResID(pViews[i].BufferLocation), eFrameRef_Read);
}
}
@@ -742,6 +780,19 @@ void WrappedID3D12GraphicsCommandList::OMSetRenderTargets(
RTsSingleHandleToDescriptorRange, pDepthStencilDescriptor);
m_ListRecord->AddChunk(scope.Get());
for(UINT i = 0; i < numHandles; i++)
{
D3D12Descriptor *desc = GetWrapped(pRenderTargetDescriptors[i]);
m_ListRecord->MarkResourceFrameReferenced(desc->nonsamp.heap->GetResourceID(), eFrameRef_Read);
m_ListRecord->MarkResourceFrameReferenced(GetResID(desc->nonsamp.resource), eFrameRef_Read);
}
if(pDepthStencilDescriptor)
{
D3D12Descriptor *desc = GetWrapped(*pDepthStencilDescriptor);
m_ListRecord->MarkResourceFrameReferenced(desc->nonsamp.heap->GetResourceID(), eFrameRef_Read);
m_ListRecord->MarkResourceFrameReferenced(GetResID(desc->nonsamp.resource), eFrameRef_Read);
}
}
}
@@ -794,6 +845,12 @@ void WrappedID3D12GraphicsCommandList::ClearRenderTargetView(
Serialise_ClearRenderTargetView(RenderTargetView, ColorRGBA, NumRects, pRects);
m_ListRecord->AddChunk(scope.Get());
{
D3D12Descriptor *desc = GetWrapped(RenderTargetView);
m_ListRecord->MarkResourceFrameReferenced(desc->nonsamp.heap->GetResourceID(), eFrameRef_Read);
m_ListRecord->MarkResourceFrameReferenced(GetResID(desc->nonsamp.resource), eFrameRef_Read);
}
}
}
+8 -2
View File
@@ -80,10 +80,13 @@ class WrappedID3D12CommandQueue : public ID3D12CommandQueue,
DummyID3D12DebugCommandQueue m_DummyDebug;
vector<D3D12ResourceRecord *> m_CmdListRecords;
const char *GetChunkName(uint32_t idx) { return m_pDevice->GetChunkName(idx); }
D3D12ResourceManager *GetResourceManager() { return m_pDevice->GetResourceManager(); }
public:
ALLOCATE_WITH_WRAPPED_POOL(WrappedID3D12CommandQueue);
static const int AllocPoolCount = 16;
ALLOCATE_WITH_WRAPPED_POOL(WrappedID3D12CommandQueue, AllocPoolCount);
WrappedID3D12CommandQueue(ID3D12CommandQueue *real, WrappedID3D12Device *device,
Serialiser *serialiser, LogState &state);
@@ -92,8 +95,11 @@ public:
Serialiser *GetSerialiser() { return m_pSerialiser; }
ResourceId GetResourceID() { return m_ResourceID; }
ID3D12CommandQueue *GetReal() { return m_pReal; }
D3D12ResourceRecord *GetRecord() { return m_QueueRecord; }
D3D12ResourceRecord *GetResourceRecord() { return m_QueueRecord; }
WrappedID3D12Device *GetWrappedDevice() { return m_pDevice; }
const vector<D3D12ResourceRecord *> &GetCmdLists() { return m_CmdListRecords; }
void ClearAfterCapture();
// interface for DXGI
virtual IUnknown *GetRealIUnknown() { return GetReal(); }
virtual IID GetBackbufferUUID() { return __uuidof(ID3D12Resource); }
@@ -83,12 +83,84 @@ void STDMETHODCALLTYPE WrappedID3D12CommandQueue::ExecuteCommandLists(
SAFE_DELETE_ARRAY(unwrapped);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(EXECUTE_CMD_LISTS);
Serialise_ExecuteCommandLists(NumCommandLists, ppCommandLists);
bool capframe = false;
set<ResourceId> refdIDs;
m_QueueRecord->AddChunk(scope.Get());
for(UINT i = 0; i < NumCommandLists; i++)
{
D3D12ResourceRecord *record = GetRecord(ppCommandLists[i]);
// TODO apply barriers from command list to current resource state tracking
// need to lock the whole section of code, not just the check on
// m_State, as we also need to make sure we don't check the state,
// start marking dirty resources then while we're doing so the
// state becomes capframe.
// the next sections where we mark resources referenced and add
// the submit chunk to the frame record don't have to be protected.
// Only the decision of whether we're inframe or not, and marking
// dirty.
{
SCOPED_LOCK(m_pDevice->GetCapTransitionLock());
if(m_State == WRITING_CAPFRAME)
{
for(auto it = record->bakedCommands->cmdInfo->dirtied.begin();
it != record->bakedCommands->cmdInfo->dirtied.end(); ++it)
GetResourceManager()->MarkPendingDirty(*it);
capframe = true;
}
else
{
for(auto it = record->bakedCommands->cmdInfo->dirtied.begin();
it != record->bakedCommands->cmdInfo->dirtied.end(); ++it)
GetResourceManager()->MarkDirtyResource(*it);
}
}
if(capframe)
{
// pull in frame refs from this baked command buffer
record->bakedCommands->AddResourceReferences(GetResourceManager());
record->bakedCommands->AddReferencedIDs(refdIDs);
// ref the parent command buffer by itself, this will pull in the cmd buffer pool
GetResourceManager()->MarkResourceFrameReferenced(record->GetResourceID(), eFrameRef_Read);
// reference all executed bundles as well
for(size_t b = 0; b < record->bakedCommands->cmdInfo->bundles.size(); b++)
{
record->bakedCommands->cmdInfo->bundles[b]->bakedCommands->AddResourceReferences(
GetResourceManager());
record->bakedCommands->cmdInfo->bundles[b]->bakedCommands->AddReferencedIDs(refdIDs);
GetResourceManager()->MarkResourceFrameReferenced(
record->bakedCommands->cmdInfo->bundles[b]->GetResourceID(), eFrameRef_Read);
record->bakedCommands->cmdInfo->bundles[b]->bakedCommands->AddRef();
}
{
m_CmdListRecords.push_back(record->bakedCommands);
for(size_t sub = 0; sub < record->bakedCommands->cmdInfo->bundles.size(); sub++)
m_CmdListRecords.push_back(record->bakedCommands->cmdInfo->bundles[sub]->bakedCommands);
}
record->bakedCommands->AddRef();
}
record->cmdInfo->dirtied.clear();
}
if(capframe)
{
// flush coherent maps
for(UINT i = 0; i < NumCommandLists; i++)
{
SCOPED_SERIALISE_CONTEXT(EXECUTE_CMD_LISTS);
Serialise_ExecuteCommandLists(1, ppCommandLists + i);
m_QueueRecord->AddChunk(scope.Get());
}
}
}
+33 -3
View File
@@ -64,6 +64,24 @@ ResourceId GetResID(ID3D12CommandList *obj)
return ((WrappedID3D12GraphicsCommandList *)obj)->GetResourceID();
}
template <>
D3D12ResourceRecord *GetRecord(ID3D12GraphicsCommandList *obj)
{
if(obj == NULL)
return NULL;
return ((WrappedID3D12GraphicsCommandList *)obj)->GetResourceRecord();
}
template <>
D3D12ResourceRecord *GetRecord(ID3D12CommandList *obj)
{
if(obj == NULL)
return NULL;
return ((WrappedID3D12GraphicsCommandList *)obj)->GetResourceRecord();
}
template <>
ID3D12CommandQueue *Unwrap(ID3D12CommandQueue *obj)
{
@@ -88,7 +106,7 @@ D3D12ResourceRecord *GetRecord(ID3D12CommandQueue *obj)
if(obj == NULL)
return NULL;
return ((WrappedID3D12CommandQueue *)obj)->GetRecord();
return ((WrappedID3D12CommandQueue *)obj)->GetResourceRecord();
}
ULONG STDMETHODCALLTYPE DummyID3D12DebugCommandQueue::AddRef()
@@ -150,7 +168,6 @@ WrappedID3D12CommandQueue::WrappedID3D12CommandQueue(ID3D12CommandQueue *real,
m_QueueRecord->DataInSerialiser = false;
m_QueueRecord->SpecialResource = true;
m_QueueRecord->Length = 0;
m_QueueRecord->ignoreSerialise = true;
}
m_pDevice->SoftRef();
@@ -201,6 +218,15 @@ HRESULT STDMETHODCALLTYPE WrappedID3D12CommandQueue::QueryInterface(REFIID riid,
return RefCounter12::QueryInterface(riid, ppvObject);
}
void WrappedID3D12CommandQueue::ClearAfterCapture()
{
// delete cmd buffers now - had to keep them alive until after serialiser flush.
for(size_t i = 0; i < m_CmdListRecords.size(); i++)
m_CmdListRecords[i]->Delete(GetResourceManager());
m_CmdListRecords.clear();
}
WrappedID3D12GraphicsCommandList::WrappedID3D12GraphicsCommandList(ID3D12GraphicsCommandList *real,
WrappedID3D12Device *device,
Serialiser *serialiser,
@@ -237,7 +263,11 @@ WrappedID3D12GraphicsCommandList::WrappedID3D12GraphicsCommandList(ID3D12Graphic
m_ListRecord->DataInSerialiser = false;
m_ListRecord->SpecialResource = true;
m_ListRecord->Length = 0;
m_ListRecord->ignoreSerialise = true;
m_ListRecord->cmdInfo = new CmdListRecordingInfo();
// this is set up in the implicit Reset() right after creation
m_ListRecord->bakedCommands = NULL;
}
m_pDevice->SoftRef();
+18 -1
View File
@@ -28,6 +28,19 @@
#include "d3d12_manager.h"
#include "d3d12_resources.h"
enum D3D12ResourceBarrierSubresource
{
D3D12AllSubresources = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES
};
string ToStrHelper<false, D3D12ResourceBarrierSubresource>::Get(const D3D12ResourceBarrierSubresource &el)
{
if(el == D3D12AllSubresources)
return "All Subresources";
return ToStr::Get(uint32_t(el));
}
// we know the object will be a non-dispatchable object type
#define SerialiseObject(type, name, obj) \
{ \
@@ -398,7 +411,11 @@ void Serialiser::Serialise(const char *name, D3D12_RESOURCE_BARRIER &el)
case D3D12_RESOURCE_BARRIER_TYPE_TRANSITION:
{
SerialiseObject(ID3D12Resource, "Transition.pResource", el.Transition.pResource);
Serialise("Transition.Subresource", el.Transition.Subresource);
// cast to a special enum so we print 'all subresources' nicely
RDCCOMPILE_ASSERT(sizeof(D3D12ResourceBarrierSubresource) == sizeof(UINT),
"Enum isn't uint sized");
Serialise("Transition.Subresource",
(D3D12ResourceBarrierSubresource &)el.Transition.Subresource);
Serialise("Transition.StateBefore", el.Transition.StateBefore);
Serialise("Transition.StateAfter", el.Transition.StateAfter);
break;
+46 -30
View File
@@ -217,6 +217,7 @@ WrappedID3D12Device::WrappedID3D12Device(ID3D12Device *realDevice, D3D12InitPara
m_DeviceRecord = NULL;
m_Queue = NULL;
m_LastSwap = NULL;
if(!RenderDoc::Inst().IsReplayApp())
{
@@ -227,8 +228,8 @@ WrappedID3D12Device::WrappedID3D12Device(ID3D12Device *realDevice, D3D12InitPara
m_FrameCaptureRecord = GetResourceManager()->AddResourceRecord(ResourceIDGen::GetNewUniqueID());
m_FrameCaptureRecord->DataInSerialiser = false;
m_FrameCaptureRecord->Length = 0;
m_FrameCaptureRecord->SpecialResource = true;
m_FrameCaptureRecord->Length = 0;
RenderDoc::Inst().AddDeviceFrameCapturer((ID3D12Device *)this, this);
}
@@ -573,7 +574,10 @@ IUnknown *WrappedID3D12Device::WrapSwapchainBuffer(WrappedIDXGISwapChain3 *swap,
D3D12NOTIMP("Creating RTV for rendering to back buffer");
// m_pDevice->CreateRenderTargetView(Unwrap(pRes), &rtvDesc, rtv);
m_SwapChains[swap] = rtv;
m_SwapChains[swap].rtvs[buffer] = rtv;
// start at -1 so that we know we've never presented before
m_SwapChains[swap].lastPresentedBuffer = -1;
}
if(swap)
@@ -603,6 +607,20 @@ HRESULT WrappedID3D12Device::Present(WrappedIDXGISwapChain3 *swap, UINT SyncInte
swap->GetDesc(&swapdesc);
bool activeWindow = RenderDoc::Inst().IsActiveWindow((ID3D12Device *)this, swapdesc.OutputWindow);
m_LastSwap = swap;
if(swapdesc.SwapEffect == DXGI_SWAP_EFFECT_DISCARD)
{
// discard always presents from 0
m_SwapChains[swap].lastPresentedBuffer = 0;
}
else
{
// other modes use each buffer in turn
m_SwapChains[swap].lastPresentedBuffer++;
m_SwapChains[swap].lastPresentedBuffer %= swapdesc.BufferCount;
}
if(m_State == WRITING_IDLE)
{
m_FrameTimes.push_back(m_FrameTimer.GetMilliseconds());
@@ -765,11 +783,11 @@ bool WrappedID3D12Device::Serialise_BeginCaptureFrame(bool applyInitialState)
return true;
}
// TODO save initial resources
// TODO save initial resource states
if(applyInitialState)
{
// apply initial resources
// apply initial resource states
}
return true;
@@ -842,7 +860,6 @@ void WrappedID3D12Device::StartFrameCapture(void *dev, void *wnd)
GetResourceManager()->ClearReferencedResources();
GetResourceManager()->MarkResourceFrameReferenced(m_ResourceID, eFrameRef_Read);
GetResourceManager()->MarkResourceFrameReferenced(GetResID(m_Queue), eFrameRef_Read);
// need to do all this atomically so that no other commands
// will check to see if they need to markdirty or markpendingdirty
@@ -876,6 +893,7 @@ bool WrappedID3D12Device::EndFrameCapture(void *dev, void *wnd)
return true;
WrappedIDXGISwapChain3 *swap = NULL;
SwapPresentInfo swapInfo = {};
if(wnd)
{
@@ -887,6 +905,7 @@ bool WrappedID3D12Device::EndFrameCapture(void *dev, void *wnd)
if(swapDesc.OutputWindow == wnd)
{
swap = it->first;
swapInfo = it->second;
break;
}
}
@@ -900,11 +919,17 @@ bool WrappedID3D12Device::EndFrameCapture(void *dev, void *wnd)
RDCLOG("Finished capture, Frame %u", m_FrameCounter);
// TODO either get the swapchain associated with this window, or the last swapchain
// to be presented.
// Get the last buffer presented on that swapchain as backbuffer
ID3D12Resource *backbuffer = NULL;
if(swap == NULL)
{
swap = m_LastSwap;
swapInfo = m_SwapChains[swap];
}
if(swap != NULL)
backbuffer = (ID3D12Resource *)swap->GetBackbuffers()[swapInfo.lastPresentedBuffer];
// transition back to IDLE atomically
{
SCOPED_LOCK(m_CapTransitionLock);
@@ -912,7 +937,7 @@ bool WrappedID3D12Device::EndFrameCapture(void *dev, void *wnd)
m_State = WRITING_IDLE;
// TOD wait for idle
// TODO wait for idle
// TODO free coherent map capture ref-data
}
@@ -980,31 +1005,26 @@ bool WrappedID3D12Device::EndFrameCapture(void *dev, void *wnd)
// in capframe (the transition is thread-protected) so nothing will be
// pushed to the vector
map<int32_t, Chunk *> recordlist;
{
const vector<D3D12ResourceRecord *> &cmdListRecords = m_Queue->GetCmdLists();
RDCDEBUG("Flushing %u command buffer records to file serialiser",
(uint32_t)m_CmdListRecords.size());
(uint32_t)cmdListRecords.size());
map<int32_t, Chunk *> recordlist;
// ensure all command buffer records within the frame evne if recorded before, but
// otherwise order must be preserved (vs. queue submits and desc set updates)
for(size_t i = 0; i < m_CmdListRecords.size(); i++)
for(size_t i = 0; i < cmdListRecords.size(); i++)
{
/*
SCOPED_SERIALISE_CONTEXT(BEGIN_CMD_LIST);
Serialise_BeginCmdList(m_CmdListRecords[i]->GetResourceID());
Chunk *beginCmdList = scope.Get();
*/
m_CmdListRecords[i]->Insert(recordlist);
cmdListRecords[i]->Insert(recordlist);
RDCDEBUG("Adding %u chunks to file serialiser from command buffer %llu",
(uint32_t)recordlist.size(), m_CmdListRecords[i]->GetResourceID());
(uint32_t)recordlist.size(), cmdListRecords[i]->GetResourceID());
}
GetRecord(m_Queue)->Insert(recordlist);
m_Queue->GetResourceRecord()->Insert(recordlist);
}
{
m_FrameCaptureRecord->Insert(recordlist);
RDCDEBUG("Flushing %u chunks to file serialiser from context record",
@@ -1025,11 +1045,7 @@ bool WrappedID3D12Device::EndFrameCapture(void *dev, void *wnd)
m_State = WRITING_IDLE;
// delete cmd buffers now - had to keep them alive until after serialiser flush.
for(size_t i = 0; i < m_CmdListRecords.size(); i++)
m_CmdListRecords[i]->Delete(GetResourceManager());
m_CmdListRecords.clear();
m_Queue->ClearAfterCapture();
GetResourceManager()->MarkUnwrittenResources();
+14 -11
View File
@@ -210,12 +210,14 @@ struct DummyID3D12DebugDevice : public ID3D12DebugDevice
virtual HRESULT STDMETHODCALLTYPE ReportLiveDeviceObjects(D3D12_RLDO_FLAGS Flags) { return S_OK; }
};
class WrappedID3D12CommandQueue;
class WrappedID3D12Device : public IFrameCapturer, public ID3DDevice, public ID3D12Device
{
private:
ID3D12Device *m_pDevice;
ID3D12CommandQueue *m_Queue;
WrappedID3D12CommandQueue *m_Queue;
D3D12ResourceManager *m_ResourceManager;
DummyID3D12InfoQueue m_DummyInfoQueue;
@@ -251,19 +253,19 @@ private:
D3D12ResourceRecord *m_FrameCaptureRecord;
Chunk *m_HeaderChunk;
// we record the command buffer records so we can insert them
// individually, that means even if they were recorded locklessly
// in parallel, on replay they are disjoint and it makes things
// much easier to process (we will enforce/display ordering
// by queue submit order anyway, so it's OK to lose the record
// order).
Threading::CriticalSection m_CmdListRecordsLock;
vector<D3D12ResourceRecord *> m_CmdListRecords;
ResourceId m_ResourceID;
D3D12ResourceRecord *m_DeviceRecord;
map<WrappedIDXGISwapChain3 *, D3D12_CPU_DESCRIPTOR_HANDLE> m_SwapChains;
struct SwapPresentInfo
{
D3D12_CPU_DESCRIPTOR_HANDLE rtvs[8];
int32_t lastPresentedBuffer;
};
map<WrappedIDXGISwapChain3 *, SwapPresentInfo> m_SwapChains;
WrappedIDXGISwapChain3 *m_LastSwap;
UINT m_DescriptorIncrements[D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES];
@@ -291,6 +293,7 @@ public:
D3D12ResourceManager *GetResourceManager() { return m_ResourceManager; }
Serialiser *GetSerialiser() { return m_pSerialiser; }
ResourceId GetResourceID() { return m_ResourceID; }
Threading::CriticalSection &GetCapTransitionLock() { return m_CapTransitionLock; }
void ReleaseSwapchainResources(IDXGISwapChain *swap, IUnknown **backbuffers, int numBackbuffers);
void FirstFrame(WrappedIDXGISwapChain3 *swap);
+8 -13
View File
@@ -85,7 +85,7 @@ HRESULT WrappedID3D12Device::CreateCommandQueue(const D3D12_COMMAND_QUEUE_DESC *
if(m_Queue != NULL)
RDCERR("Don't support multiple queues yet!");
m_Queue = (ID3D12CommandQueue *)wrapped;
m_Queue = wrapped;
*ppCommandQueue = (ID3D12CommandQueue *)wrapped;
}
@@ -219,18 +219,9 @@ HRESULT WrappedID3D12Device::CreateCommandList(UINT nodeMask, D3D12_COMMAND_LIST
if(m_State >= WRITING)
{
SCOPED_SERIALISE_CONTEXT(CREATE_COMMAND_LIST);
Serialise_CreateCommandList(nodeMask, type, pCommandAllocator, pInitialState, riid,
(void **)&wrapped);
D3D12ResourceRecord *record = wrapped->GetResourceRecord();
// we can add these parents - if the list is reset later, it will free all of its parents
record->AddParent(GetRecord(pCommandAllocator));
if(pInitialState)
record->AddParent(GetRecord(pInitialState));
record->AddChunk(scope.Get());
// we just serialise out command allocator creation as a reset, since it's equivalent.
wrapped->SetInitParams(riid, nodeMask, type);
wrapped->Reset(pCommandAllocator, pInitialState);
}
*ppCommandList = (ID3D12GraphicsCommandList *)wrapped;
@@ -297,6 +288,8 @@ HRESULT WrappedID3D12Device::CreateGraphicsPipelineState(const D3D12_GRAPHICS_PI
record->Length = 0;
wrapped->SetResourceRecord(record);
record->AddParent(GetRecord(pDesc->pRootSignature));
record->AddChunk(scope.Get());
}
@@ -361,6 +354,8 @@ HRESULT WrappedID3D12Device::CreateComputePipelineState(const D3D12_COMPUTE_PIPE
record->Length = 0;
wrapped->SetResourceRecord(record);
record->AddParent(GetRecord(pDesc->pRootSignature));
record->AddChunk(scope.Get());
}
+5 -5
View File
@@ -129,16 +129,16 @@ D3D12_CPU_DESCRIPTOR_HANDLE FromPortableHandle(D3D12ResourceManager *manager, Po
string ToStrHelper<false, PortableHandle>::Get(const PortableHandle &el)
{
return StringFormat::Fmt("D3D12_CPU_DESCRIPTOR_HANDLE %s[%u]", ToStr::Get(el.heap).c_str(),
if(el.heap == ResourceId())
return "NULL";
return StringFormat::Fmt("D3D12_CPU_DESCRIPTOR_HANDLE(%s, %u)", ToStr::Get(el.heap).c_str(),
el.index);
}
bool D3D12ResourceManager::SerialisableResource(ResourceId id, D3D12ResourceRecord *record)
{
if(id == m_Device->GetResourceID())
return true;
if(record->ignoreSerialise)
if(record->SpecialResource)
return false;
return true;
+27 -2
View File
@@ -197,6 +197,19 @@ class D3D12ResourceManager;
PortableHandle ToPortableHandle(D3D12_CPU_DESCRIPTOR_HANDLE handle);
D3D12_CPU_DESCRIPTOR_HANDLE FromPortableHandle(D3D12ResourceManager *manager, PortableHandle handle);
struct D3D12ResourceRecord;
struct CmdListRecordingInfo
{
vector<D3D12_RESOURCE_BARRIER> barriers;
// a list of all resources dirtied by this command buffer
set<ResourceId> dirtied;
// bundles executed
vector<D3D12ResourceRecord *> bundles;
};
struct D3D12ResourceRecord : public ResourceRecord
{
enum
@@ -204,8 +217,19 @@ struct D3D12ResourceRecord : public ResourceRecord
NullResource = NULL
};
D3D12ResourceRecord(ResourceId id) : ResourceRecord(id, true) { ignoreSerialise = false; }
D3D12ResourceRecord(ResourceId id) : ResourceRecord(id, true), cmdInfo(NULL), bakedCommands(NULL)
{
}
~D3D12ResourceRecord() {}
void Bake()
{
RDCASSERT(cmdInfo);
SwapChunks(bakedCommands);
cmdInfo->barriers.swap(bakedCommands->cmdInfo->barriers);
cmdInfo->dirtied.swap(bakedCommands->cmdInfo->dirtied);
cmdInfo->bundles.swap(bakedCommands->cmdInfo->bundles);
}
void Insert(map<int32_t, Chunk *> &recordlist)
{
bool dataWritten = DataWritten;
@@ -224,7 +248,8 @@ struct D3D12ResourceRecord : public ResourceRecord
recordlist.insert(m_Chunks.begin(), m_Chunks.end());
}
bool ignoreSerialise;
D3D12ResourceRecord *bakedCommands;
CmdListRecordingInfo *cmdInfo;
};
class D3D12ResourceManager