During Loading replay replace D3D12ActionTreeNode with D3D12EventNode

D3D12EventNode contains all data for an Event during loading: APIEvent, ActionDescription, resource usage, debugMessages, annotations.
Action ID, Event ID is not computed whilst loading is happening.

At the end of Loading when the D3D12EventNode's have been flattened into linear submission order then the D3D12EventNode's are baked into RenderDoc replay APIEvents and Actions. Event IDs and Action IDs are assigned as part of the baking process
This commit is contained in:
Jake Turner
2026-07-30 16:36:02 +01:00
parent 5a1b2c23e1
commit 4e59f62a96
10 changed files with 486 additions and 669 deletions
+5 -5
View File
@@ -227,11 +227,11 @@ public:
D3D12ResourceRecord *GetResourceRecord() { return m_ListRecord; }
D3D12ResourceRecord *GetCreationRecord() { return m_CreationRecord; }
void FinaliseExecuteIndirectEvents(BakedCmdListInfo &info, BakedCmdListInfo::ExecuteData &exec);
void SaveExecuteIndirectParameters(ID3D12GraphicsCommandListX *list,
ID3D12CommandSignature *pCommandSignature, UINT MaxCommandCount,
ID3D12Resource *pArgumentBuffer, UINT64 ArgumentBufferOffset,
ID3D12Resource *pCountBuffer, UINT64 CountBufferOffset);
void FinaliseExecuteIndirectEvents(BakedCmdListInfo &info, size_t nodeIdx);
D3D12ExecuteData SaveExecuteIndirectParameters(
ID3D12GraphicsCommandListX *list, ID3D12CommandSignature *pCommandSignature,
UINT MaxCommandCount, ID3D12Resource *pArgumentBuffer, UINT64 ArgumentBufferOffset,
ID3D12Resource *pCountBuffer, UINT64 CountBufferOffset);
void ResetAndRecordExecuteIndirectStates(ID3D12GraphicsCommandListX *list, uint32_t baseEventID,
uint32_t execCount,
ID3D12CommandSignature *pCommandSignature,
@@ -91,19 +91,18 @@ bool WrappedID3D12GraphicsCommandList::Serialise_AtomicCopyBufferUINT(
m_Cmd->AddAction(action);
D3D12ActionTreeNode &actionNode = m_Cmd->GetActionStack().back()->children.back();
D3D12EventNode &eventNode = m_Cmd->GetLastEventNode();
if(pSrcBuffer == pDstBuffer)
{
actionNode.resourceUsage.push_back(make_rdcpair(
GetResID(pSrcBuffer), EventUsage(actionNode.action.eventId, ResourceUsage::Copy)));
eventNode.resourceUsage.push_back(make_rdcpair(GetResID(pSrcBuffer), ResourceUsage::Copy));
}
else
{
actionNode.resourceUsage.push_back(make_rdcpair(
GetResID(pSrcBuffer), EventUsage(actionNode.action.eventId, ResourceUsage::CopySrc)));
actionNode.resourceUsage.push_back(make_rdcpair(
GetResID(pDstBuffer), EventUsage(actionNode.action.eventId, ResourceUsage::CopyDst)));
eventNode.resourceUsage.push_back(
make_rdcpair(GetResID(pSrcBuffer), ResourceUsage::CopySrc));
eventNode.resourceUsage.push_back(
make_rdcpair(GetResID(pDstBuffer), ResourceUsage::CopyDst));
}
}
}
@@ -204,19 +203,18 @@ bool WrappedID3D12GraphicsCommandList::Serialise_AtomicCopyBufferUINT64(
m_Cmd->AddAction(action);
D3D12ActionTreeNode &actionNode = m_Cmd->GetActionStack().back()->children.back();
D3D12EventNode &eventNode = m_Cmd->GetLastEventNode();
if(pSrcBuffer == pDstBuffer)
{
actionNode.resourceUsage.push_back(make_rdcpair(
GetResID(pSrcBuffer), EventUsage(actionNode.action.eventId, ResourceUsage::Copy)));
eventNode.resourceUsage.push_back(make_rdcpair(GetResID(pSrcBuffer), ResourceUsage::Copy));
}
else
{
actionNode.resourceUsage.push_back(make_rdcpair(
GetResID(pSrcBuffer), EventUsage(actionNode.action.eventId, ResourceUsage::CopySrc)));
actionNode.resourceUsage.push_back(make_rdcpair(
GetResID(pDstBuffer), EventUsage(actionNode.action.eventId, ResourceUsage::CopyDst)));
eventNode.resourceUsage.push_back(
make_rdcpair(GetResID(pSrcBuffer), ResourceUsage::CopySrc));
eventNode.resourceUsage.push_back(
make_rdcpair(GetResID(pDstBuffer), ResourceUsage::CopyDst));
}
}
}
@@ -487,21 +485,19 @@ bool WrappedID3D12GraphicsCommandList::Serialise_ResolveSubresourceRegion(
m_Cmd->AddAction(action);
D3D12ActionTreeNode &actionNode = m_Cmd->GetActionStack().back()->children.back();
D3D12EventNode &eventNode = m_Cmd->GetLastEventNode();
if(pSrcResource == pDstResource)
{
actionNode.resourceUsage.push_back(make_rdcpair(
GetResID(pSrcResource), EventUsage(actionNode.action.eventId, ResourceUsage::Resolve)));
eventNode.resourceUsage.push_back(
make_rdcpair(GetResID(pSrcResource), ResourceUsage::Resolve));
}
else
{
actionNode.resourceUsage.push_back(
make_rdcpair(GetResID(pSrcResource),
EventUsage(actionNode.action.eventId, ResourceUsage::ResolveSrc)));
actionNode.resourceUsage.push_back(
make_rdcpair(GetResID(pDstResource),
EventUsage(actionNode.action.eventId, ResourceUsage::ResolveDst)));
eventNode.resourceUsage.push_back(
make_rdcpair(GetResID(pSrcResource), ResourceUsage::ResolveSrc));
eventNode.resourceUsage.push_back(
make_rdcpair(GetResID(pDstResource), ResourceUsage::ResolveDst));
}
}
}
@@ -1397,15 +1397,16 @@ bool WrappedID3D12GraphicsCommandList::Serialise_EmitRaytracingAccelerationStruc
m_Cmd->AddAction(action);
D3D12ActionTreeNode &actionNode = m_Cmd->GetActionStack().back()->children.back();
D3D12EventNode &eventNode = m_Cmd->GetLastEventNode();
actionNode.resourceUsage.push_back(
make_rdcpair(WrappedID3D12Resource::GetResIDFromAddr(Desc.DestBuffer),
EventUsage(actionNode.action.eventId, ResourceUsage::CopyDst)));
eventNode.resourceUsage.push_back(make_rdcpair(
WrappedID3D12Resource::GetResIDFromAddr(Desc.DestBuffer), ResourceUsage::CopyDst));
for(UINT i = 0; i < NumSourceAccelerationStructures; i++)
actionNode.resourceUsage.push_back(make_rdcpair(
{
eventNode.resourceUsage.push_back(make_rdcpair(
WrappedID3D12Resource::GetResIDFromAddr(pSourceAccelerationStructureData[i]),
EventUsage(actionNode.action.eventId, ResourceUsage::CopySrc)));
ResourceUsage::CopySrc));
}
}
}
@@ -63,7 +63,7 @@ bool WrappedID3D12GraphicsCommandList::Serialise_Barrier(SerialiserType &ser, UI
D3D12_TEXTURE_BARRIER *tex = filteredUnwrappedTex.data();
D3D12_BUFFER_BARRIER *buf = filteredUnwrappedBuf.data();
BakedCmdListInfo &cmdinfo = m_Cmd->m_BakedCmdListInfo[m_Cmd->m_LastCmdListID];
D3D12EventNode &eventNode = m_Cmd->m_LoadingEventNode;
// filter out any barriers that reference a NULL resource - this means the resource wasn't used
// elsewhere so was discarded from the capture
@@ -86,8 +86,8 @@ bool WrappedID3D12GraphicsCommandList::Serialise_Barrier(SerialiserType &ser, UI
buf[group.NumBarriers].pResource = Unwrap(res);
group.NumBarriers++;
cmdinfo.resourceUsage.push_back(make_rdcpair(
GetResID(res), EventUsage(cmdinfo.curEventID, ResourceUsage::Barrier)));
if(IsLoading(m_State))
eventNode.resourceUsage.push_back(make_rdcpair(GetResID(res), ResourceUsage::Barrier));
}
}
@@ -112,8 +112,8 @@ bool WrappedID3D12GraphicsCommandList::Serialise_Barrier(SerialiserType &ser, UI
tex[group.NumBarriers].pResource = Unwrap(res);
group.NumBarriers++;
cmdinfo.resourceUsage.push_back(make_rdcpair(
GetResID(res), EventUsage(cmdinfo.curEventID, ResourceUsage::Barrier)));
if(IsLoading(m_State))
eventNode.resourceUsage.push_back(make_rdcpair(GetResID(res), ResourceUsage::Barrier));
}
}
+143 -235
View File
@@ -95,11 +95,6 @@ bool WrappedID3D12GraphicsCommandList::Serialise_Close(SerialiserType &ser)
{
GetResourceManager()->GetResAs<WrappedID3D12GraphicsCommandList>(CommandList)->Close();
{
if(m_Cmd->GetActionStack().size() > 1)
m_Cmd->GetActionStack().pop_back();
}
BakedCmdListInfo &baked = m_Cmd->m_BakedCmdListInfo[BakedCommandList];
BakedCmdListInfo &parent = m_Cmd->m_BakedCmdListInfo[CommandList];
@@ -111,7 +106,6 @@ bool WrappedID3D12GraphicsCommandList::Serialise_Close(SerialiserType &ser)
parent.curEventID = 0;
parent.eventCount = 0;
parent.actionCount = 0;
}
}
@@ -290,8 +284,6 @@ bool WrappedID3D12GraphicsCommandList::Serialise_Reset(SerialiserType &ser,
m_Cmd->m_BakedCmdListInfo[BakedCommandList].markerCount = 0;
m_Cmd->m_BakedCmdListInfo[CommandList].curEventID =
m_Cmd->m_BakedCmdListInfo[BakedCommandList].curEventID = 0;
m_Cmd->m_BakedCmdListInfo[CommandList].executeEvents =
m_Cmd->m_BakedCmdListInfo[BakedCommandList].executeEvents;
m_Cmd->m_BakedCmdListInfo[CommandList].barriers.clear();
m_Cmd->m_BakedCmdListInfo[BakedCommandList].barriers.clear();
}
@@ -337,9 +329,6 @@ bool WrappedID3D12GraphicsCommandList::Serialise_Reset(SerialiserType &ser,
}
{
D3D12ActionTreeNode *action = new D3D12ActionTreeNode;
m_Cmd->m_BakedCmdListInfo[BakedCommandList].action = action;
m_Cmd->m_BakedCmdListInfo[CommandList].type =
m_Cmd->m_BakedCmdListInfo[BakedCommandList].type = type;
m_Cmd->m_BakedCmdListInfo[CommandList].nodeMask =
@@ -353,9 +342,6 @@ bool WrappedID3D12GraphicsCommandList::Serialise_Reset(SerialiserType &ser,
// m_RootEventID and insert them into the tree.
m_Cmd->m_BakedCmdListInfo[BakedCommandList].curEventID = 0;
m_Cmd->m_BakedCmdListInfo[BakedCommandList].eventCount = 0;
m_Cmd->m_BakedCmdListInfo[BakedCommandList].actionCount = 0;
m_Cmd->m_BakedCmdListInfo[BakedCommandList].actionStack.push_back(action);
m_Cmd->m_BakedCmdListInfo[BakedCommandList].beginChunk =
uint32_t(m_Cmd->m_StructuredFile->chunks.size() - 1);
@@ -524,17 +510,15 @@ bool WrappedID3D12GraphicsCommandList::Serialise_ResourceBarrier(
if(IsLoading(m_State) && (res1 || res2))
{
BakedCmdListInfo &cmdinfo = m_Cmd->m_BakedCmdListInfo[m_Cmd->m_LastCmdListID];
D3D12EventNode &eventNode = m_Cmd->m_LoadingEventNode;
if(res1)
{
cmdinfo.resourceUsage.push_back(make_rdcpair(
GetResID(res1), EventUsage(cmdinfo.curEventID, ResourceUsage::Barrier)));
eventNode.resourceUsage.push_back(make_rdcpair(GetResID(res1), ResourceUsage::Barrier));
}
if(res2)
{
cmdinfo.resourceUsage.push_back(make_rdcpair(
GetResID(res2), EventUsage(cmdinfo.curEventID, ResourceUsage::Barrier)));
eventNode.resourceUsage.push_back(make_rdcpair(GetResID(res2), ResourceUsage::Barrier));
}
}
}
@@ -3032,11 +3016,9 @@ bool WrappedID3D12GraphicsCommandList::Serialise_ResolveQueryData(
m_Cmd->AddAction(action);
D3D12ActionTreeNode &actionNode = m_Cmd->GetActionStack().back()->children.back();
actionNode.resourceUsage.push_back(
make_rdcpair(GetResID(pDestinationBuffer),
EventUsage(actionNode.action.eventId, ResourceUsage::ResolveDst)));
D3D12EventNode &eventNode = m_Cmd->GetLastEventNode();
eventNode.resourceUsage.push_back(
make_rdcpair(GetResID(pDestinationBuffer), ResourceUsage::ResolveDst));
}
}
}
@@ -3368,10 +3350,8 @@ bool WrappedID3D12GraphicsCommandList::Serialise_SetCommandAnnotation(
ResourceId cmdId = GetResID(pCommandList);
PendingAnnotation annot = {m_Cmd->m_BakedCmdListInfo[m_Cmd->m_LastCmdListID].curEventID, key,
valueType, valueVectorWidth, value};
m_Cmd->m_BakedCmdListInfo[m_Cmd->m_LastCmdListID].annotations.push_back(annot);
PendingAnnotation annot = {0, key, valueType, valueVectorWidth, value};
m_Cmd->m_BakedCmdListInfo[m_Cmd->m_LastCmdListID].pendingAnnotations.push_back(annot);
m_pDevice->GetReplay()->WriteFrameRecord().frameInfo.containsAnnotations = true;
}
@@ -3685,15 +3665,13 @@ void WrappedID3D12GraphicsCommandList::ExecuteBundle(ID3D12GraphicsCommandList *
}
}
void WrappedID3D12GraphicsCommandList::SaveExecuteIndirectParameters(
D3D12ExecuteData WrappedID3D12GraphicsCommandList::SaveExecuteIndirectParameters(
ID3D12GraphicsCommandListX *list, ID3D12CommandSignature *pCommandSignature,
UINT MaxCommandCount, ID3D12Resource *pArgumentBuffer, UINT64 ArgumentBufferOffset,
ID3D12Resource *pCountBuffer, UINT64 CountBufferOffset)
{
WrappedID3D12CommandSignature *comSig = (WrappedID3D12CommandSignature *)pCommandSignature;
BakedCmdListInfo &cmdListInfo = m_Cmd->m_BakedCmdListInfo[m_Cmd->m_LastCmdListID];
const size_t argsSize =
comSig->sig.ByteStride * (RDCMAX(1U, MaxCommandCount) - 1) + comSig->sig.PackedByteSize;
const size_t countSize = 16;
@@ -3709,10 +3687,12 @@ void WrappedID3D12GraphicsCommandList::SaveExecuteIndirectParameters(
Unwrap(list)->CopyBufferRegion(Unwrap(buf), offs + countSize, Unwrap(pArgumentBuffer),
ArgumentBufferOffset, argsSize);
BakedCmdListInfo::ExecuteData exec = {};
exec.baseEvent = cmdListInfo.curEventID;
D3D12ExecuteData exec = {};
exec.sig = comSig;
exec.maxCount = MaxCommandCount;
// For variable count indirects only allocate up to one indirect command to avoid pessimistic
// allocation if MaxCommandCount is very high but the actual action count is low.
exec.reservedCount = pCountBuffer ? RDCMIN(1U, MaxCommandCount) : MaxCommandCount;
if(pCountBuffer)
{
exec.countBuf = buf;
@@ -3721,7 +3701,7 @@ void WrappedID3D12GraphicsCommandList::SaveExecuteIndirectParameters(
exec.argBuf = buf;
exec.argOffs = offs + 16;
cmdListInfo.executeEvents.push_back(exec);
return exec;
}
void WrappedID3D12GraphicsCommandList::ResetAndRecordExecuteIndirectStates(
@@ -3835,8 +3815,12 @@ void WrappedID3D12GraphicsCommandList::ResetAndRecordExecuteIndirectStates(
}
void WrappedID3D12GraphicsCommandList::FinaliseExecuteIndirectEvents(BakedCmdListInfo &info,
BakedCmdListInfo::ExecuteData &exec)
size_t nodeIdx)
{
rdcarray<D3D12EventNode> &eventNodes = info.eventNodes;
D3D12EventNode &baseActionNode = eventNodes[nodeIdx];
const D3D12ExecuteData &exec = baseActionNode.executeData;
WrappedID3D12CommandSignature *comSig = exec.sig;
uint32_t count = exec.maxCount;
@@ -3861,40 +3845,72 @@ void WrappedID3D12GraphicsCommandList::FinaliseExecuteIndirectEvents(BakedCmdLis
if(m_pDevice->HasFatalError())
return;
rdcarray<D3D12ActionTreeNode> &actions = info.action->children;
size_t idx = 0;
uint32_t eid = exec.baseEvent;
uint32_t firstActionEid = eid;
// find the action where our execute begins
for(; idx < actions.size(); idx++)
if(actions[idx].action.eventId == firstActionEid)
break;
RDCASSERTMSG("Couldn't find base event action!", idx < actions.size(), idx, actions.size());
// patch the name for the base action
actions[idx].action.customName =
baseActionNode.action.customName =
StringFormat::Fmt("ExecuteIndirect(maxCount %u, count <%u>)", exec.maxCount, count);
// move to the first actual action of the commands
// move to the first actual event of the commands
size_t idx = nodeIdx;
idx++;
eid++;
D3D12RenderState state;
SDChunk *baseChunk = NULL;
SDFile *sdFile = m_Cmd->m_StructuredFile;
if(count > 0)
{
RDCASSERT(actions[idx].state);
size_t firstAction = idx;
// Find the first action (which should have state)
for(uint32_t a = 0; a < sigSize; ++a)
{
if(eventNodes[firstAction].action.actionId == UINT32_MAX)
break;
firstAction++;
}
RDCASSERT(eventNodes[firstAction].state);
state = *eventNodes[firstAction].state;
state = *actions[idx].state;
baseChunk = m_Cmd->m_StructuredFile->chunks[actions[idx].action.events[0].chunkIndex];
baseChunk = m_Cmd->m_StructuredFile->chunks[eventNodes[idx].event.chunkIndex];
}
// this can be negative if count is 0
int32_t countExtraActions = count - exec.reservedCount;
// exec.reservedCount copies of the signatuire were reserved for the indirect count actions
// if we ended up with a different number countExtraNodes will be non-zero,
// we need to adjust and either remove the nodes we allocated (if no actions happened)
// or clone the nodes to create more that we can then patch.
if(countExtraActions != 0)
{
if(count == 0)
{
// idx is the start of the signature nodes
eventNodes.erase(idx, sigSize);
}
else if(countExtraActions > 0)
{
size_t baseCommandStart = idx;
// We need to clone the signature nodes countExtraNode times
size_t countExtraNodes = countExtraActions * sigSize;
sdFile->chunks.reserve(sdFile->chunks.size() + countExtraNodes);
// Insert space for the new nodes
eventNodes.resize(eventNodes.size() + countExtraNodes);
size_t endActionNode = idx + sigSize;
for(size_t e = eventNodes.size() - 1; e > endActionNode; e--)
eventNodes[e] = std::move(eventNodes[e - countExtraNodes]);
size_t newIdx = endActionNode;
for(size_t extra = 0; extra < countExtraNodes; ++extra)
{
for(uint32_t a = 0; a < sigSize; ++a)
{
// duplicate the base node
eventNodes[newIdx++] = eventNodes[baseCommandStart + a];
}
}
}
}
size_t countNodes = eventNodes.size();
for(uint32_t i = 0; i < count; i++)
{
byte *data = mapPtr + exec.argOffs;
@@ -3904,26 +3920,14 @@ void WrappedID3D12GraphicsCommandList::FinaliseExecuteIndirectEvents(BakedCmdLis
{
const D3D12_INDIRECT_ARGUMENT_DESC &arg = comSig->sig.arguments[a];
ActionDescription &curAction = actions[idx].action;
APIEvent *curEvent = NULL;
for(APIEvent &ev : curAction.events)
if(idx >= countNodes)
{
if(ev.eventId == eid)
{
curEvent = &ev;
break;
}
RDCERR("Couldn't find child event %u in current action while patching ExecuteIndirect", idx);
break;
}
APIEvent dummy;
if(!curEvent)
{
RDCERR("Couldn't find EID %u in current action while patching ExecuteIndirect", eid);
// assign a dummy so we don't have to NULL-check below
curEvent = &dummy;
}
D3D12EventNode &eventNode = eventNodes[idx];
ActionDescription &curAction = eventNodes[idx].action;
SDChunk *fakeChunk = new SDChunk(""_lit);
fakeChunk->metadata = baseChunk->metadata;
@@ -3958,17 +3962,7 @@ void WrappedID3D12GraphicsCommandList::FinaliseExecuteIndirectEvents(BakedCmdLis
structuriser.Serialise("ArgumentData"_lit, *args).Important();
// if this is the first action of the indirect, we could have picked up previous
// non-indirect events in this action, so the EID will be higher than we expect. Just
// assign the action's EID
eid = curAction.eventId;
m_Cmd->AddUsage(state, actions[idx]);
// advance
idx++;
eid++;
m_Cmd->AddUsage(state, eventNode);
break;
}
case D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED:
@@ -3991,17 +3985,7 @@ void WrappedID3D12GraphicsCommandList::FinaliseExecuteIndirectEvents(BakedCmdLis
structuriser.Serialise("ArgumentData"_lit, *args).Important();
// if this is the first action of the indirect, we could have picked up previous
// non-indirect events in this action, so the EID will be higher than we expect. Just
// assign the action's EID
eid = curAction.eventId;
m_Cmd->AddUsage(state, actions[idx]);
// advance
idx++;
eid++;
m_Cmd->AddUsage(state, eventNode);
break;
}
case D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH:
@@ -4021,17 +4005,7 @@ void WrappedID3D12GraphicsCommandList::FinaliseExecuteIndirectEvents(BakedCmdLis
structuriser.Serialise("ArgumentData"_lit, *args).Important();
// if this is the first action of the indirect, we could have picked up previous
// non-indirect events in this action, so the EID will be higher than we expect. Just
// assign the action's EID
eid = curAction.eventId;
m_Cmd->AddUsage(state, actions[idx]);
// advance
idx++;
eid++;
m_Cmd->AddUsage(state, eventNode);
break;
}
case D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH_MESH:
@@ -4052,17 +4026,7 @@ void WrappedID3D12GraphicsCommandList::FinaliseExecuteIndirectEvents(BakedCmdLis
structuriser.Serialise("ArgumentData"_lit, *args).Important();
// if this is the first action of the indirect, we could have picked up previous
// non-indirect events in this action, so the EID will be higher than we expect. Just
// assign the action's EID
eid = curAction.eventId;
m_Cmd->AddUsage(state, actions[idx]);
// advance
idx++;
eid++;
m_Cmd->AddUsage(state, eventNode);
break;
}
case D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH_RAYS:
@@ -4100,17 +4064,7 @@ void WrappedID3D12GraphicsCommandList::FinaliseExecuteIndirectEvents(BakedCmdLis
structuriser.Serialise("ArgumentData"_lit, *args).Important();
// if this is the first action of the indirect, we could have picked up previous
// non-indirect events in this action, so the EID will be higher than we expect. Just
// assign the action's EID
eid = curAction.eventId;
m_Cmd->AddUsage(state, actions[idx]);
// advance
idx++;
eid++;
m_Cmd->AddUsage(state, eventNode);
break;
}
case D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT:
@@ -4134,14 +4088,11 @@ void WrappedID3D12GraphicsCommandList::FinaliseExecuteIndirectEvents(BakedCmdLis
state.compute.sigelems[arg.Constant.RootParameterIndex].SetConstants(
arg.Constant.Num32BitValuesToSet, data32, arg.Constant.DestOffsetIn32BitValues);
}
// advance only the EID, since we're still in the same action
eid++;
break;
}
case D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW:
{
// This modifies the mapped data via vb
D3D12_VERTEX_BUFFER_VIEW *vb = (D3D12_VERTEX_BUFFER_VIEW *)data;
data += sizeof(D3D12_VERTEX_BUFFER_VIEW);
@@ -4165,10 +4116,6 @@ void WrappedID3D12GraphicsCommandList::FinaliseExecuteIndirectEvents(BakedCmdLis
fakeChunk->name = StringFormat::Fmt("[%u] arg%u: IndirectIASetVertexBuffer", i, a);
structuriser.Serialise("ArgumentData"_lit, *vb).Important();
// advance only the EID, since we're still in the same action
eid++;
break;
}
case D3D12_INDIRECT_ARGUMENT_TYPE_INDEX_BUFFER_VIEW:
@@ -4193,10 +4140,6 @@ void WrappedID3D12GraphicsCommandList::FinaliseExecuteIndirectEvents(BakedCmdLis
fakeChunk->name = StringFormat::Fmt("[%u] arg%u: IndirectIASetIndexBuffer", i, a);
structuriser.Serialise("ArgumentData"_lit, *ib).Important();
// advance only the EID, since we're still in the same action
eid++;
break;
}
case D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT_BUFFER_VIEW:
@@ -4243,42 +4186,22 @@ void WrappedID3D12GraphicsCommandList::FinaliseExecuteIndirectEvents(BakedCmdLis
D3D12BufferLocation buf = *addr;
structuriser.Serialise("ArgumentData"_lit, buf).Important();
// advance only the EID, since we're still in the same action
eid++;
break;
}
default: RDCERR("Unexpected argument type! %d", arg.Type); break;
}
}
// Set the chunk data
sdFile->chunks.push_back(fakeChunk);
m_Cmd->m_StructuredFile->chunks.push_back(fakeChunk);
eventNode.event.chunkIndex = uint32_t(sdFile->chunks.size() - 1);
curEvent->chunkIndex = uint32_t(m_Cmd->m_StructuredFile->chunks.size() - 1);
++idx;
}
}
range.End = range.Begin = 0;
exec.argBuf->Unmap(0, &range);
// remove excesss actions if count < maxCount
if(count < exec.maxCount)
{
uint32_t shiftEID = (exec.maxCount - count) * sigSize;
uint32_t lastEID = exec.baseEvent + 1 + sigSize * exec.maxCount;
uint32_t shiftActionID = 0;
while(idx + shiftActionID < actions.size() &&
actions[idx + shiftActionID].action.eventId < lastEID)
shiftActionID++;
actions.erase(idx, shiftActionID);
// shift all subsequent EIDs and action IDs so they're contiguous
info.ShiftForRemoved(shiftActionID, shiftEID, idx);
}
}
template <typename SerialiserType>
@@ -4579,8 +4502,9 @@ bool WrappedID3D12GraphicsCommandList::Serialise_ExecuteIndirect(
barriers.Apply(list);
SaveExecuteIndirectParameters(list, pCommandSignature, MaxCommandCount, pArgumentBuffer,
ArgumentBufferOffset, pCountBuffer, CountBufferOffset);
D3D12ExecuteData execData =
SaveExecuteIndirectParameters(list, pCommandSignature, MaxCommandCount, pArgumentBuffer,
ArgumentBufferOffset, pCountBuffer, CountBufferOffset);
barriers.Unapply(list);
@@ -4629,19 +4553,25 @@ bool WrappedID3D12GraphicsCommandList::Serialise_ExecuteIndirect(
action.flags |= ActionFlags::MultiAction | ActionFlags::PushMarker;
m_Cmd->AddAction(action);
cmdInfo.curEventID++;
D3D12ActionTreeNode &actionNode = m_Cmd->GetActionStack().back()->children.back();
D3D12EventNode &eventNode = m_Cmd->GetLastEventNode();
eventNode.executeData = execData;
eventNode.hasExecuteData = true;
cmdInfo.hasExecuteDatas = true;
actionNode.resourceUsage.push_back(
make_rdcpair(GetResID(pArgumentBuffer),
EventUsage(actionNode.action.eventId, ResourceUsage::Indirect)));
eventNode.resourceUsage.push_back(
make_rdcpair(GetResID(pArgumentBuffer), ResourceUsage::Indirect));
if(pCountBuffer)
actionNode.resourceUsage.push_back(make_rdcpair(
GetResID(pCountBuffer), EventUsage(actionNode.action.eventId, ResourceUsage::Indirect)));
{
eventNode.resourceUsage.push_back(
make_rdcpair(GetResID(pCountBuffer), ResourceUsage::Indirect));
}
}
for(uint32_t i = 0; i < MaxCommandCount; i++)
// For variable count indirects only allocate up to one indirect command to avoid pessimistic
// allocation if MaxCommandCount is very high but the actual action count is low.
uint32_t maxCountCmds = execData.reservedCount;
for(uint32_t i = 0; i < maxCountCmds; i++)
{
for(uint32_t a = 0; a < sigSize; a++)
{
@@ -4660,9 +4590,8 @@ bool WrappedID3D12GraphicsCommandList::Serialise_ExecuteIndirect(
ActionDescription action;
action.customName = "ExecuteIndirect";
m_Cmd->AddAction(action);
m_Cmd->GetActionStack().back()->children.back().state =
new D3D12RenderState(cmdInfo.state);
cmdInfo.curEventID++;
D3D12EventNode &eventNode = m_Cmd->GetLastEventNode();
eventNode.state = new D3D12RenderState(cmdInfo.state);
break;
}
case D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW:
@@ -4673,7 +4602,6 @@ bool WrappedID3D12GraphicsCommandList::Serialise_ExecuteIndirect(
case D3D12_INDIRECT_ARGUMENT_TYPE_UNORDERED_ACCESS_VIEW:
// add dummy event
m_Cmd->AddEvent();
cmdInfo.curEventID++;
break;
default: RDCERR("Unexpected argument type! %d", arg.Type); break;
}
@@ -4835,11 +4763,9 @@ bool WrappedID3D12GraphicsCommandList::Serialise_ClearDepthStencilView(
Subresource(GetMipForDsv(descriptor->GetDSV()), GetSliceForDsv(descriptor->GetDSV()));
m_Cmd->AddAction(action);
D3D12ActionTreeNode &actionNode = m_Cmd->GetActionStack().back()->children.back();
actionNode.resourceUsage.push_back(
make_rdcpair(descriptor->GetResResourceId(),
EventUsage(actionNode.action.eventId, ResourceUsage::Clear)));
D3D12EventNode &eventNode = m_Cmd->GetLastEventNode();
eventNode.resourceUsage.push_back(
make_rdcpair(descriptor->GetResResourceId(), ResourceUsage::Clear));
}
}
}
@@ -4936,11 +4862,9 @@ bool WrappedID3D12GraphicsCommandList::Serialise_ClearRenderTargetView(
Subresource(GetMipForRtv(descriptor->GetRTV()), GetSliceForRtv(descriptor->GetRTV()));
m_Cmd->AddAction(action);
D3D12ActionTreeNode &actionNode = m_Cmd->GetActionStack().back()->children.back();
actionNode.resourceUsage.push_back(
make_rdcpair(descriptor->GetResResourceId(),
EventUsage(actionNode.action.eventId, ResourceUsage::Clear)));
D3D12EventNode &eventNode = m_Cmd->GetLastEventNode();
eventNode.resourceUsage.push_back(
make_rdcpair(descriptor->GetResResourceId(), ResourceUsage::Clear));
}
}
}
@@ -5040,10 +4964,8 @@ bool WrappedID3D12GraphicsCommandList::Serialise_ClearUnorderedAccessViewUint(
m_Cmd->AddAction(action);
D3D12ActionTreeNode &actionNode = m_Cmd->GetActionStack().back()->children.back();
actionNode.resourceUsage.push_back(make_rdcpair(
GetResID(pResource), EventUsage(actionNode.action.eventId, ResourceUsage::Clear)));
D3D12EventNode &eventNode = m_Cmd->GetLastEventNode();
eventNode.resourceUsage.push_back(make_rdcpair(GetResID(pResource), ResourceUsage::Clear));
}
}
}
@@ -5151,10 +5073,8 @@ bool WrappedID3D12GraphicsCommandList::Serialise_ClearUnorderedAccessViewFloat(
m_Cmd->AddAction(action);
D3D12ActionTreeNode &actionNode = m_Cmd->GetActionStack().back()->children.back();
actionNode.resourceUsage.push_back(make_rdcpair(
GetResID(pResource), EventUsage(actionNode.action.eventId, ResourceUsage::Clear)));
D3D12EventNode &eventNode = m_Cmd->GetLastEventNode();
eventNode.resourceUsage.push_back(make_rdcpair(GetResID(pResource), ResourceUsage::Clear));
}
}
}
@@ -5240,10 +5160,8 @@ bool WrappedID3D12GraphicsCommandList::Serialise_DiscardResource(SerialiserType
m_Cmd->AddAction(action);
D3D12ActionTreeNode &actionNode = m_Cmd->GetActionStack().back()->children.back();
actionNode.resourceUsage.push_back(make_rdcpair(
GetResID(pResource), EventUsage(actionNode.action.eventId, ResourceUsage::Discard)));
D3D12EventNode &eventNode = m_Cmd->GetLastEventNode();
eventNode.resourceUsage.push_back(make_rdcpair(GetResID(pResource), ResourceUsage::Discard));
}
}
}
@@ -5327,19 +5245,18 @@ bool WrappedID3D12GraphicsCommandList::Serialise_CopyBufferRegion(SerialiserType
m_Cmd->AddAction(action);
D3D12ActionTreeNode &actionNode = m_Cmd->GetActionStack().back()->children.back();
D3D12EventNode &eventNode = m_Cmd->GetLastEventNode();
if(pSrcBuffer == pDstBuffer)
{
actionNode.resourceUsage.push_back(make_rdcpair(
GetResID(pSrcBuffer), EventUsage(actionNode.action.eventId, ResourceUsage::Copy)));
eventNode.resourceUsage.push_back(make_rdcpair(GetResID(pSrcBuffer), ResourceUsage::Copy));
}
else
{
actionNode.resourceUsage.push_back(make_rdcpair(
GetResID(pSrcBuffer), EventUsage(actionNode.action.eventId, ResourceUsage::CopySrc)));
actionNode.resourceUsage.push_back(make_rdcpair(
GetResID(pDstBuffer), EventUsage(actionNode.action.eventId, ResourceUsage::CopyDst)));
eventNode.resourceUsage.push_back(
make_rdcpair(GetResID(pSrcBuffer), ResourceUsage::CopySrc));
eventNode.resourceUsage.push_back(
make_rdcpair(GetResID(pDstBuffer), ResourceUsage::CopyDst));
}
}
}
@@ -5444,19 +5361,16 @@ bool WrappedID3D12GraphicsCommandList::Serialise_CopyTextureRegion(
m_Cmd->AddAction(action);
D3D12ActionTreeNode &actionNode = m_Cmd->GetActionStack().back()->children.back();
D3D12EventNode &eventNode = m_Cmd->GetLastEventNode();
if(origSrc == origDst)
{
actionNode.resourceUsage.push_back(
make_rdcpair(liveSrc, EventUsage(actionNode.action.eventId, ResourceUsage::Copy)));
eventNode.resourceUsage.push_back(make_rdcpair(liveSrc, ResourceUsage::Copy));
}
else
{
actionNode.resourceUsage.push_back(
make_rdcpair(liveSrc, EventUsage(actionNode.action.eventId, ResourceUsage::CopySrc)));
actionNode.resourceUsage.push_back(
make_rdcpair(liveDst, EventUsage(actionNode.action.eventId, ResourceUsage::CopyDst)));
eventNode.resourceUsage.push_back(make_rdcpair(liveSrc, ResourceUsage::CopySrc));
eventNode.resourceUsage.push_back(make_rdcpair(liveDst, ResourceUsage::CopyDst));
}
}
}
@@ -5539,19 +5453,18 @@ bool WrappedID3D12GraphicsCommandList::Serialise_CopyResource(SerialiserType &se
m_Cmd->AddAction(action);
D3D12ActionTreeNode &actionNode = m_Cmd->GetActionStack().back()->children.back();
D3D12EventNode &eventNode = m_Cmd->GetLastEventNode();
if(pSrcResource == pDstResource)
{
actionNode.resourceUsage.push_back(make_rdcpair(
GetResID(pSrcResource), EventUsage(actionNode.action.eventId, ResourceUsage::Copy)));
eventNode.resourceUsage.push_back(make_rdcpair(GetResID(pSrcResource), ResourceUsage::Copy));
}
else
{
actionNode.resourceUsage.push_back(make_rdcpair(
GetResID(pSrcResource), EventUsage(actionNode.action.eventId, ResourceUsage::CopySrc)));
actionNode.resourceUsage.push_back(make_rdcpair(
GetResID(pDstResource), EventUsage(actionNode.action.eventId, ResourceUsage::CopyDst)));
eventNode.resourceUsage.push_back(
make_rdcpair(GetResID(pSrcResource), ResourceUsage::CopySrc));
eventNode.resourceUsage.push_back(
make_rdcpair(GetResID(pDstResource), ResourceUsage::CopyDst));
}
}
}
@@ -5637,21 +5550,19 @@ bool WrappedID3D12GraphicsCommandList::Serialise_ResolveSubresource(
m_Cmd->AddAction(action);
D3D12ActionTreeNode &actionNode = m_Cmd->GetActionStack().back()->children.back();
D3D12EventNode &eventNode = m_Cmd->GetLastEventNode();
if(pSrcResource == pDstResource)
{
actionNode.resourceUsage.push_back(make_rdcpair(
GetResID(pSrcResource), EventUsage(actionNode.action.eventId, ResourceUsage::Resolve)));
eventNode.resourceUsage.push_back(
make_rdcpair(GetResID(pSrcResource), ResourceUsage::Resolve));
}
else
{
actionNode.resourceUsage.push_back(
make_rdcpair(GetResID(pSrcResource),
EventUsage(actionNode.action.eventId, ResourceUsage::ResolveSrc)));
actionNode.resourceUsage.push_back(
make_rdcpair(GetResID(pDstResource),
EventUsage(actionNode.action.eventId, ResourceUsage::ResolveDst)));
eventNode.resourceUsage.push_back(
make_rdcpair(GetResID(pSrcResource), ResourceUsage::ResolveSrc));
eventNode.resourceUsage.push_back(
make_rdcpair(GetResID(pDstResource), ResourceUsage::ResolveDst));
}
}
}
@@ -5756,12 +5667,9 @@ bool WrappedID3D12GraphicsCommandList::Serialise_CopyTiles(
m_Cmd->AddAction(action);
D3D12ActionTreeNode &actionNode = m_Cmd->GetActionStack().back()->children.back();
actionNode.resourceUsage.push_back(
make_rdcpair(liveSrc, EventUsage(actionNode.action.eventId, ResourceUsage::CopySrc)));
actionNode.resourceUsage.push_back(
make_rdcpair(liveDst, EventUsage(actionNode.action.eventId, ResourceUsage::CopyDst)));
D3D12EventNode &eventNode = m_Cmd->GetLastEventNode();
eventNode.resourceUsage.push_back(make_rdcpair(liveSrc, ResourceUsage::CopySrc));
eventNode.resourceUsage.push_back(make_rdcpair(liveDst, ResourceUsage::CopyDst));
}
}
}
+1 -1
View File
@@ -225,7 +225,7 @@ public:
D3D12ResourceRecord *GetCreationRecord() { return m_CreationRecord; }
WrappedID3D12Device *GetWrappedDevice() { return m_pDevice; }
const rdcarray<D3D12ResourceRecord *> &GetCmdLists() { return m_CmdListRecords; }
D3D12ActionTreeNode &GetParentAction() { return m_Cmd.m_ParentAction; }
void BakeEventNodes(ActionDescription &rootAction) { return m_Cmd.BakeEventNodes(rootAction); }
const APIEvent &GetEvent(uint32_t eventId);
uint32_t GetMaxEID() { return m_Cmd.m_Events.back().eventId; }
void ClearAfterCapture();
@@ -460,8 +460,9 @@ bool WrappedID3D12CommandQueue::Serialise_ExecuteCommandLists(SerialiserType &se
if(m_pDevice->GetReplayOptions().apiValidation)
DebugMessages.clear();
D3D12EventNode &eventNode = m_Cmd.m_LoadingEventNode;
for(const DebugMessage &msg : DebugMessages)
m_Cmd.m_EventMessages.push_back(msg);
eventNode.debugMessages.push_back(msg);
}
}
@@ -487,9 +488,6 @@ bool WrappedID3D12CommandQueue::Serialise_ExecuteCommandLists(SerialiserType &se
{
m_Cmd.AddEvent();
// we're adding multiple events, need to increment ourselves
m_Cmd.m_RootEventID++;
for(uint32_t i = 0; i < NumCommandLists; i++)
{
ResourceId cmd = GetResID(ppCommandLists[i]);
@@ -583,17 +581,13 @@ bool WrappedID3D12CommandQueue::Serialise_ExecuteCommandLists(SerialiserType &se
}
}
if(!info.executeEvents.empty())
if(info.hasExecuteDatas)
{
// ensure all GPU work has finished for readback of arguments
m_pDevice->DeviceWaitForIdle();
if(m_pDevice->HasFatalError())
return false;
// readback the patch buffer and update recorded events
for(size_t c = 0; c < info.executeEvents.size(); c++)
m_ReplayList->FinaliseExecuteIndirectEvents(info, info.executeEvents[c]);
}
}
@@ -620,56 +614,16 @@ bool WrappedID3D12CommandQueue::Serialise_ExecuteCommandLists(SerialiserType &se
ActionFlags::BeginPass;
m_Cmd.AddEvent();
m_Cmd.m_RootEvents.back().chunkIndex = cmdListInfo.beginChunk;
m_Cmd.m_Events.back().chunkIndex = cmdListInfo.beginChunk;
m_Cmd.AddAction(action);
m_Cmd.m_RootEventID++;
D3D12EventNode &eventNode = m_Cmd.GetLastEventNode();
eventNode.event.chunkIndex = cmdListInfo.beginChunk;
eventNode.addActionUse = false;
eventNode.addPrimaryExecute = true;
eventNode.primaryCmdId = cmd;
}
// insert the baked command list in-line into this list of nodes, assigning new event and
// drawIDs
m_Cmd.InsertActionsAndRefreshIDs(cmd, cmdListInfo);
for(size_t e = 0; e < cmdListInfo.action->executedCmds.size(); e++)
{
rdcarray<uint32_t> &submits = m_Cmd.m_Partial[D3D12CommandData::Secondary]
.cmdListExecs[cmdListInfo.action->executedCmds[e]];
for(size_t s = 0; s < submits.size(); s++)
submits[s] += m_Cmd.m_RootEventID;
}
for(size_t i = 0; i < cmdListInfo.debugMessages.size(); i++)
{
DebugMessage msg = cmdListInfo.debugMessages[i];
msg.eventId += m_Cmd.m_RootEventID;
m_pDevice->AddDebugMessage(msg);
}
// only primary command lists can be submitted
m_Cmd.m_Partial[D3D12CommandData::Primary].cmdListExecs[cmd].push_back(m_Cmd.m_RootEventID);
// pull in any remaining events on the command buffer that weren't added to an action
for(size_t e = 0; e < cmdListInfo.curEvents.size(); e++)
{
APIEvent apievent = cmdListInfo.curEvents[e];
apievent.eventId += m_Cmd.m_RootEventID;
m_Cmd.m_RootEvents.push_back(apievent);
m_Cmd.m_Events.resize_for_index(apievent.eventId);
m_Cmd.m_Events[apievent.eventId] = apievent;
}
for(auto it = cmdListInfo.resourceUsage.begin(); it != cmdListInfo.resourceUsage.end(); ++it)
{
EventUsage u = it->second;
u.eventId += m_Cmd.m_RootEventID;
m_Cmd.m_ResourceUses[it->first].push_back(u);
}
m_Cmd.m_RootEventID += cmdListInfo.eventCount;
m_Cmd.m_RootActionID += cmdListInfo.actionCount;
// insert the baked command buffer into the root events, resolving indirect actions
SDObject *localAnnotations = m_Cmd.InsertEventNodes(m_ReplayList, cmd, cmdListInfo);
{
action.customName =
@@ -678,11 +632,25 @@ bool WrappedID3D12CommandQueue::Serialise_ExecuteCommandLists(SerialiserType &se
ActionFlags::CommandBufferBoundary | ActionFlags::PassBoundary | ActionFlags::EndPass;
m_Cmd.AddEvent();
m_Cmd.m_RootEvents.back().chunkIndex = cmdListInfo.endChunk;
m_Cmd.m_Events.back().chunkIndex = cmdListInfo.endChunk;
m_Cmd.AddAction(action);
m_Cmd.m_RootEventID++;
D3D12EventNode &eventNode = m_Cmd.GetLastEventNode();
eventNode.event.chunkIndex = cmdListInfo.endChunk;
eventNode.addActionUse = false;
if(localAnnotations)
{
// Modify using the annotations stored in the event node
for(const PendingAnnotation &annot : cmdListInfo.pendingAnnotations)
{
if(annot.valueType == eRENDERDOC_Empty)
localAnnotations->EraseChildByKeyPath(annot.key);
else
WriteAnnotation(localAnnotations->CreateChildByKeyPath(annot.key), annot.valueType,
annot.valueVectorWidth, annot.value);
}
eventNode.event.annotations = localAnnotations->Duplicate();
delete localAnnotations;
}
}
}
@@ -703,12 +671,10 @@ bool WrappedID3D12CommandQueue::Serialise_ExecuteCommandLists(SerialiserType &se
ResourceId cmd = GetResID(ppCommandLists[c]);
m_Cmd.m_RootEventID += m_Cmd.m_BakedCmdListInfo[cmd].eventCount;
m_Cmd.m_RootActionID += m_Cmd.m_BakedCmdListInfo[cmd].actionCount;
// 2 extra for the virtual labels around the command list
{
m_Cmd.m_RootEventID += 2;
m_Cmd.m_RootActionID += 2;
}
}
@@ -1321,9 +1287,6 @@ bool WrappedID3D12CommandQueue::Serialise_BeginEvent(SerialiserType &ser, UINT M
m_Cmd.AddEvent();
m_Cmd.AddAction(action);
// now push the action stack
m_Cmd.GetActionStack().push_back(&m_Cmd.GetActionStack().back()->children.back());
}
}
@@ -1365,9 +1328,6 @@ bool WrappedID3D12CommandQueue::Serialise_EndEvent(SerialiserType &ser)
m_Cmd.AddEvent();
m_Cmd.AddAction(action);
if(m_Cmd.GetActionStack().size() > 1)
m_Cmd.GetActionStack().pop_back();
}
}
+196 -214
View File
@@ -740,7 +740,11 @@ const APIEvent &WrappedID3D12CommandQueue::GetEvent(uint32_t eventId)
bool WrappedID3D12CommandQueue::ProcessChunk(ReadSerialiser &ser, D3D12Chunk chunk)
{
m_Cmd.m_AddedAction = false;
if(IsLoading(m_State))
{
m_Cmd.m_AddedEventNode = false;
m_Cmd.m_LoadingEventNode = D3D12EventNode();
}
bool ret = false;
@@ -1129,13 +1133,11 @@ bool WrappedID3D12CommandQueue::ProcessChunk(ReadSerialiser &ser, D3D12Chunk chu
}
else
{
if(!m_Cmd.m_AddedAction)
if(!m_Cmd.m_AddedEventNode)
m_Cmd.AddEvent();
}
}
m_Cmd.m_AddedAction = false;
return ret;
}
@@ -1192,8 +1194,6 @@ RDResult WrappedID3D12CommandQueue::ReplayLog(CaptureState readType, uint32_t st
ser.EndChunk();
m_Cmd.m_RootEvents.clear();
if(IsLoading(m_State))
{
m_pDevice->ApplyInitialContents();
@@ -1233,7 +1233,6 @@ RDResult WrappedID3D12CommandQueue::ReplayLog(CaptureState readType, uint32_t st
else
{
m_Cmd.m_RootEventID = 1;
m_Cmd.m_RootActionID = 1;
m_Cmd.m_FirstEventID = 0;
m_Cmd.m_LastEventID = ~0U;
}
@@ -1757,49 +1756,6 @@ HRESULT STDMETHODCALLTYPE WrappedID3D12GraphicsCommandList::QueryInterface(REFII
return m_RefCounter.QueryInterface("ID3D12GraphicsCommandList", riid, ppvObject);
}
void BakedCmdListInfo::ShiftForRemoved(uint32_t shiftActionID, uint32_t shiftEID, size_t idx)
{
rdcarray<D3D12ActionTreeNode> &actions = action->children;
actionCount -= shiftActionID;
eventCount -= shiftEID;
if(idx < actions.size())
{
for(size_t i = idx; i < actions.size(); i++)
{
// should have no children as we don't push in for markers since they
// can cross command list boundaries.
RDCASSERT(actions[i].children.empty());
actions[i].action.eventId -= shiftEID;
actions[i].action.actionId -= shiftActionID;
for(APIEvent &ev : actions[i].action.events)
ev.eventId -= shiftEID;
for(size_t u = 0; u < actions[i].resourceUsage.size(); u++)
actions[i].resourceUsage[u].second.eventId -= shiftEID;
}
uint32_t lastEID = actions[idx].action.eventId;
// shift any resource usage for actions after the removed section
// patch any subsequent executes
for(size_t i = 0; i < executeEvents.size(); i++)
{
if(executeEvents[i].baseEvent >= lastEID)
executeEvents[i].baseEvent -= shiftEID;
}
}
for(size_t i = 0; i < curEvents.size(); i++)
{
curEvents[i].eventId -= shiftEID;
}
}
SubresourceStateVector BakedCmdListInfo::GetState(WrappedID3D12Device *device, ResourceId id)
{
std::map<ResourceId, SubresourceStateVector> data;
@@ -1835,7 +1791,6 @@ D3D12CommandData::D3D12CommandData()
m_IndirectOffset = 0;
m_RootEventID = 1;
m_RootActionID = 1;
m_FirstEventID = 0;
m_LastEventID = ~0U;
@@ -1845,9 +1800,7 @@ D3D12CommandData::D3D12CommandData()
m_ActionCallback = NULL;
m_AddedAction = false;
m_RootActionStack.push_back(&m_ParentAction);
m_AddedEventNode = false;
}
void D3D12CommandData::GetIndirectBuffer(size_t size, ID3D12Resource **buf, uint64_t *offs)
@@ -2018,74 +1971,57 @@ ID3D12GraphicsCommandListX *D3D12CommandData::RerecordCmdList(ResourceId cmdid,
void D3D12CommandData::AddEvent()
{
APIEvent apievent;
rdcarray<D3D12EventNode> &eventNodes =
(m_LastCmdListID != ResourceId() ? m_BakedCmdListInfo[m_LastCmdListID].eventNodes
: m_EventNodes);
eventNodes.emplace_back(m_LoadingEventNode);
m_LoadingEventNode = D3D12EventNode();
apievent.fileOffset = m_CurChunkOffset;
apievent.eventId = m_LastCmdListID != ResourceId() ? m_BakedCmdListInfo[m_LastCmdListID].curEventID
: m_RootEventID;
D3D12EventNode &node = eventNodes.back();
apievent.chunkIndex = uint32_t(m_StructuredFile->chunks.size() - 1);
// if we're using replay-time debug messages, fetch them now since we can do better to correlate
// to events on replay
// if we're using replay-time debug messages, fetch them now since we can do better to correlate to events on replay
if(m_pDevice->GetReplayOptions().apiValidation)
m_EventMessages = m_pDevice->GetDebugMessages();
for(size_t i = 0; i < m_EventMessages.size(); i++)
m_EventMessages[i].eventId = apievent.eventId;
node.debugMessages = m_pDevice->GetDebugMessages();
APIEvent &apievent = node.event;
apievent.fileOffset = m_CurChunkOffset;
apievent.chunkIndex = uint32_t(m_StructuredFile->chunks.size() - 1);
// event IDs start from one not zero
apievent.eventId = (uint32_t)eventNodes.count();
if(m_LastCmdListID != ResourceId())
{
m_BakedCmdListInfo[m_LastCmdListID].curEvents.push_back(apievent);
rdcarray<DebugMessage> &msgs = m_BakedCmdListInfo[m_LastCmdListID].debugMessages;
msgs.append(m_EventMessages);
node.annotations.swap(m_BakedCmdListInfo[m_LastCmdListID].pendingAnnotations);
}
else
{
if(m_RootAnnotation)
{
apievent.annotations = m_RootAnnotation->Duplicate();
m_EventAnnotations.push_back(apievent.annotations);
}
m_RootEvents.push_back(apievent);
m_Events.resize_for_index(apievent.eventId);
m_Events[apievent.eventId] = apievent;
for(auto it = m_EventMessages.begin(); it != m_EventMessages.end(); ++it)
m_pDevice->AddDebugMessage(*it);
}
m_EventMessages.clear();
m_AddedEventNode = true;
}
void D3D12CommandData::AddResourceUsage(D3D12ActionTreeNode &actionNode, ResourceId id,
uint32_t EID, ResourceUsage usage)
void D3D12CommandData::AddResourceUsage(D3D12EventNode &eventNode, ResourceId id, ResourceUsage usage)
{
if(id == ResourceId())
return;
actionNode.resourceUsage.push_back(make_rdcpair(id, EventUsage(EID, usage)));
eventNode.resourceUsage.push_back(make_rdcpair(id, usage));
}
void D3D12CommandData::AddCPUUsage(ResourceId id, ResourceUsage usage)
{
m_ResourceUses[id].push_back(EventUsage(m_RootEventID, usage));
m_LoadingEventNode.resourceUsage.push_back(make_rdcpair<ResourceId, ResourceUsage>(id, usage));
}
void D3D12CommandData::AddUsageForBindInRootSig(const D3D12RenderState &state,
D3D12ActionTreeNode &actionNode,
D3D12EventNode &eventNode,
const D3D12RenderState::RootSignature *rootsig,
D3D12_DESCRIPTOR_RANGE_TYPE type, uint32_t space,
uint32_t bind, uint32_t rangeSize)
{
static bool hugeRangeWarned = false;
ActionDescription &a = actionNode.action;
uint32_t eid = a.eventId;
// use a 'clamped' range size to avoid annoying overflow issues
rangeSize = RDCMIN(rangeSize, 0x10000000U);
@@ -2128,7 +2064,7 @@ void D3D12CommandData::AddUsageForBindInRootSig(const D3D12RenderState &state,
type == D3D12_DESCRIPTOR_RANGE_TYPE_CBV && p.Descriptor.RegisterSpace == space &&
p.Descriptor.ShaderRegister >= bind && p.Descriptor.ShaderRegister < bind + rangeSize)
{
AddResourceUsage(actionNode, el.id, eid, cb);
AddResourceUsage(eventNode, el.id, cb);
// common case - root element matches 1:1 with a non-array shader bind, if so we can exit. If
// not we might have to continue since other parts of it might be mapped to a table, or
@@ -2140,7 +2076,7 @@ void D3D12CommandData::AddUsageForBindInRootSig(const D3D12RenderState &state,
type == D3D12_DESCRIPTOR_RANGE_TYPE_SRV && p.Descriptor.RegisterSpace == space &&
p.Descriptor.ShaderRegister >= bind && p.Descriptor.ShaderRegister < bind + rangeSize)
{
AddResourceUsage(actionNode, el.id, eid, ro);
AddResourceUsage(eventNode, el.id, ro);
// common case - root element matches 1:1 with a non-array shader bind, if so we can exit. If
// not we might have to continue since other parts of it might be mapped to a table, or
@@ -2152,7 +2088,7 @@ void D3D12CommandData::AddUsageForBindInRootSig(const D3D12RenderState &state,
type == D3D12_DESCRIPTOR_RANGE_TYPE_UAV && p.Descriptor.RegisterSpace == space &&
p.Descriptor.ShaderRegister >= bind && p.Descriptor.ShaderRegister < bind + rangeSize)
{
AddResourceUsage(actionNode, el.id, eid, rw);
AddResourceUsage(eventNode, el.id, rw);
// common case - root element matches 1:1 with a non-array shader bind, if so we can exit. If
// not we might have to continue since other parts of it might be mapped to a table, or
@@ -2225,13 +2161,11 @@ void D3D12CommandData::AddUsageForBindInRootSig(const D3D12RenderState &state,
if(range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_CBV)
{
EventUsage usage(eid, cb);
for(UINT i = 0; i < num && i < rangeSize; i++)
{
ResourceId id = WrappedID3D12Resource::GetResIDFromAddr(desc->GetCBV().BufferLocation);
AddResourceUsage(actionNode, id, eid, cb);
AddResourceUsage(eventNode, id, cb);
desc++;
}
@@ -2243,7 +2177,7 @@ void D3D12CommandData::AddUsageForBindInRootSig(const D3D12RenderState &state,
for(UINT i = 0; i < num && i < rangeSize; i++)
{
AddResourceUsage(actionNode, desc->GetResResourceId(), eid, usage);
AddResourceUsage(eventNode, desc->GetResResourceId(), usage);
desc++;
}
@@ -2258,11 +2192,9 @@ void D3D12CommandData::AddUsageForBindInRootSig(const D3D12RenderState &state,
}
}
void D3D12CommandData::AddUsage(const D3D12RenderState &state, D3D12ActionTreeNode &actionNode)
void D3D12CommandData::AddUsage(const D3D12RenderState &state, D3D12EventNode &eventNode)
{
ActionDescription &a = actionNode.action;
uint32_t eid = a.eventId;
ActionDescription &a = eventNode.action;
ActionFlags DrawMask = ActionFlags::Drawcall | ActionFlags::MeshDispatch | ActionFlags::Dispatch;
if(!(a.flags & DrawMask))
@@ -2320,26 +2252,25 @@ void D3D12CommandData::AddUsage(const D3D12RenderState &state, D3D12ActionTreeNo
}
if(a.flags & ActionFlags::Indexed && state.ibuffer.buf != ResourceId())
actionNode.resourceUsage.push_back(
make_rdcpair(state.ibuffer.buf, EventUsage(eid, ResourceUsage::IndexBuffer)));
eventNode.resourceUsage.push_back(make_rdcpair(state.ibuffer.buf, ResourceUsage::IndexBuffer));
if(a.flags & ActionFlags::Drawcall)
{
for(size_t i = 0; i < state.vbuffers.size(); i++)
{
if(state.vbuffers[i].buf != ResourceId())
actionNode.resourceUsage.push_back(
make_rdcpair(state.vbuffers[i].buf, EventUsage(eid, ResourceUsage::VertexBuffer)));
eventNode.resourceUsage.push_back(
make_rdcpair(state.vbuffers[i].buf, ResourceUsage::VertexBuffer));
}
for(size_t i = 0; i < state.streamouts.size(); i++)
{
if(state.streamouts[i].buf != ResourceId())
actionNode.resourceUsage.push_back(
make_rdcpair(state.streamouts[i].buf, EventUsage(eid, ResourceUsage::StreamOut)));
eventNode.resourceUsage.push_back(
make_rdcpair(state.streamouts[i].buf, ResourceUsage::StreamOut));
if(state.streamouts[i].countbuf != ResourceId())
actionNode.resourceUsage.push_back(make_rdcpair(
state.streamouts[i].countbuf, EventUsage(eid, ResourceUsage::StreamOut)));
eventNode.resourceUsage.push_back(
make_rdcpair(state.streamouts[i].countbuf, ResourceUsage::StreamOut));
}
}
@@ -2348,14 +2279,12 @@ void D3D12CommandData::AddUsage(const D3D12RenderState &state, D3D12ActionTreeNo
for(size_t i = 0; i < rts.size(); i++)
{
if(rts[i] != ResourceId())
actionNode.resourceUsage.push_back(
make_rdcpair(rts[i], EventUsage(eid, ResourceUsage::ColorTarget)));
eventNode.resourceUsage.push_back(make_rdcpair(rts[i], ResourceUsage::ColorTarget));
}
ResourceId id = state.GetDSVID();
if(id != ResourceId())
actionNode.resourceUsage.push_back(
make_rdcpair(id, EventUsage(eid, ResourceUsage::DepthStencilTarget)));
eventNode.resourceUsage.push_back(make_rdcpair(id, ResourceUsage::DepthStencilTarget));
}
if(rootsig)
@@ -2371,34 +2300,144 @@ void D3D12CommandData::AddUsage(const D3D12RenderState &state, D3D12ActionTreeNo
for(const ConstantBlock &b : refls[sh]->constantBlocks)
{
AddUsageForBindInRootSig(state, actionNode, rootsig, D3D12_DESCRIPTOR_RANGE_TYPE_CBV,
AddUsageForBindInRootSig(state, eventNode, rootsig, D3D12_DESCRIPTOR_RANGE_TYPE_CBV,
b.fixedBindSetOrSpace, b.fixedBindNumber, b.bindArraySize);
}
for(const ShaderResource &r : refls[sh]->readOnlyResources)
{
AddUsageForBindInRootSig(state, actionNode, rootsig, D3D12_DESCRIPTOR_RANGE_TYPE_SRV,
AddUsageForBindInRootSig(state, eventNode, rootsig, D3D12_DESCRIPTOR_RANGE_TYPE_SRV,
r.fixedBindSetOrSpace, r.fixedBindNumber, r.bindArraySize);
}
for(const ShaderResource &r : refls[sh]->readWriteResources)
{
AddUsageForBindInRootSig(state, actionNode, rootsig, D3D12_DESCRIPTOR_RANGE_TYPE_UAV,
AddUsageForBindInRootSig(state, eventNode, rootsig, D3D12_DESCRIPTOR_RANGE_TYPE_UAV,
r.fixedBindSetOrSpace, r.fixedBindNumber, r.bindArraySize);
}
}
}
}
void D3D12CommandData::BakeEventNodes(ActionDescription &rootAction)
{
// EIDs start from 1
m_Events.resize(1);
uint32_t eid = 1;
uint32_t actionId = 1;
rdcarray<APIEvent> actionEvents;
rdcarray<ActionDescription *> actionStack;
actionStack.push_back(&rootAction);
ActionDescription *parentAction = actionStack.back();
std::map<ResourceId, uint32_t> cmdListStarts;
for(const D3D12EventNode &node : m_EventNodes)
{
m_Events.push_back(node.event);
APIEvent &apievent = m_Events.back();
apievent.eventId = eid;
actionEvents.push_back(apievent);
for(const DebugMessage &msg : node.debugMessages)
{
DebugMessage m(msg);
m.eventId = eid;
m_pDevice->AddDebugMessage(m);
}
if(apievent.annotations)
m_EventAnnotations.push_back(apievent.annotations);
for(auto it = node.resourceUsage.begin(); it != node.resourceUsage.end(); ++it)
{
ResourceUsage usage = it->second;
m_ResourceUses[it->first].push_back({eid, usage});
}
if(node.action.actionId == UINT32_MAX)
{
parentAction->children.push_back(node.action);
ActionDescription &action = parentAction->children.back();
RDCASSERT(action.events.isEmpty());
action.events.swap(actionEvents);
action.eventId = eid;
action.actionId = actionId;
ActionFlags flags = action.flags;
if(flags & ActionFlags::PushMarker)
{
actionStack.push_back(parentAction);
parentAction = &action;
}
if(!action.events.empty() && node.addActionUse)
{
auto it = cmdListStarts.find(node.cmdListID);
uint32_t startEID = 0;
if(it != cmdListStarts.end())
startEID = it->second;
ActionUse use(action.events.back().fileOffset, eid, node.cmdListID, eid - startEID);
// insert in sorted location
auto drawit = std::lower_bound(m_ActionUses.begin(), m_ActionUses.end(), use);
m_ActionUses.insert(drawit - m_ActionUses.begin(), use);
}
if(flags & ActionFlags::PopMarker)
{
if(actionStack.count() == 0)
{
RDCERR("Pop but the action stack is empty");
parentAction = &rootAction;
}
else
{
parentAction = actionStack.back();
RDCASSERT(parentAction);
if(!parentAction)
{
RDCERR("NULL parent on the action stack");
parentAction = &rootAction;
}
actionStack.pop_back();
}
}
// markers don't increment action ID
ActionFlags MarkerMask = ActionFlags::SetMarker | ActionFlags::PushMarker |
ActionFlags::PopMarker | ActionFlags::PassBoundary;
bool isMarker = (flags & MarkerMask) ? true : false;
if(!isMarker)
++actionId;
}
if(node.addPrimaryExecute)
{
RDCASSERT(node.primaryCmdId != ResourceId());
cmdListStarts[node.primaryCmdId] = eid + 1;
m_Partial[D3D12CommandData::Primary].cmdListExecs[node.primaryCmdId].push_back(eid + 1);
}
++eid;
}
// release the EventNodes now they are baked into actions and events
m_EventNodes.clear();
for(auto it = m_BakedCmdListInfo.begin(); it != m_BakedCmdListInfo.end(); ++it)
it->second.eventNodes.clear();
}
void D3D12CommandData::AddAction(const ActionDescription &a)
{
m_AddedAction = true;
RDCASSERT(m_AddedEventNode);
ActionDescription action = a;
action.eventId = m_LastCmdListID != ResourceId() ? m_BakedCmdListInfo[m_LastCmdListID].curEventID
: m_RootEventID;
action.actionId = m_LastCmdListID != ResourceId() ? m_BakedCmdListInfo[m_LastCmdListID].actionCount
: m_RootActionID;
D3D12EventNode &node = GetLastEventNode();
ActionDescription &action = node.action;
action = a;
for(int i = 0; i < 8; i++)
action.outputs[i] = ResourceId();
@@ -2407,6 +2446,9 @@ void D3D12CommandData::AddAction(const ActionDescription &a)
if(m_LastCmdListID != ResourceId())
{
node.addActionUse = true;
node.cmdListID = m_LastCmdListID;
rdcarray<ResourceId> rts = m_BakedCmdListInfo[m_LastCmdListID].state.GetRTVIDs();
for(size_t i = 0; i < ARRAY_COUNT(action.outputs); i++)
@@ -2420,110 +2462,50 @@ void D3D12CommandData::AddAction(const ActionDescription &a)
action.depthOut = m_BakedCmdListInfo[m_LastCmdListID].state.GetDSVID();
}
// markers don't increment action ID
ActionFlags MarkerMask = ActionFlags::SetMarker | ActionFlags::PushMarker |
ActionFlags::PopMarker | ActionFlags::PassBoundary;
if(!(action.flags & MarkerMask))
{
if(m_LastCmdListID != ResourceId())
m_BakedCmdListInfo[m_LastCmdListID].actionCount++;
else
m_RootActionID++;
}
// Mark the action as active
action.actionId = UINT32_MAX;
action.events.swap(m_LastCmdListID != ResourceId() ? m_BakedCmdListInfo[m_LastCmdListID].curEvents
: m_RootEvents);
// should have at least the root action here, push this action
// onto the back's children list.
if(!GetActionStack().empty())
{
D3D12ActionTreeNode node(action);
if(m_LastCmdListID != ResourceId())
{
node.resourceUsage.swap(m_BakedCmdListInfo[m_LastCmdListID].resourceUsage);
AddUsage(m_BakedCmdListInfo[m_LastCmdListID].state, node);
}
for(const ActionDescription &child : action.children)
node.children.push_back(D3D12ActionTreeNode(child));
GetActionStack().back()->children.push_back(node);
}
else
RDCERR("Somehow lost action stack!");
if(m_LastCmdListID != ResourceId())
AddUsage(m_BakedCmdListInfo[m_LastCmdListID].state, node);
}
void D3D12CommandData::InsertActionsAndRefreshIDs(ResourceId cmd, const BakedCmdListInfo &cmdListInfo)
SDObject *D3D12CommandData::InsertEventNodes(WrappedID3D12GraphicsCommandList *replayList,
ResourceId cmd, BakedCmdListInfo &cmdListInfo)
{
const rdcarray<D3D12ActionTreeNode> &cmdBufNodes = cmdListInfo.action->children;
// Start with the Queue annotation (RootAnnotations)
SDObject *localAnnotations = NULL;
if(m_RootAnnotation)
localAnnotations = m_RootAnnotation->Duplicate();
size_t curAnnot = 0;
// assign new action IDs
for(size_t i = 0; i < cmdBufNodes.size(); i++)
rdcarray<D3D12EventNode> &eventNodes = cmdListInfo.eventNodes;
for(size_t i = 0; i < eventNodes.size(); i++)
{
D3D12ActionTreeNode n = cmdBufNodes[i];
n.action.eventId += m_RootEventID;
n.action.actionId += m_RootActionID;
for(APIEvent &ev : n.action.events)
if(eventNodes[i].hasExecuteData)
{
if(localAnnotations)
// Readback the patch buffer and update the event nodes
// The reserved execute indirect event nodes might get duplicated or deleted
// This modifies eventNodes including the current node
replayList->FinaliseExecuteIndirectEvents(cmdListInfo, i);
}
D3D12EventNode n = eventNodes[i];
if(localAnnotations)
{
// Modify using the annotations stored in the event node
for(const PendingAnnotation &annot : n.annotations)
{
for(; curAnnot < cmdListInfo.annotations.size(); curAnnot++)
{
const PendingAnnotation &annot = cmdListInfo.annotations[curAnnot];
if(annot.eventId == ev.eventId)
{
if(annot.valueType == eRENDERDOC_Empty)
localAnnotations->EraseChildByKeyPath(annot.key);
else
WriteAnnotation(localAnnotations->CreateChildByKeyPath(annot.key), annot.valueType,
annot.valueVectorWidth, annot.value);
}
else if(annot.eventId > ev.eventId)
{
break;
}
}
ev.annotations = localAnnotations->Duplicate();
m_EventAnnotations.push_back(ev.annotations);
if(annot.valueType == eRENDERDOC_Empty)
localAnnotations->EraseChildByKeyPath(annot.key);
else
WriteAnnotation(localAnnotations->CreateChildByKeyPath(annot.key), annot.valueType,
annot.valueVectorWidth, annot.value);
}
ev.eventId += m_RootEventID;
m_Events.resize(ev.eventId + 1);
m_Events[ev.eventId] = ev;
n.event.annotations = localAnnotations->Duplicate();
}
ActionUse use(m_Events.back().fileOffset, n.action.eventId, cmd, cmdBufNodes[i].action.eventId);
// insert in sorted location
auto drawit = std::lower_bound(m_ActionUses.begin(), m_ActionUses.end(), use);
m_ActionUses.insert(drawit - m_ActionUses.begin(), 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);
}
GetActionStack().back()->children.push_back(n);
// if this is a push marker too, step down the action stack
if(cmdBufNodes[i].action.flags & ActionFlags::PushMarker)
GetActionStack().push_back(&GetActionStack().back()->children.back());
// similarly for a pop, but don't pop off the root
if((cmdBufNodes[i].action.flags & ActionFlags::PopMarker) && GetActionStack().size() > 1)
GetActionStack().pop_back();
m_EventNodes.push_back(n);
}
cmdListInfo.eventCount = (uint32_t)eventNodes.size();
return localAnnotations;
}
+79 -108
View File
@@ -30,77 +30,65 @@
#include "d3d12_resources.h"
#include "d3d12_state.h"
struct D3D12ActionTreeNode
struct D3D12ExecuteData
{
D3D12ActionTreeNode() {}
explicit D3D12ActionTreeNode(const ActionDescription &a) : action(a) {}
D3D12ActionTreeNode(const D3D12ActionTreeNode &other) { *this = other; }
~D3D12ActionTreeNode() { SAFE_DELETE(state); }
ID3D12Resource *argBuf = NULL;
ID3D12Resource *countBuf = NULL;
uint64_t argOffs = 0;
uint64_t countOffs = 0;
WrappedID3D12CommandSignature *sig = NULL;
UINT maxCount = 0;
UINT reservedCount = 0;
};
struct D3D12EventNode
{
D3D12EventNode() = default;
~D3D12EventNode() { SAFE_DELETE(state); }
D3D12EventNode(const D3D12EventNode &other) { *this = other; }
D3D12EventNode &operator=(const D3D12EventNode &a)
{
event = a.event;
action = a.action;
if(a.state)
{
state = new D3D12RenderState();
*state = *a.state;
}
executeData = a.executeData;
resourceUsage = a.resourceUsage;
debugMessages = a.debugMessages;
annotations = a.annotations;
cmdListID = a.cmdListID;
primaryCmdId = a.primaryCmdId;
childCmdBufId = a.childCmdBufId;
addActionUse = a.addActionUse;
addPrimaryExecute = a.addPrimaryExecute;
hasExecuteData = a.hasExecuteData;
return *this;
}
// eventId is not used
APIEvent event;
ActionDescription action;
rdcarray<D3D12ActionTreeNode> children;
D3D12RenderState *state = NULL;
rdcarray<rdcpair<ResourceId, EventUsage>> resourceUsage;
D3D12ExecuteData executeData;
rdcarray<ResourceId> executedCmds;
rdcarray<rdcpair<ResourceId, ResourceUsage>> resourceUsage;
D3D12ActionTreeNode &operator=(const ActionDescription &a)
{
*this = D3D12ActionTreeNode(a);
return *this;
}
// eventId is not used
rdcarray<DebugMessage> debugMessages;
rdcarray<PendingAnnotation> annotations;
D3D12ActionTreeNode &operator=(const D3D12ActionTreeNode &a)
{
action = a.action;
children = a.children;
if(a.state)
state = new D3D12RenderState(*a.state);
else
state = NULL;
resourceUsage = a.resourceUsage;
executedCmds = a.executedCmds;
return *this;
}
void InsertAndUpdateIDs(const D3D12ActionTreeNode &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().action.eventId += baseEventID;
children.back().action.actionId += baseDrawID;
for(APIEvent &ev : children.back().action.events)
ev.eventId += baseEventID;
}
}
rdcarray<ActionDescription> Bake()
{
rdcarray<ActionDescription> ret;
if(children.empty())
return ret;
ret.resize(children.size());
for(size_t i = 0; i < children.size(); i++)
{
ret[i] = children[i].action;
ret[i].children = children[i].Bake();
}
return ret;
}
ResourceId cmdListID;
ResourceId primaryCmdId;
ResourceId childCmdBufId;
bool addActionUse = false;
bool addPrimaryExecute = false;
bool hasExecuteData = false;
};
struct D3D12ActionCallback
@@ -178,30 +166,13 @@ struct AccStructPatchInfo;
struct BakedCmdListInfo
{
~BakedCmdListInfo() { SAFE_DELETE(action); }
void ShiftForRemoved(uint32_t shiftActionID, uint32_t shiftEID, size_t idx);
~BakedCmdListInfo() {}
SubresourceStateVector GetState(WrappedID3D12Device *device, ResourceId id);
struct ExecuteData
{
uint32_t baseEvent = 0;
ID3D12Resource *argBuf = NULL;
ID3D12Resource *countBuf = NULL;
uint64_t argOffs = 0;
uint64_t countOffs = 0;
WrappedID3D12CommandSignature *sig = NULL;
UINT maxCount = 0;
};
rdcarray<D3D12EventNode> eventNodes;
rdcarray<ExecuteData> executeEvents;
rdcarray<APIEvent> curEvents;
rdcarray<DebugMessage> debugMessages;
rdcarray<D3D12ActionTreeNode *> actionStack;
rdcarray<PendingAnnotation> annotations;
rdcarray<rdcpair<ResourceId, EventUsage>> resourceUsage;
rdcarray<PendingAnnotation> pendingAnnotations;
struct PatchRaytracing
{
@@ -244,10 +215,10 @@ struct BakedCmdListInfo
uint32_t beginChunk = 0;
uint32_t endChunk = 0;
D3D12ActionTreeNode *action = NULL; // the root action 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 actionCount; // similar to above
uint32_t eventCount; // how many events are in this cmd list, for quick skipping
uint32_t curEventID; // current event ID while replaying, not used during loading
bool hasExecuteDatas = false;
};
class WrappedID3D12Device;
@@ -337,7 +308,8 @@ struct D3D12CommandData
// so we just set this command list
ID3D12GraphicsCommandListX *m_OutsideCmdList = NULL;
void InsertActionsAndRefreshIDs(ResourceId cmd, const BakedCmdListInfo &cmdListInfo);
SDObject *InsertEventNodes(WrappedID3D12GraphicsCommandList *replayList, ResourceId cmd,
BakedCmdListInfo &cmdListInfo);
// this is a list of uint64_t file offset -> uint32_t EIDs of where each
// action is used. E.g. the action at offset 873954 is EID 50. If a
@@ -368,13 +340,14 @@ struct D3D12CommandData
std::map<ResourceId, ID3D12GraphicsCommandListX *> m_RerecordCmds;
rdcarray<ID3D12GraphicsCommandListX *> m_RerecordCmdList;
bool m_AddedAction;
rdcarray<APIEvent> m_RootEvents, m_Events;
rdcarray<APIEvent> m_Events;
D3D12EventNode m_LoadingEventNode;
rdcarray<D3D12EventNode> m_EventNodes;
bool m_AddedEventNode;
uint64_t m_CurChunkOffset;
SDChunkMetaData m_ChunkMetadata;
uint32_t m_RootEventID, m_RootActionID;
uint32_t m_RootEventID;
uint32_t m_FirstEventID, m_LastEventID;
D3D12Chunk m_LastChunk;
@@ -388,10 +361,6 @@ struct D3D12CommandData
std::map<ResourceId, rdcarray<EventUsage>> m_ResourceUses;
D3D12ActionTreeNode m_ParentAction;
rdcarray<D3D12ActionTreeNode *> m_RootActionStack;
struct IndirectReplayData
{
ID3D12CommandSignature *commandSig = NULL;
@@ -399,14 +368,6 @@ struct D3D12CommandData
UINT64 argsOffset = 0;
} m_IndirectData;
rdcarray<D3D12ActionTreeNode *> &GetActionStack()
{
if(m_LastCmdListID != ResourceId())
return m_BakedCmdListInfo[m_LastCmdListID].actionStack;
return m_RootActionStack;
}
void GetIndirectBuffer(size_t size, ID3D12Resource **buf, uint64_t *offs);
// util function to handle fetching the right eventId, calling any
@@ -422,14 +383,24 @@ struct D3D12CommandData
void AddAction(const ActionDescription &a);
void AddEvent();
void AddUsage(const D3D12RenderState &state, D3D12ActionTreeNode &actionNode);
void AddUsageForBindInRootSig(const D3D12RenderState &state, D3D12ActionTreeNode &actionNode,
D3D12EventNode &GetLastEventNode()
{
rdcarray<D3D12EventNode> &eventNodes =
(m_LastCmdListID != ResourceId() ? m_BakedCmdListInfo[m_LastCmdListID].eventNodes
: m_EventNodes);
return eventNodes.back();
}
void BakeEventNodes(ActionDescription &rootAction);
void AddUsage(const D3D12RenderState &state, D3D12EventNode &eventNode);
void AddUsageForBindInRootSig(const D3D12RenderState &state, D3D12EventNode &eventNode,
const D3D12RenderState::RootSignature *rootsig,
D3D12_DESCRIPTOR_RANGE_TYPE type, uint32_t space, uint32_t bind,
uint32_t rangeSize);
void AddResourceUsage(D3D12ActionTreeNode &actionNode, ResourceId id, uint32_t EID,
ResourceUsage usage);
void AddResourceUsage(D3D12EventNode &eventNode, ResourceId id, ResourceUsage usage);
void AddCPUUsage(ResourceId id, ResourceUsage usage);
};
+3 -4
View File
@@ -5649,10 +5649,9 @@ RDResult WrappedID3D12Device::ReadLogInitialisation(RDCFile *rdc, bool storeStru
if(!IsStructuredExporting(m_State))
{
GetReplay()->WriteFrameRecord().actionList = m_Queue->GetParentAction().Bake();
m_Queue->GetParentAction().children.clear();
ActionDescription rootAction;
m_Queue->BakeEventNodes(rootAction);
rootAction.children.swap(GetReplay()->WriteFrameRecord().actionList);
SetupActionPointers(m_Actions, GetReplay()->WriteFrameRecord().actionList);
}