mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-07-09 01:00:51 +00:00
Add remaining parent and dependency tracking to serialise frame
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user