mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-13 13:30:44 +00:00
Factor out command record/partial replay into common place
* Both command lists and command queues need to be able to access this data so we expose it in a common place. * This gets command stepping partially working.
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/wrapped_pool.h"
|
||||
#include "d3d12_commands.h"
|
||||
#include "d3d12_common.h"
|
||||
#include "d3d12_device.h"
|
||||
#include "d3d12_resources.h"
|
||||
@@ -85,6 +86,9 @@ class WrappedID3D12GraphicsCommandList : public RefCounter12<ID3D12GraphicsComma
|
||||
{
|
||||
WrappedID3D12Device *m_pDevice;
|
||||
|
||||
// command recording/replay data shared between queues and lists
|
||||
D3D12CommandData *m_Cmd;
|
||||
|
||||
ResourceId m_ResourceID;
|
||||
D3D12ResourceRecord *m_ListRecord;
|
||||
|
||||
@@ -100,9 +104,6 @@ class WrappedID3D12GraphicsCommandList : public RefCounter12<ID3D12GraphicsComma
|
||||
D3D12_COMMAND_LIST_TYPE type;
|
||||
} m_Init;
|
||||
|
||||
void AddDrawcall(const FetchDrawcall &d, bool hasEvents);
|
||||
void AddEvent(D3D12ChunkType type, string description);
|
||||
|
||||
const char *GetChunkName(uint32_t idx) { return m_pDevice->GetChunkName(idx); }
|
||||
D3D12ResourceManager *GetResourceManager() { return m_pDevice->GetResourceManager(); }
|
||||
public:
|
||||
@@ -119,6 +120,7 @@ public:
|
||||
D3D12ResourceRecord *GetResourceRecord() { return m_ListRecord; }
|
||||
ID3D12GraphicsCommandList *GetList(ResourceId id);
|
||||
|
||||
void SetCommandData(D3D12CommandData *cmd) { m_Cmd = cmd; }
|
||||
void SetInitParams(REFIID riid, UINT nodeMask, D3D12_COMMAND_LIST_TYPE type)
|
||||
{
|
||||
m_Init.riid = riid;
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
******************************************************************************/
|
||||
|
||||
#include "d3d12_command_list.h"
|
||||
#include "d3d12_command_queue.h"
|
||||
|
||||
ID3D12GraphicsCommandList *WrappedID3D12GraphicsCommandList::GetList(ResourceId id)
|
||||
{
|
||||
@@ -33,8 +34,68 @@ bool WrappedID3D12GraphicsCommandList::Serialise_Close()
|
||||
{
|
||||
SERIALISE_ELEMENT(ResourceId, CommandList, GetResourceID());
|
||||
|
||||
if(m_State <= READING)
|
||||
GetList(CommandList)->Close();
|
||||
ResourceId bakedCmdId;
|
||||
|
||||
if(m_State >= WRITING)
|
||||
{
|
||||
D3D12ResourceRecord *record = GetResourceManager()->GetResourceRecord(CommandList);
|
||||
RDCASSERT(record->bakedCommands);
|
||||
if(record->bakedCommands)
|
||||
bakedCmdId = record->bakedCommands->GetResourceID();
|
||||
}
|
||||
|
||||
SERIALISE_ELEMENT(ResourceId, bakeId, bakedCmdId);
|
||||
|
||||
if(m_State < WRITING)
|
||||
m_Cmd->m_LastCmdListID = CommandList;
|
||||
|
||||
if(m_State == EXECUTING)
|
||||
{
|
||||
if(m_Cmd->ShouldRerecordCmd(CommandList))
|
||||
{
|
||||
ID3D12GraphicsCommandList *list = m_Cmd->RerecordCmdList(CommandList);
|
||||
#ifdef VERBOSE_PARTIAL_REPLAY
|
||||
RDCDEBUG("Ending partial command buffer for %llu baked to %llu", CommandList, bakeId);
|
||||
#endif
|
||||
|
||||
list->Close();
|
||||
|
||||
// erase the non-baked reference to this command list so that we don't have
|
||||
// duplicates when it comes time to clean up. See below in in Reset()
|
||||
m_Cmd->m_RerecordCmds.erase(CommandList);
|
||||
|
||||
if(m_Cmd->m_Partial[D3D12CommandData::Primary].partialParent == CommandList)
|
||||
m_Cmd->m_Partial[D3D12CommandData::Primary].partialParent = ResourceId();
|
||||
}
|
||||
|
||||
m_Cmd->m_BakedCmdListInfo[CommandList].curEventID = 0;
|
||||
}
|
||||
else if(m_State == READING)
|
||||
{
|
||||
ID3D12GraphicsCommandList *list = GetList(CommandList);
|
||||
|
||||
GetResourceManager()->RemoveReplacement(CommandList);
|
||||
|
||||
list->Close();
|
||||
|
||||
if(m_State == READING && !m_Cmd->m_BakedCmdListInfo[CommandList].curEvents.empty())
|
||||
{
|
||||
FetchDrawcall draw;
|
||||
draw.name = "API Calls";
|
||||
draw.flags |= eDraw_SetMarker;
|
||||
|
||||
m_Cmd->AddDrawcall(draw, true);
|
||||
|
||||
m_Cmd->m_BakedCmdListInfo[CommandList].curEventID++;
|
||||
}
|
||||
|
||||
{
|
||||
if(m_Cmd->GetDrawcallStack().size() > 1)
|
||||
m_Cmd->GetDrawcallStack().pop_back();
|
||||
}
|
||||
|
||||
m_Cmd->m_BakedCmdListInfo[bakeId].BakeFrom(m_Cmd->m_BakedCmdListInfo[CommandList]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -68,21 +129,128 @@ bool WrappedID3D12GraphicsCommandList::Serialise_Reset(ID3D12CommandAllocator *p
|
||||
SERIALISE_ELEMENT(ResourceId, Allocator, GetResID(pAllocator));
|
||||
SERIALISE_ELEMENT(ResourceId, State, GetResID(pInitialState));
|
||||
|
||||
if(m_State <= READING)
|
||||
ResourceId bakedCmdId;
|
||||
|
||||
if(m_State >= WRITING)
|
||||
{
|
||||
D3D12ResourceRecord *record = GetResourceManager()->GetResourceRecord(CommandList);
|
||||
RDCASSERT(record->bakedCommands);
|
||||
if(record->bakedCommands)
|
||||
bakedCmdId = record->bakedCommands->GetResourceID();
|
||||
}
|
||||
|
||||
SERIALISE_ELEMENT(ResourceId, bakeId, bakedCmdId);
|
||||
|
||||
if(m_State < WRITING)
|
||||
m_Cmd->m_LastCmdListID = CommandList;
|
||||
|
||||
if(m_State == EXECUTING)
|
||||
{
|
||||
const uint32_t length = m_Cmd->m_BakedCmdListInfo[bakeId].eventCount;
|
||||
|
||||
bool partial = false;
|
||||
int partialType = D3D12CommandData::ePartialNum;
|
||||
|
||||
// check for partial execution of this command buffer
|
||||
for(int p = 0; p < D3D12CommandData::ePartialNum; p++)
|
||||
{
|
||||
const vector<uint32_t> &baseEvents = m_Cmd->m_Partial[p].cmdListExecs[bakeId];
|
||||
|
||||
for(auto it = baseEvents.begin(); it != baseEvents.end(); ++it)
|
||||
{
|
||||
if(*it <= m_Cmd->m_LastEventID && m_Cmd->m_LastEventID < (*it + length))
|
||||
{
|
||||
#ifdef VERBOSE_PARTIAL_REPLAY
|
||||
RDCDEBUG("vkBegin - partial detected %u < %u < %u, %llu -> %llu", *it,
|
||||
m_Cmd->m_LastEventID, *it + length, CommandList, bakeId);
|
||||
#endif
|
||||
|
||||
m_Cmd->m_Partial[p].partialParent = CommandList;
|
||||
m_Cmd->m_Partial[p].baseEvent = *it;
|
||||
|
||||
partial = true;
|
||||
partialType = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
D3D12NOTIMP("m_DrawcallCallback");
|
||||
// const bool recordAllCmds = false; // m_DrawcallCallback &&
|
||||
// m_DrawcallCallback->RecordAllCmds()
|
||||
|
||||
if(partial) // || recordAllCmds
|
||||
{
|
||||
pAllocator = GetResourceManager()->GetLiveAs<ID3D12CommandAllocator>(Allocator);
|
||||
pInitialState =
|
||||
State == ResourceId() ? NULL : GetResourceManager()->GetLiveAs<ID3D12PipelineState>(State);
|
||||
|
||||
// pull all re-recorded commands from our own device and command pool for easier cleanup
|
||||
if(!partial)
|
||||
pAllocator = Unwrap(m_pDevice->GetAlloc());
|
||||
|
||||
ID3D12GraphicsCommandList *list = NULL;
|
||||
HRESULT hr = m_pDevice->CreateCommandList(nodeMask, type, pAllocator, pInitialState, riid,
|
||||
(void **)&list);
|
||||
|
||||
if(FAILED(hr))
|
||||
RDCERR("Failed on resource serialise-creation, hr: 0x%08x", hr);
|
||||
|
||||
if(partial)
|
||||
{
|
||||
m_Cmd->m_Partial[partialType].resultPartialCmdList = list;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we store under both baked and non baked ID.
|
||||
// The baked ID is the 'real' entry, the non baked is simply so it
|
||||
// can be found in the subsequent serialised commands that ref the
|
||||
// non-baked ID. The baked ID is referenced by the submit itself.
|
||||
//
|
||||
// In vkEndCommandBuffer we erase the non-baked reference, and since
|
||||
// we know you can only be recording a command buffer once at a time
|
||||
// (even if it's baked to several command buffers in the frame)
|
||||
// there's no issue with clashes here.
|
||||
m_Cmd->m_RerecordCmds[bakeId] = list;
|
||||
m_Cmd->m_RerecordCmds[CommandList] = list;
|
||||
}
|
||||
}
|
||||
|
||||
m_Cmd->m_BakedCmdListInfo[CommandList].curEventID = 0;
|
||||
}
|
||||
else if(m_State == READING)
|
||||
{
|
||||
pAllocator = GetResourceManager()->GetLiveAs<ID3D12CommandAllocator>(Allocator);
|
||||
pInitialState =
|
||||
State == ResourceId() ? NULL : GetResourceManager()->GetLiveAs<ID3D12PipelineState>(State);
|
||||
|
||||
if(m_State == READING && !GetResourceManager()->HasLiveResource(CommandList))
|
||||
if(!GetResourceManager()->HasLiveResource(bakeId))
|
||||
{
|
||||
ID3D12GraphicsCommandList *list = NULL;
|
||||
m_pDevice->CreateCommandList(nodeMask, type, pAllocator, pInitialState, riid, (void **)&list);
|
||||
|
||||
GetResourceManager()->AddLiveResource(CommandList, list);
|
||||
GetResourceManager()->AddLiveResource(bakeId, list);
|
||||
|
||||
// whenever a vkCmd command-building chunk asks for the command buffer, it
|
||||
// will get our baked version.
|
||||
GetResourceManager()->ReplaceResource(CommandList, bakeId);
|
||||
}
|
||||
else
|
||||
{
|
||||
GetList(CommandList)->Reset(Unwrap(pAllocator), Unwrap(pInitialState));
|
||||
}
|
||||
|
||||
{
|
||||
D3D12DrawcallTreeNode *draw = new D3D12DrawcallTreeNode;
|
||||
m_Cmd->m_BakedCmdListInfo[CommandList].draw = draw;
|
||||
|
||||
// On list execute we increment all child events/drawcalls by
|
||||
// m_RootEventID and insert them into the tree.
|
||||
m_Cmd->m_BakedCmdListInfo[CommandList].curEventID = 0;
|
||||
m_Cmd->m_BakedCmdListInfo[CommandList].eventCount = 0;
|
||||
m_Cmd->m_BakedCmdListInfo[CommandList].drawCount = 0;
|
||||
|
||||
m_Cmd->m_BakedCmdListInfo[CommandList].drawStack.push_back(draw);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -151,18 +319,43 @@ bool WrappedID3D12GraphicsCommandList::Serialise_DrawIndexedInstanced(UINT Index
|
||||
SERIALISE_ELEMENT(INT, startVtx, BaseVertexLocation);
|
||||
SERIALISE_ELEMENT(UINT, startInst, StartInstanceLocation);
|
||||
|
||||
if(m_State <= READING)
|
||||
if(m_State < WRITING)
|
||||
m_Cmd->m_LastCmdListID = CommandList;
|
||||
|
||||
D3D12NOTIMP("Serialise_DebugMessages");
|
||||
|
||||
if(m_State == EXECUTING)
|
||||
{
|
||||
if(m_Cmd->ShouldRerecordCmd(CommandList) && m_Cmd->InRerecordRange(CommandList))
|
||||
{
|
||||
ID3D12GraphicsCommandList *list = m_Cmd->RerecordCmdList(CommandList);
|
||||
|
||||
Unwrap(list)->DrawIndexedInstanced(idxCount, instCount, startIdx, startVtx, startInst);
|
||||
|
||||
D3D12NOTIMP("Drawcall callbacks");
|
||||
/*
|
||||
uint32_t eventID = HandlePreCallback(commandBuffer);
|
||||
|
||||
ObjDisp(commandBuffer)
|
||||
->CmdDrawIndexed(Unwrap(commandBuffer), idxCount, instCount, firstIdx, vtxOffs,
|
||||
firstInst);
|
||||
|
||||
if(eventID && m_DrawcallCallback->PostDraw(eventID, commandBuffer))
|
||||
{
|
||||
ObjDisp(commandBuffer)
|
||||
->CmdDrawIndexed(Unwrap(commandBuffer), idxCount, instCount, firstIdx, vtxOffs,
|
||||
firstInst);
|
||||
m_DrawcallCallback->PostRedraw(eventID, commandBuffer);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
else if(m_State == READING)
|
||||
{
|
||||
GetList(CommandList)->DrawIndexedInstanced(idxCount, instCount, startIdx, startVtx, startInst);
|
||||
}
|
||||
|
||||
const string desc = m_pSerialiser->GetDebugStr();
|
||||
const string desc = m_pSerialiser->GetDebugStr();
|
||||
|
||||
// TODO - Serialise_DebugMessages();
|
||||
|
||||
if(m_State == READING)
|
||||
{
|
||||
AddEvent(DRAW_INDEXED_INST, desc);
|
||||
m_Cmd->AddEvent(DRAW_INDEXED_INST, desc);
|
||||
string name =
|
||||
"DrawIndexedInstanced(" + ToStr::Get(idxCount) + ", " + ToStr::Get(instCount) + ")";
|
||||
|
||||
@@ -176,7 +369,7 @@ bool WrappedID3D12GraphicsCommandList::Serialise_DrawIndexedInstanced(UINT Index
|
||||
|
||||
draw.flags |= eDraw_Drawcall | eDraw_Instanced | eDraw_UseIBuffer;
|
||||
|
||||
AddDrawcall(draw, true);
|
||||
m_Cmd->AddDrawcall(draw, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -219,13 +412,58 @@ bool WrappedID3D12GraphicsCommandList::Serialise_CopyBufferRegion(ID3D12Resource
|
||||
SERIALISE_ELEMENT(UINT64, srcoffs, SrcOffset);
|
||||
SERIALISE_ELEMENT(UINT64, num, NumBytes);
|
||||
|
||||
if(m_State <= READING && GetResourceManager()->HasLiveResource(dst) &&
|
||||
GetResourceManager()->HasLiveResource(src))
|
||||
if(m_State < WRITING)
|
||||
m_Cmd->m_LastCmdListID = CommandList;
|
||||
|
||||
if(m_State == EXECUTING)
|
||||
{
|
||||
pDstBuffer = GetResourceManager()->GetLiveAs<ID3D12Resource>(dst);
|
||||
pSrcBuffer = GetResourceManager()->GetLiveAs<ID3D12Resource>(src);
|
||||
|
||||
GetList(CommandList)->CopyBufferRegion(Unwrap(pDstBuffer), dstoffs, Unwrap(pSrcBuffer), srcoffs, num);
|
||||
if(m_Cmd->ShouldRerecordCmd(CommandList) && m_Cmd->InRerecordRange(CommandList))
|
||||
{
|
||||
ID3D12GraphicsCommandList *list = m_Cmd->RerecordCmdList(CommandList);
|
||||
Unwrap(list)->CopyBufferRegion(Unwrap(pDstBuffer), dstoffs, Unwrap(pSrcBuffer), srcoffs, num);
|
||||
}
|
||||
}
|
||||
else if(m_State == READING)
|
||||
{
|
||||
ID3D12GraphicsCommandList *list = GetList(CommandList);
|
||||
pDstBuffer = GetResourceManager()->GetLiveAs<ID3D12Resource>(dst);
|
||||
pSrcBuffer = GetResourceManager()->GetLiveAs<ID3D12Resource>(src);
|
||||
|
||||
list->CopyBufferRegion(Unwrap(pDstBuffer), dstoffs, Unwrap(pSrcBuffer), srcoffs, num);
|
||||
|
||||
const string desc = m_pSerialiser->GetDebugStr();
|
||||
|
||||
{
|
||||
m_Cmd->AddEvent(COPY_BUFFER, desc);
|
||||
string name = "CopyBufferRegion(" + ToStr::Get(src) + "," + ToStr::Get(dst) + ")";
|
||||
|
||||
FetchDrawcall draw;
|
||||
draw.name = name;
|
||||
draw.flags |= eDraw_Copy;
|
||||
|
||||
draw.copySource = src;
|
||||
draw.copyDestination = dst;
|
||||
|
||||
m_Cmd->AddDrawcall(draw, true);
|
||||
|
||||
D3D12DrawcallTreeNode &drawNode = m_Cmd->GetDrawcallStack().back()->children.back();
|
||||
|
||||
if(src == dst)
|
||||
{
|
||||
drawNode.resourceUsage.push_back(
|
||||
std::make_pair(GetResID(pSrcBuffer), EventUsage(drawNode.draw.eventID, eUsage_Copy)));
|
||||
}
|
||||
else
|
||||
{
|
||||
drawNode.resourceUsage.push_back(std::make_pair(
|
||||
GetResID(pSrcBuffer), EventUsage(drawNode.draw.eventID, eUsage_CopySrc)));
|
||||
drawNode.resourceUsage.push_back(std::make_pair(
|
||||
GetResID(pDstBuffer), EventUsage(drawNode.draw.eventID, eUsage_CopyDst)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -292,8 +530,22 @@ bool WrappedID3D12GraphicsCommandList::Serialise_IASetPrimitiveTopology(
|
||||
SERIALISE_ELEMENT(ResourceId, CommandList, GetResourceID());
|
||||
SERIALISE_ELEMENT(D3D12_PRIMITIVE_TOPOLOGY, topo, PrimitiveTopology);
|
||||
|
||||
if(m_State <= READING)
|
||||
if(m_State < WRITING)
|
||||
m_Cmd->m_LastCmdListID = CommandList;
|
||||
|
||||
if(m_State == EXECUTING)
|
||||
{
|
||||
if(m_Cmd->ShouldRerecordCmd(CommandList) && m_Cmd->InRerecordRange(CommandList))
|
||||
{
|
||||
Unwrap(m_Cmd->RerecordCmdList(CommandList))->IASetPrimitiveTopology(topo);
|
||||
|
||||
// m_RenderState.topo = topo;
|
||||
}
|
||||
}
|
||||
else if(m_State == READING)
|
||||
{
|
||||
m_Cmd->m_BakedCmdListInfo[CommandList].state.topo = topo;
|
||||
|
||||
GetList(CommandList)->IASetPrimitiveTopology(topo);
|
||||
}
|
||||
|
||||
@@ -320,7 +572,24 @@ bool WrappedID3D12GraphicsCommandList::Serialise_RSSetViewports(UINT NumViewport
|
||||
SERIALISE_ELEMENT(UINT, num, NumViewports);
|
||||
SERIALISE_ELEMENT_ARR(D3D12_VIEWPORT, views, pViewports, num);
|
||||
|
||||
if(m_State <= READING)
|
||||
if(m_State < WRITING)
|
||||
m_Cmd->m_LastCmdListID = CommandList;
|
||||
|
||||
if(m_State == EXECUTING)
|
||||
{
|
||||
if(m_Cmd->ShouldRerecordCmd(CommandList) && m_Cmd->InRerecordRange(CommandList))
|
||||
{
|
||||
Unwrap(m_Cmd->RerecordCmdList(CommandList))->RSSetViewports(num, views);
|
||||
|
||||
/*
|
||||
if(m_RenderState.views.size() < first + count)
|
||||
m_RenderState.views.resize(first + count);
|
||||
|
||||
for(uint32_t i = 0; i < count; i++)
|
||||
m_RenderState.views[first + i] = views[i];*/
|
||||
}
|
||||
}
|
||||
else if(m_State == READING)
|
||||
{
|
||||
GetList(CommandList)->RSSetViewports(num, views);
|
||||
}
|
||||
@@ -351,7 +620,24 @@ bool WrappedID3D12GraphicsCommandList::Serialise_RSSetScissorRects(UINT NumRects
|
||||
SERIALISE_ELEMENT(UINT, num, NumRects);
|
||||
SERIALISE_ELEMENT_ARR(D3D12_RECT, rects, pRects, num);
|
||||
|
||||
if(m_State <= READING)
|
||||
if(m_State < WRITING)
|
||||
m_Cmd->m_LastCmdListID = CommandList;
|
||||
|
||||
if(m_State == EXECUTING)
|
||||
{
|
||||
if(m_Cmd->ShouldRerecordCmd(CommandList) && m_Cmd->InRerecordRange(CommandList))
|
||||
{
|
||||
Unwrap(m_Cmd->RerecordCmdList(CommandList))->RSSetScissorRects(num, rects);
|
||||
|
||||
/*
|
||||
if(m_RenderState.scissors.size() < first + count)
|
||||
m_RenderState.scissors.resize(first + count);
|
||||
|
||||
for(uint32_t i = 0; i < count; i++)
|
||||
m_RenderState.scissors[first + i] = scissors[i];*/
|
||||
}
|
||||
}
|
||||
else if(m_State == READING)
|
||||
{
|
||||
GetList(CommandList)->RSSetScissorRects(num, rects);
|
||||
}
|
||||
@@ -389,7 +675,20 @@ bool WrappedID3D12GraphicsCommandList::Serialise_SetPipelineState(ID3D12Pipeline
|
||||
SERIALISE_ELEMENT(ResourceId, CommandList, GetResourceID());
|
||||
SERIALISE_ELEMENT(ResourceId, pipe, GetResID(pPipelineState));
|
||||
|
||||
if(m_State <= READING)
|
||||
if(m_State < WRITING)
|
||||
m_Cmd->m_LastCmdListID = CommandList;
|
||||
|
||||
if(m_State == EXECUTING)
|
||||
{
|
||||
if(m_Cmd->ShouldRerecordCmd(CommandList) && m_Cmd->InRerecordRange(CommandList))
|
||||
{
|
||||
pPipelineState = GetResourceManager()->GetLiveAs<ID3D12PipelineState>(pipe);
|
||||
Unwrap(m_Cmd->RerecordCmdList(CommandList))->SetPipelineState(Unwrap(pPipelineState));
|
||||
|
||||
// m_RenderState.pipe = ;
|
||||
}
|
||||
}
|
||||
else if(m_State == READING)
|
||||
{
|
||||
pPipelineState = GetResourceManager()->GetLiveAs<ID3D12PipelineState>(pipe);
|
||||
GetList(CommandList)->SetPipelineState(Unwrap(pPipelineState));
|
||||
@@ -419,11 +718,94 @@ bool WrappedID3D12GraphicsCommandList::Serialise_ResourceBarrier(UINT NumBarrier
|
||||
SERIALISE_ELEMENT(UINT, num, NumBarriers);
|
||||
SERIALISE_ELEMENT_ARR(D3D12_RESOURCE_BARRIER, barriers, pBarriers, num);
|
||||
|
||||
if(m_State < WRITING)
|
||||
m_Cmd->m_LastCmdListID = CommandList;
|
||||
|
||||
if(m_State <= READING)
|
||||
{
|
||||
// TODO filter out any barriers for NULL resources
|
||||
GetList(CommandList)->ResourceBarrier(num, barriers);
|
||||
}
|
||||
if(m_State == EXECUTING)
|
||||
{
|
||||
if(m_Cmd->ShouldRerecordCmd(CommandList) && m_Cmd->InRerecordRange(CommandList))
|
||||
{
|
||||
ID3D12GraphicsCommandList *list = m_Cmd->RerecordCmdList(CommandList);
|
||||
Unwrap(list)->ResourceBarrier(num, barriers);
|
||||
|
||||
ResourceId cmd = GetResID(list);
|
||||
|
||||
// need to re-wrap the barriers
|
||||
for(UINT i = 0; i < num; i++)
|
||||
{
|
||||
D3D12_RESOURCE_BARRIER b = barriers[i];
|
||||
|
||||
switch(b.Type)
|
||||
{
|
||||
case D3D12_RESOURCE_BARRIER_TYPE_TRANSITION:
|
||||
{
|
||||
b.Transition.pResource =
|
||||
(ID3D12Resource *)GetResourceManager()->GetWrapper(b.Transition.pResource);
|
||||
break;
|
||||
}
|
||||
case D3D12_RESOURCE_BARRIER_TYPE_ALIASING:
|
||||
{
|
||||
b.Aliasing.pResourceBefore =
|
||||
(ID3D12Resource *)GetResourceManager()->GetWrapper(b.Aliasing.pResourceBefore);
|
||||
b.Aliasing.pResourceAfter =
|
||||
(ID3D12Resource *)GetResourceManager()->GetWrapper(b.Aliasing.pResourceAfter);
|
||||
break;
|
||||
}
|
||||
case D3D12_RESOURCE_BARRIER_TYPE_UAV:
|
||||
{
|
||||
b.UAV.pResource = (ID3D12Resource *)GetResourceManager()->GetWrapper(b.UAV.pResource);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_Cmd->m_BakedCmdListInfo[cmd].barriers.push_back(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(m_State == READING)
|
||||
{
|
||||
ID3D12GraphicsCommandList *list = GetList(CommandList);
|
||||
|
||||
list->ResourceBarrier(num, barriers);
|
||||
|
||||
ResourceId cmd = GetResID(list);
|
||||
|
||||
// need to re-wrap the barriers
|
||||
for(UINT i = 0; i < num; i++)
|
||||
{
|
||||
D3D12_RESOURCE_BARRIER b = barriers[i];
|
||||
|
||||
switch(b.Type)
|
||||
{
|
||||
case D3D12_RESOURCE_BARRIER_TYPE_TRANSITION:
|
||||
{
|
||||
b.Transition.pResource =
|
||||
(ID3D12Resource *)GetResourceManager()->GetWrapper(b.Transition.pResource);
|
||||
break;
|
||||
}
|
||||
case D3D12_RESOURCE_BARRIER_TYPE_ALIASING:
|
||||
{
|
||||
b.Aliasing.pResourceBefore =
|
||||
(ID3D12Resource *)GetResourceManager()->GetWrapper(b.Aliasing.pResourceBefore);
|
||||
b.Aliasing.pResourceAfter =
|
||||
(ID3D12Resource *)GetResourceManager()->GetWrapper(b.Aliasing.pResourceAfter);
|
||||
break;
|
||||
}
|
||||
case D3D12_RESOURCE_BARRIER_TYPE_UAV:
|
||||
{
|
||||
b.UAV.pResource = (ID3D12Resource *)GetResourceManager()->GetWrapper(b.UAV.pResource);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_Cmd->m_BakedCmdListInfo[cmd].barriers.push_back(b);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -487,9 +869,21 @@ bool WrappedID3D12GraphicsCommandList::Serialise_SetGraphicsRootSignature(
|
||||
SERIALISE_ELEMENT(ResourceId, CommandList, GetResourceID());
|
||||
SERIALISE_ELEMENT(ResourceId, sig, GetResID(pRootSignature));
|
||||
|
||||
if(m_State <= READING)
|
||||
if(m_State < WRITING)
|
||||
m_Cmd->m_LastCmdListID = CommandList;
|
||||
|
||||
if(m_State == EXECUTING)
|
||||
{
|
||||
if(m_Cmd->ShouldRerecordCmd(CommandList) && m_Cmd->InRerecordRange(CommandList))
|
||||
{
|
||||
pRootSignature = GetResourceManager()->GetLiveAs<ID3D12RootSignature>(sig);
|
||||
Unwrap(m_Cmd->RerecordCmdList(CommandList))->SetGraphicsRootSignature(Unwrap(pRootSignature));
|
||||
}
|
||||
}
|
||||
else if(m_State == READING)
|
||||
{
|
||||
pRootSignature = GetResourceManager()->GetLiveAs<ID3D12RootSignature>(sig);
|
||||
|
||||
GetList(CommandList)->SetGraphicsRootSignature(Unwrap(pRootSignature));
|
||||
}
|
||||
|
||||
@@ -574,7 +968,20 @@ bool WrappedID3D12GraphicsCommandList::Serialise_SetGraphicsRootConstantBufferVi
|
||||
SERIALISE_ELEMENT(ResourceId, buffer, id);
|
||||
SERIALISE_ELEMENT(UINT64, byteOffset, offs);
|
||||
|
||||
if(m_State <= READING)
|
||||
if(m_State < WRITING)
|
||||
m_Cmd->m_LastCmdListID = CommandList;
|
||||
|
||||
if(m_State == EXECUTING)
|
||||
{
|
||||
if(m_Cmd->ShouldRerecordCmd(CommandList) && m_Cmd->InRerecordRange(CommandList))
|
||||
{
|
||||
WrappedID3D12Resource *pRes = GetResourceManager()->GetLiveAs<WrappedID3D12Resource>(buffer);
|
||||
|
||||
Unwrap(m_Cmd->RerecordCmdList(CommandList))
|
||||
->SetGraphicsRootConstantBufferView(idx, pRes->GetGPUVirtualAddress() + byteOffset);
|
||||
}
|
||||
}
|
||||
else if(m_State == READING)
|
||||
{
|
||||
WrappedID3D12Resource *pRes = GetResourceManager()->GetLiveAs<WrappedID3D12Resource>(buffer);
|
||||
|
||||
@@ -634,12 +1041,54 @@ bool WrappedID3D12GraphicsCommandList::Serialise_IASetIndexBuffer(const D3D12_IN
|
||||
SERIALISE_ELEMENT(bool, HasView, pView != NULL);
|
||||
SERIALISE_ELEMENT_OPT(D3D12_INDEX_BUFFER_VIEW, view, *pView, HasView);
|
||||
|
||||
if(m_State <= READING)
|
||||
if(m_State < WRITING)
|
||||
m_Cmd->m_LastCmdListID = CommandList;
|
||||
|
||||
if(m_State == EXECUTING)
|
||||
{
|
||||
if(m_Cmd->ShouldRerecordCmd(CommandList) && m_Cmd->InRerecordRange(CommandList))
|
||||
{
|
||||
ID3D12GraphicsCommandList *list = m_Cmd->RerecordCmdList(CommandList);
|
||||
|
||||
if(HasView)
|
||||
{
|
||||
Unwrap(list)->IASetIndexBuffer(&view);
|
||||
|
||||
// WrappedID3D12Resource::GetResIDFromAddr(view.BufferLocation, m_RenderState.ibuffer.buf,
|
||||
// m_RenderState.ibuffer.offs);
|
||||
// m_RenderState.ibuffer.bytewidth = (view.Format == DXGI_FORMAT_R32_UINT ? 4 : 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
Unwrap(list)->IASetIndexBuffer(NULL);
|
||||
|
||||
// m_RenderState.ibuffer.buf = ResourceId();
|
||||
// m_RenderState.ibuffer.offs = 0;
|
||||
// m_RenderState.ibuffer.bytewidth = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(m_State == READING)
|
||||
{
|
||||
ID3D12GraphicsCommandList *list = GetList(CommandList);
|
||||
|
||||
if(HasView)
|
||||
GetList(CommandList)->IASetIndexBuffer(&view);
|
||||
{
|
||||
list->IASetIndexBuffer(&view);
|
||||
|
||||
UINT64 dummy = 0;
|
||||
WrappedID3D12Resource::GetResIDFromAddr(
|
||||
view.BufferLocation, m_Cmd->m_BakedCmdListInfo[CommandList].state.ibuffer, dummy);
|
||||
m_Cmd->m_BakedCmdListInfo[CommandList].state.idxWidth =
|
||||
(view.Format == DXGI_FORMAT_R32_UINT ? 4 : 2);
|
||||
}
|
||||
else
|
||||
GetList(CommandList)->IASetIndexBuffer(NULL);
|
||||
{
|
||||
list->IASetIndexBuffer(NULL);
|
||||
|
||||
m_Cmd->m_BakedCmdListInfo[CommandList].state.ibuffer = ResourceId();
|
||||
m_Cmd->m_BakedCmdListInfo[CommandList].state.idxWidth = 2;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -674,7 +1123,19 @@ bool WrappedID3D12GraphicsCommandList::Serialise_IASetVertexBuffers(
|
||||
SERIALISE_ELEMENT(UINT, num, NumViews);
|
||||
SERIALISE_ELEMENT_ARR(D3D12_VERTEX_BUFFER_VIEW, views, pViews, num);
|
||||
|
||||
if(m_State <= READING)
|
||||
if(m_State < WRITING)
|
||||
m_Cmd->m_LastCmdListID = CommandList;
|
||||
|
||||
if(m_State == EXECUTING)
|
||||
{
|
||||
if(m_Cmd->ShouldRerecordCmd(CommandList) && m_Cmd->InRerecordRange(CommandList))
|
||||
{
|
||||
Unwrap(m_Cmd->RerecordCmdList(CommandList))->IASetVertexBuffers(start, num, views);
|
||||
|
||||
// m_RenderState.vbuffers = ;
|
||||
}
|
||||
}
|
||||
else if(m_State == READING)
|
||||
{
|
||||
GetList(CommandList)->IASetVertexBuffers(start, num, views);
|
||||
}
|
||||
@@ -720,6 +1181,9 @@ bool WrappedID3D12GraphicsCommandList::Serialise_OMSetRenderTargets(
|
||||
SERIALISE_ELEMENT(UINT, num, NumRenderTargetDescriptors);
|
||||
SERIALISE_ELEMENT(bool, singlehandle, RTsSingleHandleToDescriptorRange != FALSE);
|
||||
|
||||
if(m_State < WRITING)
|
||||
m_Cmd->m_LastCmdListID = CommandList;
|
||||
|
||||
UINT numHandles = singlehandle ? 1U : num;
|
||||
|
||||
std::vector<PortableHandle> rts;
|
||||
@@ -739,7 +1203,25 @@ bool WrappedID3D12GraphicsCommandList::Serialise_OMSetRenderTargets(
|
||||
? ToPortableHandle(*pDepthStencilDescriptor)
|
||||
: PortableHandle(0));
|
||||
|
||||
if(m_State <= READING)
|
||||
if(m_State == EXECUTING)
|
||||
{
|
||||
if(m_Cmd->ShouldRerecordCmd(CommandList) && m_Cmd->InRerecordRange(CommandList))
|
||||
{
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = FromPortableHandle(GetResourceManager(), dsv);
|
||||
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE *rtHandles = new D3D12_CPU_DESCRIPTOR_HANDLE[numHandles];
|
||||
|
||||
for(UINT i = 0; i < numHandles; i++)
|
||||
rtHandles[i] = FromPortableHandle(GetResourceManager(), rts[i]);
|
||||
|
||||
Unwrap(m_Cmd->RerecordCmdList(CommandList))
|
||||
->OMSetRenderTargets(num, rtHandles, singlehandle ? TRUE : FALSE,
|
||||
dsv.heap != ResourceId() ? &dsvHandle : NULL);
|
||||
|
||||
SAFE_DELETE_ARRAY(rtHandles);
|
||||
}
|
||||
}
|
||||
else if(m_State == READING)
|
||||
{
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = FromPortableHandle(GetResourceManager(), dsv);
|
||||
|
||||
@@ -751,6 +1233,8 @@ bool WrappedID3D12GraphicsCommandList::Serialise_OMSetRenderTargets(
|
||||
GetList(CommandList)
|
||||
->OMSetRenderTargets(num, rtHandles, singlehandle ? TRUE : FALSE,
|
||||
dsv.heap != ResourceId() ? &dsvHandle : NULL);
|
||||
|
||||
SAFE_DELETE_ARRAY(rtHandles);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -811,6 +1295,9 @@ bool WrappedID3D12GraphicsCommandList::Serialise_ClearRenderTargetView(
|
||||
SERIALISE_ELEMENT(ResourceId, CommandList, GetResourceID());
|
||||
SERIALISE_ELEMENT(PortableHandle, rtv, ToPortableHandle(RenderTargetView));
|
||||
|
||||
if(m_State < WRITING)
|
||||
m_Cmd->m_LastCmdListID = CommandList;
|
||||
|
||||
float Color[4] = {0};
|
||||
|
||||
if(m_State >= WRITING)
|
||||
@@ -821,11 +1308,42 @@ bool WrappedID3D12GraphicsCommandList::Serialise_ClearRenderTargetView(
|
||||
SERIALISE_ELEMENT(UINT, num, NumRects);
|
||||
SERIALISE_ELEMENT_ARR(D3D12_RECT, rects, pRects, num);
|
||||
|
||||
if(m_State <= READING)
|
||||
if(m_State == EXECUTING)
|
||||
{
|
||||
RenderTargetView = FromPortableHandle(GetResourceManager(), rtv);
|
||||
|
||||
if(m_Cmd->ShouldRerecordCmd(CommandList) && m_Cmd->InRerecordRange(CommandList))
|
||||
{
|
||||
Unwrap(m_Cmd->RerecordCmdList(CommandList))
|
||||
->ClearRenderTargetView(RenderTargetView, Color, num, rects);
|
||||
}
|
||||
}
|
||||
else if(m_State == READING)
|
||||
{
|
||||
RenderTargetView = FromPortableHandle(GetResourceManager(), rtv);
|
||||
|
||||
GetList(CommandList)->ClearRenderTargetView(RenderTargetView, Color, num, rects);
|
||||
|
||||
const string desc = m_pSerialiser->GetDebugStr();
|
||||
|
||||
{
|
||||
m_Cmd->AddEvent(CLEAR_RTV, desc);
|
||||
string name = "ClearRenderTargetView(" + ToStr::Get(Color[0]) + "," + ToStr::Get(Color[1]) +
|
||||
"," + ToStr::Get(Color[2]) + "," + ToStr::Get(Color[3]) + ")";
|
||||
|
||||
FetchDrawcall draw;
|
||||
draw.name = name;
|
||||
draw.flags |= eDraw_Clear | eDraw_ClearColour;
|
||||
|
||||
m_Cmd->AddDrawcall(draw, true);
|
||||
|
||||
D3D12NOTIMP("Getting image for RTV to mark usage");
|
||||
|
||||
// D3D12DrawcallTreeNode &drawNode = m_Cmd->GetDrawcallStack().back()->children.back();
|
||||
|
||||
// drawNode.resourceUsage.push_back(
|
||||
// std::make_pair(GetResID(image), EventUsage(drawNode.draw.eventID, eUsage_Clear)));
|
||||
}
|
||||
}
|
||||
|
||||
SAFE_DELETE_ARRAY(rects);
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include <list>
|
||||
#include "common/wrapped_pool.h"
|
||||
#include "d3d12_commands.h"
|
||||
#include "d3d12_common.h"
|
||||
#include "d3d12_device.h"
|
||||
#include "d3d12_resources.h"
|
||||
@@ -67,44 +68,14 @@ struct DummyID3D12DebugCommandQueue : public ID3D12DebugCommandQueue
|
||||
}
|
||||
};
|
||||
|
||||
struct D3D12DrawcallTreeNode
|
||||
{
|
||||
D3D12DrawcallTreeNode() {}
|
||||
explicit D3D12DrawcallTreeNode(const FetchDrawcall &d) : draw(d) {}
|
||||
FetchDrawcall draw;
|
||||
vector<D3D12DrawcallTreeNode> children;
|
||||
|
||||
vector<pair<ResourceId, EventUsage> > resourceUsage;
|
||||
|
||||
D3D12DrawcallTreeNode &operator=(const FetchDrawcall &d)
|
||||
{
|
||||
*this = D3D12DrawcallTreeNode(d);
|
||||
return *this;
|
||||
}
|
||||
|
||||
vector<FetchDrawcall> Bake()
|
||||
{
|
||||
vector<FetchDrawcall> ret;
|
||||
if(children.empty())
|
||||
return ret;
|
||||
|
||||
ret.resize(children.size());
|
||||
for(size_t i = 0; i < children.size(); i++)
|
||||
{
|
||||
ret[i] = children[i].draw;
|
||||
ret[i].children = children[i].Bake();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
class WrappedID3D12GraphicsCommandList;
|
||||
|
||||
class WrappedID3D12CommandQueue : public ID3D12CommandQueue,
|
||||
public RefCounter12<ID3D12CommandQueue>,
|
||||
public ID3DDevice
|
||||
{
|
||||
friend class WrappedID3D12GraphicsCommandList;
|
||||
|
||||
WrappedID3D12Device *m_pDevice;
|
||||
|
||||
WrappedID3D12GraphicsCommandList *m_ReplayList;
|
||||
@@ -119,136 +90,11 @@ class WrappedID3D12CommandQueue : public ID3D12CommandQueue,
|
||||
|
||||
vector<D3D12ResourceRecord *> m_CmdListRecords;
|
||||
|
||||
vector<FetchAPIEvent> m_RootEvents, m_Events;
|
||||
bool m_AddedDrawcall;
|
||||
|
||||
uint64_t m_CurChunkOffset;
|
||||
uint32_t m_RootEventID, m_RootDrawcallID;
|
||||
uint32_t m_FirstEventID, m_LastEventID;
|
||||
|
||||
D3D12DrawcallTreeNode m_ParentDrawcall;
|
||||
// command recording/replay data shared between queues and lists
|
||||
D3D12CommandData m_Cmd;
|
||||
|
||||
ResourceId m_BackbufferID;
|
||||
|
||||
void InsertDrawsAndRefreshIDs(vector<D3D12DrawcallTreeNode> &cmdBufNodes, uint32_t baseEventID,
|
||||
uint32_t baseDrawID);
|
||||
|
||||
struct BakedCmdListInfo
|
||||
{
|
||||
vector<FetchAPIEvent> curEvents;
|
||||
vector<DebugMessage> debugMessages;
|
||||
std::list<D3D12DrawcallTreeNode *> drawStack;
|
||||
|
||||
vector<pair<ResourceId, EventUsage> > resourceUsage;
|
||||
|
||||
struct CmdListState
|
||||
{
|
||||
ResourceId pipeline;
|
||||
|
||||
uint32_t idxWidth;
|
||||
ResourceId ibuffer;
|
||||
vector<ResourceId> vbuffers;
|
||||
|
||||
ResourceId rts[8];
|
||||
ResourceId dsv;
|
||||
} state;
|
||||
|
||||
vector<D3D12_RESOURCE_BARRIER> barriers;
|
||||
|
||||
D3D12DrawcallTreeNode *draw; // the root draw to copy from when submitting
|
||||
uint32_t eventCount; // how many events are in this cmd list, for quick skipping
|
||||
uint32_t curEventID; // current event ID while reading or executing
|
||||
uint32_t drawCount; // similar to above
|
||||
};
|
||||
map<ResourceId, BakedCmdListInfo> m_BakedCmdListInfo;
|
||||
|
||||
// on replay, the current command list for the last chunk we
|
||||
// handled.
|
||||
ResourceId m_LastCmdListID;
|
||||
int m_CmdListsInProgress;
|
||||
|
||||
// this is a list of uint64_t file offset -> uint32_t EIDs of where each
|
||||
// drawcall is used. E.g. the drawcall at offset 873954 is EID 50. If a
|
||||
// command list is executed more than once, there may be more than
|
||||
// one entry here - the drawcall will be aliased among several EIDs, with
|
||||
// the first one being the 'primary'
|
||||
struct DrawcallUse
|
||||
{
|
||||
DrawcallUse(uint64_t offs, uint32_t eid) : fileOffset(offs), eventID(eid) {}
|
||||
uint64_t fileOffset;
|
||||
uint32_t eventID;
|
||||
bool operator<(const DrawcallUse &o) const
|
||||
{
|
||||
if(fileOffset != o.fileOffset)
|
||||
return fileOffset < o.fileOffset;
|
||||
return eventID < o.eventID;
|
||||
}
|
||||
};
|
||||
vector<DrawcallUse> m_DrawcallUses;
|
||||
|
||||
struct PartialReplayData
|
||||
{
|
||||
// if we're doing a partial replay, by definition only one command
|
||||
// list will be partial at any one time. While replaying through
|
||||
// the command list chunks, the partial command list will be
|
||||
// created as a temporary new command list and when it comes to
|
||||
// the queue that should execute it, it can execute this instead.
|
||||
ID3D12CommandAllocator *resultPartialCmdAllocator;
|
||||
ID3D12GraphicsCommandList *resultPartialCmdList;
|
||||
|
||||
// if we're replaying just a single draw or a particular command
|
||||
// list subsection of command events, we don't go through the
|
||||
// whole original command lists to set up the partial replay,
|
||||
// so we just set this command list
|
||||
ID3D12GraphicsCommandList *outsideCmdList;
|
||||
|
||||
// this records where in the frame a command list was executed,
|
||||
// so that we know if our replay range ends in one of these ranges
|
||||
// we need to construct a partial command list for future
|
||||
// replaying. Note that we always have the complete command list
|
||||
// around - it's the bakeID itself.
|
||||
// Since we only ever record a bakeID once the key is unique - note
|
||||
// that the same command list could be reset multiple times
|
||||
// a frame, so the parent command list ID (the one recorded in
|
||||
// CmdList chunks) is NOT unique.
|
||||
// However, a single baked command list can be executed multiple
|
||||
// times - so we have to have a list of base events
|
||||
// Map from bakeID -> vector<baseEventID>
|
||||
map<ResourceId, vector<uint32_t> > cmdListExecs;
|
||||
|
||||
// This is just the ResourceId of the original parent command list
|
||||
// and it's baked id.
|
||||
// If we are in the middle of a partial replay - allows fast checking
|
||||
// in all CmdList chunks, with the iteration through the above list
|
||||
// only in Reset.
|
||||
// partialParent gets reset to ResourceId() in the Close so that
|
||||
// other baked command lists from the same parent don't pick it up
|
||||
// Also reset each overall replay
|
||||
ResourceId partialParent;
|
||||
|
||||
// If a partial replay is detected, this records the base of the
|
||||
// range. This both allows easily and uniquely identifying it in the
|
||||
// executecmdlists, but also allows the recording to 'rebase' the
|
||||
// last event ID by subtracting this, to know how far to record
|
||||
uint32_t baseEvent;
|
||||
} m_PartialReplayData;
|
||||
|
||||
map<ResourceId, ID3D12GraphicsCommandList *> m_RerecordCmds;
|
||||
|
||||
std::list<D3D12DrawcallTreeNode *> m_DrawcallStack;
|
||||
|
||||
std::list<D3D12DrawcallTreeNode *> &GetDrawcallStack()
|
||||
{
|
||||
if(m_LastCmdListID != ResourceId())
|
||||
return m_BakedCmdListInfo[m_LastCmdListID].drawStack;
|
||||
|
||||
return m_DrawcallStack;
|
||||
}
|
||||
|
||||
bool ShouldRerecordCmd(ResourceId cmdid);
|
||||
bool InRerecordRange(ResourceId cmdid);
|
||||
ID3D12GraphicsCommandList *RerecordCmdList(ResourceId cmdid);
|
||||
|
||||
void ProcessChunk(uint64_t offset, D3D12ChunkType context);
|
||||
|
||||
const char *GetChunkName(uint32_t idx) { return m_pDevice->GetChunkName(idx); }
|
||||
@@ -267,17 +113,16 @@ public:
|
||||
D3D12ResourceRecord *GetResourceRecord() { return m_QueueRecord; }
|
||||
WrappedID3D12Device *GetWrappedDevice() { return m_pDevice; }
|
||||
const vector<D3D12ResourceRecord *> &GetCmdLists() { return m_CmdListRecords; }
|
||||
D3D12DrawcallTreeNode &GetParentDrawcall() { return m_ParentDrawcall; }
|
||||
D3D12DrawcallTreeNode &GetParentDrawcall() { return m_Cmd.m_ParentDrawcall; }
|
||||
FetchAPIEvent GetEvent(uint32_t eventID);
|
||||
uint32_t GetMaxEID() { return m_Events.back().eventID; }
|
||||
uint32_t GetMaxEID() { return m_Cmd.m_Events.back().eventID; }
|
||||
ResourceId GetBackbufferResourceID() { return m_BackbufferID; }
|
||||
void ClearAfterCapture();
|
||||
|
||||
void AddDrawcall(const FetchDrawcall &d, bool hasEvents);
|
||||
void AddEvent(D3D12ChunkType type, string description);
|
||||
|
||||
void ReplayLog(LogState readType, uint32_t startEventID, uint32_t endEventID, bool partial);
|
||||
|
||||
D3D12CommandData *GetCommandData() { return &m_Cmd; }
|
||||
vector<EventUsage> GetUsage(ResourceId id) { return m_Cmd.m_ResourceUses[id]; }
|
||||
// interface for DXGI
|
||||
virtual IUnknown *GetRealIUnknown() { return GetReal(); }
|
||||
virtual IID GetBackbufferUUID() { return __uuidof(ID3D12Resource); }
|
||||
|
||||
@@ -50,29 +50,243 @@ void STDMETHODCALLTYPE WrappedID3D12CommandQueue::CopyTileMappings(
|
||||
bool WrappedID3D12CommandQueue::Serialise_ExecuteCommandLists(UINT NumCommandLists,
|
||||
ID3D12CommandList *const *ppCommandLists)
|
||||
{
|
||||
SERIALISE_ELEMENT(UINT, num, NumCommandLists);
|
||||
SERIALISE_ELEMENT(UINT, numCmds, NumCommandLists);
|
||||
|
||||
std::vector<ResourceId> ids;
|
||||
vector<ResourceId> cmdIds;
|
||||
ID3D12CommandList **cmds = m_State >= WRITING ? NULL : new ID3D12CommandList *[numCmds];
|
||||
|
||||
if(m_State >= WRITING)
|
||||
{
|
||||
ids.reserve(num);
|
||||
for(UINT i = 0; i < num; i++)
|
||||
ids.push_back(GetResID(ppCommandLists[i]));
|
||||
for(UINT i = 0; i < numCmds; i++)
|
||||
{
|
||||
D3D12ResourceRecord *record = GetRecord(ppCommandLists[i]);
|
||||
RDCASSERT(record->bakedCommands);
|
||||
if(record->bakedCommands)
|
||||
cmdIds.push_back(record->bakedCommands->GetResourceID());
|
||||
}
|
||||
}
|
||||
|
||||
m_pSerialiser->Serialise("ppCommandLists", ids);
|
||||
m_pSerialiser->Serialise("ppCommandLists", cmdIds);
|
||||
|
||||
if(m_State <= EXECUTING)
|
||||
if(m_State < WRITING)
|
||||
{
|
||||
std::vector<ID3D12CommandList *> unwrappedLists;
|
||||
unwrappedLists.reserve(num);
|
||||
for(UINT i = 0; i < num; i++)
|
||||
unwrappedLists.push_back(Unwrap(GetResourceManager()->GetLiveAs<ID3D12CommandList>(ids[i])));
|
||||
|
||||
m_pReal->ExecuteCommandLists(num, &unwrappedLists[0]);
|
||||
for(UINT i = 0; i < numCmds; i++)
|
||||
{
|
||||
cmds[i] = cmdIds[i] != ResourceId()
|
||||
? Unwrap(GetResourceManager()->GetLiveAs<ID3D12CommandList>(cmdIds[i]))
|
||||
: NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const string desc = m_pSerialiser->GetDebugStr();
|
||||
|
||||
D3D12NOTIMP("Serialise_DebugMessages");
|
||||
|
||||
if(m_State == READING)
|
||||
{
|
||||
m_pReal->ExecuteCommandLists(numCmds, cmds);
|
||||
|
||||
for(uint32_t i = 0; i < numCmds; i++)
|
||||
{
|
||||
ResourceId cmd = GetResourceManager()->GetLiveID(cmdIds[i]);
|
||||
m_pDevice->ApplyBarriers(m_Cmd.m_BakedCmdListInfo[cmd].barriers);
|
||||
}
|
||||
|
||||
m_Cmd.AddEvent(EXECUTE_CMD_LISTS, desc);
|
||||
|
||||
// we're adding multiple events, need to increment ourselves
|
||||
m_Cmd.m_RootEventID++;
|
||||
|
||||
string basename = "ExecuteCommandLists(" + ToStr::Get(numCmds) + ")";
|
||||
|
||||
for(uint32_t c = 0; c < numCmds; c++)
|
||||
{
|
||||
string name = StringFormat::Fmt("=> %s[%u]: ID3D12CommandList(%s)", basename.c_str(), c,
|
||||
ToStr::Get(cmdIds[c]).c_str());
|
||||
|
||||
// add a fake marker
|
||||
FetchDrawcall draw;
|
||||
draw.name = name;
|
||||
draw.flags |= eDraw_SetMarker;
|
||||
m_Cmd.AddEvent(SET_MARKER, name);
|
||||
m_Cmd.AddDrawcall(draw, true);
|
||||
m_Cmd.m_RootEventID++;
|
||||
|
||||
BakedCmdListInfo &cmdBufInfo = m_Cmd.m_BakedCmdListInfo[cmdIds[c]];
|
||||
|
||||
// insert the baked command buffer in-line into this list of notes, assigning new event and
|
||||
// drawIDs
|
||||
m_Cmd.InsertDrawsAndRefreshIDs(cmdBufInfo.draw->children);
|
||||
|
||||
for(size_t e = 0; e < cmdBufInfo.draw->executedCmds.size(); e++)
|
||||
{
|
||||
vector<uint32_t> &submits =
|
||||
m_Cmd.m_Partial[D3D12CommandData::Secondary].cmdListExecs[cmdBufInfo.draw->executedCmds[e]];
|
||||
|
||||
for(size_t s = 0; s < submits.size(); s++)
|
||||
submits[s] += m_Cmd.m_RootEventID;
|
||||
}
|
||||
|
||||
D3D12NOTIMP("Debug Messages");
|
||||
/*
|
||||
for(size_t i = 0; i < cmdBufInfo.debugMessages.size(); i++)
|
||||
{
|
||||
m_DebugMessages.push_back(cmdBufInfo.debugMessages[i]);
|
||||
m_DebugMessages.back().eventID += m_RootEventID;
|
||||
}
|
||||
*/
|
||||
|
||||
// only primary command buffers can be submitted
|
||||
m_Cmd.m_Partial[D3D12CommandData::Primary].cmdListExecs[cmdIds[c]].push_back(
|
||||
m_Cmd.m_RootEventID);
|
||||
|
||||
m_Cmd.m_RootEventID += cmdBufInfo.eventCount;
|
||||
m_Cmd.m_RootDrawcallID += cmdBufInfo.drawCount;
|
||||
|
||||
name = StringFormat::Fmt("=> %s[%u]: Close(%s)", basename.c_str(), c,
|
||||
ToStr::Get(cmdIds[c]).c_str());
|
||||
draw.name = name;
|
||||
m_Cmd.AddEvent(SET_MARKER, name);
|
||||
m_Cmd.AddDrawcall(draw, true);
|
||||
m_Cmd.m_RootEventID++;
|
||||
}
|
||||
|
||||
// account for the outer loop thinking we've added one event and incrementing,
|
||||
// since we've done all the handling ourselves this will be off by one.
|
||||
m_Cmd.m_RootEventID--;
|
||||
}
|
||||
else if(m_State == EXECUTING)
|
||||
{
|
||||
// account for the queue submit event
|
||||
m_Cmd.m_RootEventID++;
|
||||
|
||||
uint32_t startEID = m_Cmd.m_RootEventID;
|
||||
|
||||
// advance m_CurEventID to match the events added when reading
|
||||
for(uint32_t c = 0; c < numCmds; c++)
|
||||
{
|
||||
// 2 extra for the virtual labels around the command buffer
|
||||
m_Cmd.m_RootEventID += 2 + m_Cmd.m_BakedCmdListInfo[cmdIds[c]].eventCount;
|
||||
m_Cmd.m_RootDrawcallID += 2 + m_Cmd.m_BakedCmdListInfo[cmdIds[c]].drawCount;
|
||||
}
|
||||
|
||||
// same accounting for the outer loop as above
|
||||
m_Cmd.m_RootEventID--;
|
||||
|
||||
D3D12NOTIMP("m_DrawcallCallback");
|
||||
|
||||
if(numCmds == 0)
|
||||
{
|
||||
// do nothing, don't bother with the logic below
|
||||
}
|
||||
else if(m_Cmd.m_LastEventID <= startEID)
|
||||
{
|
||||
#ifdef VERBOSE_PARTIAL_REPLAY
|
||||
RDCDEBUG("Queue Submit no replay %u == %u", m_Cmd.m_LastEventID, startEID);
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
else if(m_DrawcallCallback && m_DrawcallCallback->RecordAllCmds())
|
||||
{
|
||||
#ifdef VERBOSE_PARTIAL_REPLAY
|
||||
RDCDEBUG("Queue Submit re-recording from %u", m_RootEventID);
|
||||
#endif
|
||||
|
||||
vector<ID3D12CommandList *> rerecordedCmds;
|
||||
|
||||
for(uint32_t c = 0; c < numCmds; c++)
|
||||
{
|
||||
ID3D12CommandList *cmd = RerecordCmdBuf(cmdIds[c]);
|
||||
ResourceId rerecord = GetResID(cmd);
|
||||
#ifdef VERBOSE_PARTIAL_REPLAY
|
||||
RDCDEBUG("Queue Submit fully re-recorded replay of %llu, using %llu", cmdIds[c], rerecord);
|
||||
#endif
|
||||
rerecordedCmds.push_back(Unwrap(cmd));
|
||||
|
||||
m_pDevice->ApplyBarriers(m_BakedCmdBufferInfo[rerecord].imgbarriers);
|
||||
}
|
||||
|
||||
m_pReal->ExecuteCommandLists((UINT)rerecordedCmds.size(), &rerecordedCmds[0]);
|
||||
}
|
||||
*/
|
||||
else if(m_Cmd.m_LastEventID > startEID && m_Cmd.m_LastEventID < m_Cmd.m_RootEventID)
|
||||
{
|
||||
#ifdef VERBOSE_PARTIAL_REPLAY
|
||||
RDCDEBUG("Queue Submit partial replay %u < %u", m_Cmd.m_LastEventID, m_Cmd.m_RootEventID);
|
||||
#endif
|
||||
|
||||
uint32_t eid = startEID;
|
||||
|
||||
vector<ResourceId> trimmedCmdIds;
|
||||
vector<ID3D12CommandList *> trimmedCmds;
|
||||
|
||||
for(uint32_t c = 0; c < numCmds; c++)
|
||||
{
|
||||
// account for the virtual vkBeginCommandBuffer label at the start of the events here
|
||||
// so it matches up to baseEvent
|
||||
eid++;
|
||||
|
||||
uint32_t end = eid + m_Cmd.m_BakedCmdListInfo[cmdIds[c]].eventCount;
|
||||
|
||||
if(eid == m_Cmd.m_Partial[D3D12CommandData::Primary].baseEvent)
|
||||
{
|
||||
ID3D12GraphicsCommandList *list =
|
||||
m_Cmd.RerecordCmdList(cmdIds[c], D3D12CommandData::Primary);
|
||||
ResourceId partial = GetResID(list);
|
||||
#ifdef VERBOSE_PARTIAL_REPLAY
|
||||
RDCDEBUG("Queue Submit partial replay of %llu at %u, using %llu", cmdIds[c], eid, partial);
|
||||
#endif
|
||||
trimmedCmdIds.push_back(partial);
|
||||
trimmedCmds.push_back(Unwrap(list));
|
||||
}
|
||||
else if(m_Cmd.m_LastEventID >= end)
|
||||
{
|
||||
#ifdef VERBOSE_PARTIAL_REPLAY
|
||||
RDCDEBUG("Queue Submit full replay %llu", cmdIds[c]);
|
||||
#endif
|
||||
trimmedCmdIds.push_back(cmdIds[c]);
|
||||
trimmedCmds.push_back(Unwrap(GetResourceManager()->GetLiveAs<ID3D12CommandList>(cmdIds[c])));
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef VERBOSE_PARTIAL_REPLAY
|
||||
RDCDEBUG("Queue not submitting %llu", cmdIds[c]);
|
||||
#endif
|
||||
}
|
||||
|
||||
// 1 extra to account for the virtual end command buffer label (begin is accounted for
|
||||
// above)
|
||||
eid += 1 + m_Cmd.m_BakedCmdListInfo[cmdIds[c]].eventCount;
|
||||
}
|
||||
|
||||
RDCASSERT(trimmedCmds.size() > 0);
|
||||
|
||||
m_pReal->ExecuteCommandLists((UINT)trimmedCmds.size(), &trimmedCmds[0]);
|
||||
|
||||
for(uint32_t i = 0; i < trimmedCmdIds.size(); i++)
|
||||
{
|
||||
ResourceId cmd = trimmedCmdIds[i];
|
||||
m_pDevice->ApplyBarriers(m_Cmd.m_BakedCmdListInfo[cmd].barriers);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef VERBOSE_PARTIAL_REPLAY
|
||||
RDCDEBUG("Queue Submit full replay %u >= %u", m_Cmd.m_LastEventID, m_Cmd.m_RootEventID);
|
||||
#endif
|
||||
|
||||
m_pReal->ExecuteCommandLists(numCmds, cmds);
|
||||
|
||||
for(uint32_t i = 0; i < numCmds; i++)
|
||||
{
|
||||
ResourceId cmd = GetResourceManager()->GetLiveID(cmdIds[i]);
|
||||
m_pDevice->ApplyBarriers(m_Cmd.m_BakedCmdListInfo[cmd].barriers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SAFE_DELETE_ARRAY(cmds);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -150,6 +150,8 @@ WrappedID3D12CommandQueue::WrappedID3D12CommandQueue(ID3D12CommandQueue *real,
|
||||
m_pSerialiser = serialiser;
|
||||
|
||||
m_ReplayList = new WrappedID3D12GraphicsCommandList(NULL, m_pDevice, m_pSerialiser, state);
|
||||
|
||||
m_ReplayList->SetCommandData(&m_Cmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -165,19 +167,7 @@ WrappedID3D12CommandQueue::WrappedID3D12CommandQueue(ID3D12CommandQueue *real,
|
||||
|
||||
m_QueueRecord = NULL;
|
||||
|
||||
m_RootEventID = 1;
|
||||
m_RootDrawcallID = 1;
|
||||
m_FirstEventID = 0;
|
||||
m_LastEventID = ~0U;
|
||||
|
||||
m_LastCmdListID = ResourceId();
|
||||
|
||||
m_PartialReplayData.resultPartialCmdList = NULL;
|
||||
m_PartialReplayData.outsideCmdList = NULL;
|
||||
m_PartialReplayData.partialParent = ResourceId();
|
||||
m_PartialReplayData.baseEvent = 0;
|
||||
|
||||
m_DrawcallStack.push_back(&m_ParentDrawcall);
|
||||
m_Cmd.m_pSerialiser = m_pSerialiser;
|
||||
|
||||
if(!RenderDoc::Inst().IsReplayApp())
|
||||
{
|
||||
@@ -247,20 +237,19 @@ void WrappedID3D12CommandQueue::ClearAfterCapture()
|
||||
|
||||
FetchAPIEvent WrappedID3D12CommandQueue::GetEvent(uint32_t eventID)
|
||||
{
|
||||
for(size_t i = m_Events.size() - 1; i > 0; i--)
|
||||
for(size_t i = m_Cmd.m_Events.size() - 1; i > 0; i--)
|
||||
{
|
||||
if(m_Events[i].eventID <= eventID)
|
||||
return m_Events[i];
|
||||
if(m_Cmd.m_Events[i].eventID <= eventID)
|
||||
return m_Cmd.m_Events[i];
|
||||
}
|
||||
|
||||
return m_Events[0];
|
||||
return m_Cmd.m_Events[0];
|
||||
}
|
||||
|
||||
void WrappedID3D12CommandQueue::ProcessChunk(uint64_t offset, D3D12ChunkType chunk)
|
||||
{
|
||||
m_CurChunkOffset = offset;
|
||||
|
||||
m_AddedDrawcall = false;
|
||||
m_Cmd.m_CurChunkOffset = offset;
|
||||
m_Cmd.m_AddedDrawcall = false;
|
||||
|
||||
switch(chunk)
|
||||
{
|
||||
@@ -316,7 +305,7 @@ void WrappedID3D12CommandQueue::ProcessChunk(uint64_t offset, D3D12ChunkType chu
|
||||
|
||||
if(m_State == READING)
|
||||
{
|
||||
AddEvent(CONTEXT_CAPTURE_FOOTER, "Present()");
|
||||
m_Cmd.AddEvent(CONTEXT_CAPTURE_FOOTER, "Present()");
|
||||
|
||||
FetchDrawcall draw;
|
||||
draw.name = "Present()";
|
||||
@@ -324,7 +313,7 @@ void WrappedID3D12CommandQueue::ProcessChunk(uint64_t offset, D3D12ChunkType chu
|
||||
|
||||
draw.copyDestination = bbid;
|
||||
|
||||
AddDrawcall(draw, true);
|
||||
m_Cmd.AddDrawcall(draw, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -351,11 +340,11 @@ void WrappedID3D12CommandQueue::ProcessChunk(uint64_t offset, D3D12ChunkType chu
|
||||
}
|
||||
else if(m_State == READING)
|
||||
{
|
||||
if(!m_AddedDrawcall)
|
||||
AddEvent(chunk, m_pSerialiser->GetDebugStr());
|
||||
if(!m_Cmd.m_AddedDrawcall)
|
||||
m_Cmd.AddEvent(chunk, m_pSerialiser->GetDebugStr());
|
||||
}
|
||||
|
||||
m_AddedDrawcall = false;
|
||||
m_Cmd.m_AddedDrawcall = false;
|
||||
}
|
||||
|
||||
void WrappedID3D12CommandQueue::ReplayLog(LogState readType, uint32_t startEventID,
|
||||
@@ -373,12 +362,12 @@ void WrappedID3D12CommandQueue::ReplayLog(LogState readType, uint32_t startEvent
|
||||
|
||||
m_pSerialiser->PopContext(header);
|
||||
|
||||
m_RootEvents.clear();
|
||||
m_Cmd.m_RootEvents.clear();
|
||||
|
||||
if(m_State == EXECUTING)
|
||||
{
|
||||
FetchAPIEvent ev = GetEvent(startEventID);
|
||||
m_RootEventID = ev.eventID;
|
||||
m_Cmd.m_RootEventID = ev.eventID;
|
||||
|
||||
// if not partial, we need to be sure to replay
|
||||
// past the command buffer records, so can't
|
||||
@@ -386,20 +375,20 @@ void WrappedID3D12CommandQueue::ReplayLog(LogState readType, uint32_t startEvent
|
||||
if(partial)
|
||||
m_pSerialiser->SetOffset(ev.fileOffset);
|
||||
|
||||
m_FirstEventID = startEventID;
|
||||
m_LastEventID = endEventID;
|
||||
m_Cmd.m_FirstEventID = startEventID;
|
||||
m_Cmd.m_LastEventID = endEventID;
|
||||
}
|
||||
else if(m_State == READING)
|
||||
{
|
||||
m_RootEventID = 1;
|
||||
m_RootDrawcallID = 1;
|
||||
m_FirstEventID = 0;
|
||||
m_LastEventID = ~0U;
|
||||
m_Cmd.m_RootEventID = 1;
|
||||
m_Cmd.m_RootDrawcallID = 1;
|
||||
m_Cmd.m_FirstEventID = 0;
|
||||
m_Cmd.m_LastEventID = ~0U;
|
||||
}
|
||||
|
||||
for(;;)
|
||||
{
|
||||
if(m_State == EXECUTING && m_RootEventID > endEventID)
|
||||
if(m_State == EXECUTING && m_Cmd.m_RootEventID > endEventID)
|
||||
{
|
||||
// we can just break out if we've done all the events desired.
|
||||
// note that the command buffer events aren't 'real' and we just blaze through them
|
||||
@@ -410,7 +399,7 @@ void WrappedID3D12CommandQueue::ReplayLog(LogState readType, uint32_t startEvent
|
||||
|
||||
D3D12ChunkType context = (D3D12ChunkType)m_pSerialiser->PushContext(NULL, NULL, 1, false);
|
||||
|
||||
m_LastCmdListID = ResourceId();
|
||||
m_Cmd.m_LastCmdListID = ResourceId();
|
||||
|
||||
ProcessChunk(offset, context);
|
||||
|
||||
@@ -430,16 +419,16 @@ void WrappedID3D12CommandQueue::ReplayLog(LogState readType, uint32_t startEvent
|
||||
// in which case it's up to the calling code to make sure we only
|
||||
// replay inside a command buffer (if we crossed command buffer
|
||||
// boundaries, the event IDs would no longer match up).
|
||||
if(m_LastCmdListID == ResourceId() || startEventID > 1)
|
||||
if(m_Cmd.m_LastCmdListID == ResourceId() || startEventID > 1)
|
||||
{
|
||||
m_RootEventID++;
|
||||
m_Cmd.m_RootEventID++;
|
||||
|
||||
if(startEventID > 1)
|
||||
m_pSerialiser->SetOffset(GetEvent(m_RootEventID).fileOffset);
|
||||
m_pSerialiser->SetOffset(GetEvent(m_Cmd.m_RootEventID).fileOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_BakedCmdListInfo[m_LastCmdListID].curEventID++;
|
||||
m_Cmd.m_BakedCmdListInfo[m_Cmd.m_LastCmdListID].curEventID++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -456,119 +445,20 @@ void WrappedID3D12CommandQueue::ReplayLog(LogState readType, uint32_t startEvent
|
||||
}
|
||||
};
|
||||
|
||||
std::sort(m_Events.begin(), m_Events.end(), SortEID());
|
||||
std::sort(m_Cmd.m_Events.begin(), m_Cmd.m_Events.end(), SortEID());
|
||||
}
|
||||
|
||||
SAFE_RELEASE(m_PartialReplayData.resultPartialCmdList);
|
||||
for(int p = 0; p < D3D12CommandData::ePartialNum; p++)
|
||||
SAFE_RELEASE(m_Cmd.m_Partial[p].resultPartialCmdList);
|
||||
|
||||
for(auto it = m_RerecordCmds.begin(); it != m_RerecordCmds.end(); ++it)
|
||||
for(auto it = m_Cmd.m_RerecordCmds.begin(); it != m_Cmd.m_RerecordCmds.end(); ++it)
|
||||
SAFE_RELEASE(it->second);
|
||||
|
||||
m_RerecordCmds.clear();
|
||||
m_Cmd.m_RerecordCmds.clear();
|
||||
|
||||
m_State = READING;
|
||||
}
|
||||
|
||||
void WrappedID3D12CommandQueue::AddDrawcall(const FetchDrawcall &d, bool hasEvents)
|
||||
{
|
||||
m_AddedDrawcall = true;
|
||||
|
||||
FetchDrawcall draw = d;
|
||||
draw.eventID = m_LastCmdListID != ResourceId() ? m_BakedCmdListInfo[m_LastCmdListID].curEventID
|
||||
: m_RootEventID;
|
||||
draw.drawcallID = m_LastCmdListID != ResourceId() ? m_BakedCmdListInfo[m_LastCmdListID].drawCount
|
||||
: m_RootDrawcallID;
|
||||
|
||||
for(int i = 0; i < 8; i++)
|
||||
draw.outputs[i] = ResourceId();
|
||||
|
||||
draw.depthOut = ResourceId();
|
||||
|
||||
draw.indexByteWidth = 0;
|
||||
draw.topology = eTopology_Unknown;
|
||||
|
||||
if(m_LastCmdListID != ResourceId())
|
||||
{
|
||||
// TODO fill from m_BakedCmdListInfo[m_LastCmdListID].state
|
||||
}
|
||||
|
||||
if(m_LastCmdListID != ResourceId())
|
||||
m_BakedCmdListInfo[m_LastCmdListID].drawCount++;
|
||||
else
|
||||
m_RootDrawcallID++;
|
||||
|
||||
if(hasEvents)
|
||||
{
|
||||
vector<FetchAPIEvent> &srcEvents = m_LastCmdListID != ResourceId()
|
||||
? m_BakedCmdListInfo[m_LastCmdListID].curEvents
|
||||
: m_RootEvents;
|
||||
|
||||
draw.events = srcEvents;
|
||||
srcEvents.clear();
|
||||
}
|
||||
|
||||
// should have at least the root drawcall here, push this drawcall
|
||||
// onto the back's children list.
|
||||
if(!GetDrawcallStack().empty())
|
||||
{
|
||||
D3D12DrawcallTreeNode node(draw);
|
||||
|
||||
node.resourceUsage.swap(m_BakedCmdListInfo[m_LastCmdListID].resourceUsage);
|
||||
|
||||
// TODO add usage
|
||||
|
||||
node.children.insert(node.children.begin(), draw.children.elems,
|
||||
draw.children.elems + draw.children.count);
|
||||
GetDrawcallStack().back()->children.push_back(node);
|
||||
}
|
||||
else
|
||||
RDCERR("Somehow lost drawcall stack!");
|
||||
}
|
||||
|
||||
void WrappedID3D12CommandQueue::AddEvent(D3D12ChunkType type, string description)
|
||||
{
|
||||
FetchAPIEvent apievent;
|
||||
|
||||
apievent.context = ResourceId();
|
||||
apievent.fileOffset = m_CurChunkOffset;
|
||||
apievent.eventID = m_LastCmdListID != ResourceId() ? m_BakedCmdListInfo[m_LastCmdListID].curEventID
|
||||
: m_RootEventID;
|
||||
|
||||
apievent.eventDesc = description;
|
||||
|
||||
Callstack::Stackwalk *stack = m_pSerialiser->GetLastCallstack();
|
||||
if(stack)
|
||||
{
|
||||
create_array(apievent.callstack, stack->NumLevels());
|
||||
memcpy(apievent.callstack.elems, stack->GetAddrs(), sizeof(uint64_t) * stack->NumLevels());
|
||||
}
|
||||
|
||||
// TODO have real m_EventMessages
|
||||
vector<DebugMessage> m_EventMessages;
|
||||
|
||||
for(size_t i = 0; i < m_EventMessages.size(); i++)
|
||||
m_EventMessages[i].eventID = apievent.eventID;
|
||||
|
||||
if(m_LastCmdListID != ResourceId())
|
||||
{
|
||||
m_BakedCmdListInfo[m_LastCmdListID].curEvents.push_back(apievent);
|
||||
|
||||
vector<DebugMessage> &msgs = m_BakedCmdListInfo[m_LastCmdListID].debugMessages;
|
||||
|
||||
msgs.insert(msgs.end(), m_EventMessages.begin(), m_EventMessages.end());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_RootEvents.push_back(apievent);
|
||||
m_Events.push_back(apievent);
|
||||
|
||||
// TODO m_DebugMessages.insert(m_DebugMessages.end(), m_EventMessages.begin(),
|
||||
// m_EventMessages.end());
|
||||
}
|
||||
|
||||
m_EventMessages.clear();
|
||||
}
|
||||
|
||||
WrappedID3D12GraphicsCommandList::WrappedID3D12GraphicsCommandList(ID3D12GraphicsCommandList *real,
|
||||
WrappedID3D12Device *device,
|
||||
Serialiser *serialiser,
|
||||
@@ -601,6 +491,7 @@ WrappedID3D12GraphicsCommandList::WrappedID3D12GraphicsCommandList(ID3D12Graphic
|
||||
RDCEraseEl(m_Init);
|
||||
|
||||
m_ListRecord = NULL;
|
||||
m_Cmd = NULL;
|
||||
|
||||
if(!RenderDoc::Inst().IsReplayApp())
|
||||
{
|
||||
@@ -615,6 +506,10 @@ WrappedID3D12GraphicsCommandList::WrappedID3D12GraphicsCommandList(ID3D12Graphic
|
||||
// this is set up in the implicit Reset() right after creation
|
||||
m_ListRecord->bakedCommands = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Cmd = m_pDevice->GetQueue()->GetCommandData();
|
||||
}
|
||||
|
||||
m_pDevice->SoftRef();
|
||||
}
|
||||
@@ -671,12 +566,228 @@ HRESULT STDMETHODCALLTYPE WrappedID3D12GraphicsCommandList::QueryInterface(REFII
|
||||
return RefCounter12::QueryInterface(riid, ppvObject);
|
||||
}
|
||||
|
||||
void WrappedID3D12GraphicsCommandList::AddDrawcall(const FetchDrawcall &d, bool hasEvents)
|
||||
D3D12CommandData::D3D12CommandData()
|
||||
{
|
||||
m_pDevice->GetQueue()->AddDrawcall(d, hasEvents);
|
||||
m_RootEventID = 1;
|
||||
m_RootDrawcallID = 1;
|
||||
m_FirstEventID = 0;
|
||||
m_LastEventID = ~0U;
|
||||
|
||||
m_RootDrawcallStack.push_back(&m_ParentDrawcall);
|
||||
}
|
||||
|
||||
void WrappedID3D12GraphicsCommandList::AddEvent(D3D12ChunkType type, string description)
|
||||
bool D3D12CommandData::ShouldRerecordCmd(ResourceId cmdid)
|
||||
{
|
||||
m_pDevice->GetQueue()->AddEvent(type, description);
|
||||
if(m_Partial[Primary].outsideCmdList != NULL)
|
||||
return true;
|
||||
|
||||
D3D12NOTIMP("m_DrawcallCallback");
|
||||
/*
|
||||
if(m_DrawcallCallback && m_DrawcallCallback->RecordAllCmds())
|
||||
return true;
|
||||
*/
|
||||
|
||||
return cmdid == m_Partial[Primary].partialParent || cmdid == m_Partial[Secondary].partialParent;
|
||||
}
|
||||
|
||||
bool D3D12CommandData::InRerecordRange(ResourceId cmdid)
|
||||
{
|
||||
if(m_Partial[Primary].outsideCmdList != NULL)
|
||||
return true;
|
||||
|
||||
D3D12NOTIMP("m_DrawcallCallback");
|
||||
/*
|
||||
if(m_DrawcallCallback && m_DrawcallCallback->RecordAllCmds())
|
||||
return true;
|
||||
*/
|
||||
|
||||
for(int p = 0; p < ePartialNum; p++)
|
||||
{
|
||||
if(cmdid == m_Partial[p].partialParent)
|
||||
{
|
||||
return m_BakedCmdListInfo[m_Partial[p].partialParent].curEventID <=
|
||||
m_LastEventID - m_Partial[p].baseEvent;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ID3D12GraphicsCommandList *D3D12CommandData::RerecordCmdList(ResourceId cmdid,
|
||||
PartialReplayIndex partialType)
|
||||
{
|
||||
if(m_Partial[Primary].outsideCmdList != NULL)
|
||||
return m_Partial[Primary].outsideCmdList;
|
||||
|
||||
D3D12NOTIMP("m_DrawcallCallback");
|
||||
/*
|
||||
if(m_DrawcallCallback && m_DrawcallCallback->RecordAllCmds())
|
||||
{
|
||||
auto it = m_RerecordCmds.find(cmdid);
|
||||
|
||||
RDCASSERT(it != m_RerecordCmds.end());
|
||||
|
||||
return it->second;
|
||||
}
|
||||
*/
|
||||
|
||||
if(partialType != ePartialNum)
|
||||
return m_Partial[partialType].resultPartialCmdList;
|
||||
|
||||
for(int p = 0; p < ePartialNum; p++)
|
||||
if(cmdid == m_Partial[p].partialParent)
|
||||
return m_Partial[p].resultPartialCmdList;
|
||||
|
||||
RDCERR("Calling re-record for invalid command list id");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void D3D12CommandData::AddEvent(D3D12ChunkType type, string description)
|
||||
{
|
||||
FetchAPIEvent apievent;
|
||||
|
||||
apievent.context = ResourceId();
|
||||
apievent.fileOffset = m_CurChunkOffset;
|
||||
apievent.eventID = m_LastCmdListID != ResourceId() ? m_BakedCmdListInfo[m_LastCmdListID].curEventID
|
||||
: m_RootEventID;
|
||||
|
||||
apievent.eventDesc = description;
|
||||
|
||||
Callstack::Stackwalk *stack = m_pSerialiser->GetLastCallstack();
|
||||
if(stack)
|
||||
{
|
||||
create_array(apievent.callstack, stack->NumLevels());
|
||||
memcpy(apievent.callstack.elems, stack->GetAddrs(), sizeof(uint64_t) * stack->NumLevels());
|
||||
}
|
||||
|
||||
// TODO have real m_EventMessages
|
||||
vector<DebugMessage> m_EventMessages;
|
||||
|
||||
for(size_t i = 0; i < m_EventMessages.size(); i++)
|
||||
m_EventMessages[i].eventID = apievent.eventID;
|
||||
|
||||
if(m_LastCmdListID != ResourceId())
|
||||
{
|
||||
m_BakedCmdListInfo[m_LastCmdListID].curEvents.push_back(apievent);
|
||||
|
||||
vector<DebugMessage> &msgs = m_BakedCmdListInfo[m_LastCmdListID].debugMessages;
|
||||
|
||||
msgs.insert(msgs.end(), m_EventMessages.begin(), m_EventMessages.end());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_RootEvents.push_back(apievent);
|
||||
m_Events.push_back(apievent);
|
||||
|
||||
// TODO m_DebugMessages.insert(m_DebugMessages.end(), m_EventMessages.begin(),
|
||||
// m_EventMessages.end());
|
||||
}
|
||||
|
||||
m_EventMessages.clear();
|
||||
}
|
||||
|
||||
void D3D12CommandData::AddDrawcall(const FetchDrawcall &d, bool hasEvents)
|
||||
{
|
||||
m_AddedDrawcall = true;
|
||||
|
||||
FetchDrawcall draw = d;
|
||||
draw.eventID = m_LastCmdListID != ResourceId() ? m_BakedCmdListInfo[m_LastCmdListID].curEventID
|
||||
: m_RootEventID;
|
||||
draw.drawcallID = m_LastCmdListID != ResourceId() ? m_BakedCmdListInfo[m_LastCmdListID].drawCount
|
||||
: m_RootDrawcallID;
|
||||
|
||||
for(int i = 0; i < 8; i++)
|
||||
draw.outputs[i] = ResourceId();
|
||||
|
||||
draw.depthOut = ResourceId();
|
||||
|
||||
draw.indexByteWidth = 0;
|
||||
draw.topology = eTopology_Unknown;
|
||||
|
||||
if(m_LastCmdListID != ResourceId())
|
||||
{
|
||||
// TODO fill from m_BakedCmdListInfo[m_LastCmdListID].state
|
||||
}
|
||||
|
||||
if(m_LastCmdListID != ResourceId())
|
||||
m_BakedCmdListInfo[m_LastCmdListID].drawCount++;
|
||||
else
|
||||
m_RootDrawcallID++;
|
||||
|
||||
if(hasEvents)
|
||||
{
|
||||
vector<FetchAPIEvent> &srcEvents = m_LastCmdListID != ResourceId()
|
||||
? m_BakedCmdListInfo[m_LastCmdListID].curEvents
|
||||
: m_RootEvents;
|
||||
|
||||
draw.events = srcEvents;
|
||||
srcEvents.clear();
|
||||
}
|
||||
|
||||
// should have at least the root drawcall here, push this drawcall
|
||||
// onto the back's children list.
|
||||
if(!GetDrawcallStack().empty())
|
||||
{
|
||||
D3D12DrawcallTreeNode node(draw);
|
||||
|
||||
node.resourceUsage.swap(m_BakedCmdListInfo[m_LastCmdListID].resourceUsage);
|
||||
|
||||
// TODO add usage
|
||||
|
||||
node.children.insert(node.children.begin(), draw.children.elems,
|
||||
draw.children.elems + draw.children.count);
|
||||
GetDrawcallStack().back()->children.push_back(node);
|
||||
}
|
||||
else
|
||||
RDCERR("Somehow lost drawcall stack!");
|
||||
}
|
||||
|
||||
void D3D12CommandData::InsertDrawsAndRefreshIDs(vector<D3D12DrawcallTreeNode> &cmdBufNodes)
|
||||
{
|
||||
// assign new drawcall IDs
|
||||
for(size_t i = 0; i < cmdBufNodes.size(); i++)
|
||||
{
|
||||
if(cmdBufNodes[i].draw.flags & eDraw_PopMarker)
|
||||
{
|
||||
RDCASSERT(GetDrawcallStack().size() > 1);
|
||||
if(GetDrawcallStack().size() > 1)
|
||||
GetDrawcallStack().pop_back();
|
||||
|
||||
// Skip - pop marker draws aren't processed otherwise, we just apply them to the drawcall
|
||||
// stack.
|
||||
continue;
|
||||
}
|
||||
|
||||
D3D12DrawcallTreeNode n = cmdBufNodes[i];
|
||||
n.draw.eventID += m_RootEventID;
|
||||
n.draw.drawcallID += m_RootDrawcallID;
|
||||
|
||||
for(int32_t e = 0; e < n.draw.events.count; e++)
|
||||
{
|
||||
n.draw.events[e].eventID += m_RootEventID;
|
||||
m_Events.push_back(n.draw.events[e]);
|
||||
}
|
||||
|
||||
DrawcallUse use(m_Events.back().fileOffset, n.draw.eventID);
|
||||
|
||||
// insert in sorted location
|
||||
auto drawit = std::lower_bound(m_DrawcallUses.begin(), m_DrawcallUses.end(), use);
|
||||
m_DrawcallUses.insert(drawit, use);
|
||||
|
||||
RDCASSERT(n.children.empty());
|
||||
|
||||
for(auto it = n.resourceUsage.begin(); it != n.resourceUsage.end(); ++it)
|
||||
{
|
||||
EventUsage u = it->second;
|
||||
u.eventID += m_RootEventID;
|
||||
m_ResourceUses[it->first].push_back(u);
|
||||
}
|
||||
|
||||
GetDrawcallStack().back()->children.push_back(n);
|
||||
|
||||
// if this is a push marker too, step down the drawcall stack
|
||||
if(cmdBufNodes[i].draw.flags & eDraw_PushMarker)
|
||||
GetDrawcallStack().push_back(&GetDrawcallStack().back()->children.back());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,258 @@
|
||||
/******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Baldur Karlsson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/common.h"
|
||||
#include "api/replay/renderdoc_replay.h"
|
||||
#include "d3d12_common.h"
|
||||
|
||||
struct D3D12DrawcallTreeNode
|
||||
{
|
||||
D3D12DrawcallTreeNode() {}
|
||||
explicit D3D12DrawcallTreeNode(const FetchDrawcall &d) : draw(d) {}
|
||||
FetchDrawcall draw;
|
||||
vector<D3D12DrawcallTreeNode> children;
|
||||
|
||||
vector<pair<ResourceId, EventUsage> > resourceUsage;
|
||||
|
||||
vector<ResourceId> executedCmds;
|
||||
|
||||
D3D12DrawcallTreeNode &operator=(const FetchDrawcall &d)
|
||||
{
|
||||
*this = D3D12DrawcallTreeNode(d);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void InsertAndUpdateIDs(const D3D12DrawcallTreeNode &child, uint32_t baseEventID,
|
||||
uint32_t baseDrawID)
|
||||
{
|
||||
for(size_t i = 0; i < child.resourceUsage.size(); i++)
|
||||
{
|
||||
resourceUsage.push_back(child.resourceUsage[i]);
|
||||
resourceUsage.back().second.eventID += baseEventID;
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < child.children.size(); i++)
|
||||
{
|
||||
children.push_back(child.children[i]);
|
||||
children.back().draw.eventID += baseEventID;
|
||||
children.back().draw.drawcallID += baseDrawID;
|
||||
|
||||
for(int32_t e = 0; e < children.back().draw.events.count; e++)
|
||||
children.back().draw.events[e].eventID += baseEventID;
|
||||
}
|
||||
}
|
||||
|
||||
vector<FetchDrawcall> Bake()
|
||||
{
|
||||
vector<FetchDrawcall> ret;
|
||||
if(children.empty())
|
||||
return ret;
|
||||
|
||||
ret.resize(children.size());
|
||||
for(size_t i = 0; i < children.size(); i++)
|
||||
{
|
||||
ret[i] = children[i].draw;
|
||||
ret[i].children = children[i].Bake();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
struct BakedCmdListInfo
|
||||
{
|
||||
void BakeFrom(BakedCmdListInfo &parent)
|
||||
{
|
||||
draw = parent.draw;
|
||||
curEvents = parent.curEvents;
|
||||
debugMessages = parent.debugMessages;
|
||||
eventCount = parent.curEventID;
|
||||
drawCount = parent.drawCount;
|
||||
|
||||
curEventID = 0;
|
||||
|
||||
parent.draw = NULL;
|
||||
parent.curEventID = 0;
|
||||
parent.eventCount = 0;
|
||||
parent.drawCount = 0;
|
||||
parent.curEvents.clear();
|
||||
parent.debugMessages.clear();
|
||||
}
|
||||
|
||||
vector<FetchAPIEvent> curEvents;
|
||||
vector<DebugMessage> debugMessages;
|
||||
std::list<D3D12DrawcallTreeNode *> drawStack;
|
||||
|
||||
vector<pair<ResourceId, EventUsage> > resourceUsage;
|
||||
|
||||
struct CmdListState
|
||||
{
|
||||
ResourceId pipeline;
|
||||
|
||||
D3D12_PRIMITIVE_TOPOLOGY topo;
|
||||
|
||||
uint32_t idxWidth;
|
||||
ResourceId ibuffer;
|
||||
vector<ResourceId> vbuffers;
|
||||
|
||||
ResourceId rts[8];
|
||||
ResourceId dsv;
|
||||
} state;
|
||||
|
||||
vector<D3D12_RESOURCE_BARRIER> barriers;
|
||||
|
||||
D3D12DrawcallTreeNode *draw; // the root draw to copy from when submitting
|
||||
uint32_t eventCount; // how many events are in this cmd list, for quick skipping
|
||||
uint32_t curEventID; // current event ID while reading or executing
|
||||
uint32_t drawCount; // similar to above
|
||||
};
|
||||
|
||||
struct D3D12CommandData
|
||||
{
|
||||
D3D12CommandData();
|
||||
|
||||
Serialiser *m_pSerialiser;
|
||||
|
||||
ResourceId m_LastCmdListID;
|
||||
|
||||
map<ResourceId, BakedCmdListInfo> m_BakedCmdListInfo;
|
||||
|
||||
enum PartialReplayIndex
|
||||
{
|
||||
Primary,
|
||||
Secondary,
|
||||
ePartialNum
|
||||
};
|
||||
|
||||
struct PartialReplayData
|
||||
{
|
||||
PartialReplayData() { Reset(); }
|
||||
void Reset()
|
||||
{
|
||||
resultPartialCmdList = NULL;
|
||||
outsideCmdList = NULL;
|
||||
partialParent = ResourceId();
|
||||
baseEvent = 0;
|
||||
}
|
||||
|
||||
// if we're doing a partial replay, by definition only one command
|
||||
// list will be partial at any one time. While replaying through
|
||||
// the command list chunks, the partial command list will be
|
||||
// created as a temporary new command list and when it comes to
|
||||
// the queue that should execute it, it can execute this instead.
|
||||
ID3D12GraphicsCommandList *resultPartialCmdList;
|
||||
|
||||
// if we're replaying just a single draw or a particular command
|
||||
// list subsection of command events, we don't go through the
|
||||
// whole original command lists to set up the partial replay,
|
||||
// so we just set this command list
|
||||
ID3D12GraphicsCommandList *outsideCmdList;
|
||||
|
||||
// this records where in the frame a command list was executed,
|
||||
// so that we know if our replay range ends in one of these ranges
|
||||
// we need to construct a partial command list for future
|
||||
// replaying. Note that we always have the complete command list
|
||||
// around - it's the bakeID itself.
|
||||
// Since we only ever record a bakeID once the key is unique - note
|
||||
// that the same command list could be reset multiple times
|
||||
// a frame, so the parent command list ID (the one recorded in
|
||||
// CmdList chunks) is NOT unique.
|
||||
// However, a single baked command list can be executed multiple
|
||||
// times - so we have to have a list of base events
|
||||
// Map from bakeID -> vector<baseEventID>
|
||||
map<ResourceId, vector<uint32_t> > cmdListExecs;
|
||||
|
||||
// This is just the ResourceId of the original parent command list
|
||||
// and it's baked id.
|
||||
// If we are in the middle of a partial replay - allows fast checking
|
||||
// in all CmdList chunks, with the iteration through the above list
|
||||
// only in Reset.
|
||||
// partialParent gets reset to ResourceId() in the Close so that
|
||||
// other baked command lists from the same parent don't pick it up
|
||||
// Also reset each overall replay
|
||||
ResourceId partialParent;
|
||||
|
||||
// If a partial replay is detected, this records the base of the
|
||||
// range. This both allows easily and uniquely identifying it in the
|
||||
// executecmdlists, but also allows the recording to 'rebase' the
|
||||
// last event ID by subtracting this, to know how far to record
|
||||
uint32_t baseEvent;
|
||||
} m_Partial[ePartialNum];
|
||||
|
||||
void InsertDrawsAndRefreshIDs(vector<D3D12DrawcallTreeNode> &cmdBufNodes);
|
||||
|
||||
// this is a list of uint64_t file offset -> uint32_t EIDs of where each
|
||||
// drawcall is used. E.g. the drawcall at offset 873954 is EID 50. If a
|
||||
// command list is executed more than once, there may be more than
|
||||
// one entry here - the drawcall will be aliased among several EIDs, with
|
||||
// the first one being the 'primary'
|
||||
struct DrawcallUse
|
||||
{
|
||||
DrawcallUse(uint64_t offs, uint32_t eid) : fileOffset(offs), eventID(eid) {}
|
||||
uint64_t fileOffset;
|
||||
uint32_t eventID;
|
||||
bool operator<(const DrawcallUse &o) const
|
||||
{
|
||||
if(fileOffset != o.fileOffset)
|
||||
return fileOffset < o.fileOffset;
|
||||
return eventID < o.eventID;
|
||||
}
|
||||
};
|
||||
vector<DrawcallUse> m_DrawcallUses;
|
||||
|
||||
map<ResourceId, ID3D12GraphicsCommandList *> m_RerecordCmds;
|
||||
|
||||
bool m_AddedDrawcall;
|
||||
|
||||
vector<FetchAPIEvent> m_RootEvents, m_Events;
|
||||
|
||||
uint64_t m_CurChunkOffset;
|
||||
|
||||
uint32_t m_RootEventID, m_RootDrawcallID;
|
||||
uint32_t m_FirstEventID, m_LastEventID;
|
||||
|
||||
map<ResourceId, vector<EventUsage> > m_ResourceUses;
|
||||
|
||||
D3D12DrawcallTreeNode m_ParentDrawcall;
|
||||
|
||||
std::list<D3D12DrawcallTreeNode *> m_RootDrawcallStack;
|
||||
|
||||
std::list<D3D12DrawcallTreeNode *> &GetDrawcallStack()
|
||||
{
|
||||
if(m_LastCmdListID != ResourceId())
|
||||
return m_BakedCmdListInfo[m_LastCmdListID].drawStack;
|
||||
|
||||
return m_RootDrawcallStack;
|
||||
}
|
||||
|
||||
bool ShouldRerecordCmd(ResourceId cmdid);
|
||||
bool InRerecordRange(ResourceId cmdid);
|
||||
ID3D12GraphicsCommandList *RerecordCmdList(ResourceId cmdid,
|
||||
PartialReplayIndex partialType = ePartialNum);
|
||||
|
||||
void AddDrawcall(const FetchDrawcall &d, bool hasEvents);
|
||||
void AddEvent(D3D12ChunkType type, string description);
|
||||
};
|
||||
@@ -35,7 +35,24 @@
|
||||
|
||||
// similar to RDCUNIMPLEMENTED but for things that are hit often so we don't want to fire the
|
||||
// debugbreak.
|
||||
#define D3D12NOTIMP(...) RDCDEBUG("D3D12 not implemented - " __VA_ARGS__)
|
||||
#define D3D12NOTIMP(...) \
|
||||
{ \
|
||||
static bool CONCAT(ignore, __LINE__) = false; \
|
||||
if(!CONCAT(ignore, __LINE__)) \
|
||||
{ \
|
||||
RDCDEBUG("D3D12 not implemented - " __VA_ARGS__); \
|
||||
CONCAT(ignore, __LINE__) = true; \
|
||||
} \
|
||||
}
|
||||
|
||||
// uncomment this to cause every internal ExecuteCommandLists to immediately call
|
||||
// FlushLists(), and to only submit one command list at once to narrow
|
||||
// down the cause of device lost errors
|
||||
//#define SINGLE_FLUSH_VALIDATE
|
||||
|
||||
// uncomment this to get verbose debugging about when/where/why partial command
|
||||
// buffer replay is happening
|
||||
#define VERBOSE_PARTIAL_REPLAY
|
||||
|
||||
UINT GetNumSubresources(const D3D12_RESOURCE_DESC *desc);
|
||||
|
||||
|
||||
@@ -229,6 +229,11 @@ ResourceId D3D12Replay::GetLiveID(ResourceId id)
|
||||
return m_pDevice->GetResourceManager()->GetLiveID(id);
|
||||
}
|
||||
|
||||
vector<EventUsage> D3D12Replay::GetUsage(ResourceId id)
|
||||
{
|
||||
return m_pDevice->GetQueue()->GetUsage(id);
|
||||
}
|
||||
|
||||
void D3D12Replay::RenderCheckerboard(Vec3f light, Vec3f dark)
|
||||
{
|
||||
m_pDevice->GetDebugManager()->RenderCheckerboard(light, dark);
|
||||
@@ -326,11 +331,6 @@ ShaderReflection *D3D12Replay::GetShader(ResourceId shader, string entryPoint)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vector<EventUsage> D3D12Replay::GetUsage(ResourceId id)
|
||||
{
|
||||
return vector<EventUsage>();
|
||||
}
|
||||
|
||||
vector<DebugMessage> D3D12Replay::GetDebugMessages()
|
||||
{
|
||||
return vector<DebugMessage>();
|
||||
|
||||
@@ -197,6 +197,7 @@
|
||||
<ClCompile Include="d3d12_resources.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="d3d12_commands.h" />
|
||||
<ClInclude Include="d3d12_command_list.h" />
|
||||
<ClInclude Include="d3d12_command_queue.h" />
|
||||
<ClInclude Include="d3d12_common.h" />
|
||||
|
||||
@@ -51,6 +51,9 @@
|
||||
<ClInclude Include="d3d12_debug.h">
|
||||
<Filter>Replay</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="d3d12_commands.h">
|
||||
<Filter>Core IFaces</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="d3d12_common.cpp">
|
||||
|
||||
Reference in New Issue
Block a user