From 4e59f62a96f2b571ba830cd1ccfc2b5c5cd7ae48 Mon Sep 17 00:00:00 2001 From: Jake Turner Date: Thu, 23 Jul 2026 10:14:31 +0100 Subject: [PATCH] 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 --- renderdoc/driver/d3d12/d3d12_command_list.h | 10 +- .../driver/d3d12/d3d12_command_list1_wrap.cpp | 42 +- .../driver/d3d12/d3d12_command_list4_wrap.cpp | 13 +- .../driver/d3d12/d3d12_command_list7_wrap.cpp | 10 +- .../driver/d3d12/d3d12_command_list_wrap.cpp | 378 ++++++---------- renderdoc/driver/d3d12/d3d12_command_queue.h | 2 +- .../driver/d3d12/d3d12_command_queue_wrap.cpp | 96 ++-- renderdoc/driver/d3d12/d3d12_commands.cpp | 410 +++++++++--------- renderdoc/driver/d3d12/d3d12_commands.h | 187 ++++---- renderdoc/driver/d3d12/d3d12_device.cpp | 7 +- 10 files changed, 486 insertions(+), 669 deletions(-) diff --git a/renderdoc/driver/d3d12/d3d12_command_list.h b/renderdoc/driver/d3d12/d3d12_command_list.h index 6c12583b9..73b578f6e 100644 --- a/renderdoc/driver/d3d12/d3d12_command_list.h +++ b/renderdoc/driver/d3d12/d3d12_command_list.h @@ -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, diff --git a/renderdoc/driver/d3d12/d3d12_command_list1_wrap.cpp b/renderdoc/driver/d3d12/d3d12_command_list1_wrap.cpp index c9714de19..722a3296c 100644 --- a/renderdoc/driver/d3d12/d3d12_command_list1_wrap.cpp +++ b/renderdoc/driver/d3d12/d3d12_command_list1_wrap.cpp @@ -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)); } } } diff --git a/renderdoc/driver/d3d12/d3d12_command_list4_wrap.cpp b/renderdoc/driver/d3d12/d3d12_command_list4_wrap.cpp index 53ddd49a9..4ab2b1af0 100644 --- a/renderdoc/driver/d3d12/d3d12_command_list4_wrap.cpp +++ b/renderdoc/driver/d3d12/d3d12_command_list4_wrap.cpp @@ -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)); + } } } diff --git a/renderdoc/driver/d3d12/d3d12_command_list7_wrap.cpp b/renderdoc/driver/d3d12/d3d12_command_list7_wrap.cpp index 8e06c2dc6..79a4baf08 100644 --- a/renderdoc/driver/d3d12/d3d12_command_list7_wrap.cpp +++ b/renderdoc/driver/d3d12/d3d12_command_list7_wrap.cpp @@ -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)); } } diff --git a/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp b/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp index d850b9206..cc6ca53bf 100644 --- a/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp +++ b/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp @@ -95,11 +95,6 @@ bool WrappedID3D12GraphicsCommandList::Serialise_Close(SerialiserType &ser) { GetResourceManager()->GetResAs(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 &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 &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 @@ -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)); } } } diff --git a/renderdoc/driver/d3d12/d3d12_command_queue.h b/renderdoc/driver/d3d12/d3d12_command_queue.h index 2a7c3e910..ca2c5f61d 100644 --- a/renderdoc/driver/d3d12/d3d12_command_queue.h +++ b/renderdoc/driver/d3d12/d3d12_command_queue.h @@ -225,7 +225,7 @@ public: D3D12ResourceRecord *GetCreationRecord() { return m_CreationRecord; } WrappedID3D12Device *GetWrappedDevice() { return m_pDevice; } const rdcarray &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(); diff --git a/renderdoc/driver/d3d12/d3d12_command_queue_wrap.cpp b/renderdoc/driver/d3d12/d3d12_command_queue_wrap.cpp index b12806eb4..9c4b8f4ba 100644 --- a/renderdoc/driver/d3d12/d3d12_command_queue_wrap.cpp +++ b/renderdoc/driver/d3d12/d3d12_command_queue_wrap.cpp @@ -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 &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(); } } diff --git a/renderdoc/driver/d3d12/d3d12_commands.cpp b/renderdoc/driver/d3d12/d3d12_commands.cpp index d6fc6182b..239382088 100644 --- a/renderdoc/driver/d3d12/d3d12_commands.cpp +++ b/renderdoc/driver/d3d12/d3d12_commands.cpp @@ -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 &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 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 &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 &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(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 actionEvents; + + rdcarray actionStack; + actionStack.push_back(&rootAction); + + ActionDescription *parentAction = actionStack.back(); + + std::map 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 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 &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 &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; } diff --git a/renderdoc/driver/d3d12/d3d12_commands.h b/renderdoc/driver/d3d12/d3d12_commands.h index 2c4762dee..ca1d7cb90 100644 --- a/renderdoc/driver/d3d12/d3d12_commands.h +++ b/renderdoc/driver/d3d12/d3d12_commands.h @@ -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 children; D3D12RenderState *state = NULL; - rdcarray> resourceUsage; + D3D12ExecuteData executeData; - rdcarray executedCmds; + rdcarray> resourceUsage; - D3D12ActionTreeNode &operator=(const ActionDescription &a) - { - *this = D3D12ActionTreeNode(a); - return *this; - } + // eventId is not used + rdcarray debugMessages; + rdcarray 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 Bake() - { - rdcarray 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 eventNodes; - rdcarray executeEvents; - - rdcarray curEvents; - rdcarray debugMessages; - rdcarray actionStack; - rdcarray annotations; - - rdcarray> resourceUsage; + rdcarray 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 m_RerecordCmds; rdcarray m_RerecordCmdList; - bool m_AddedAction; - - rdcarray m_RootEvents, m_Events; + rdcarray m_Events; + D3D12EventNode m_LoadingEventNode; + rdcarray 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> m_ResourceUses; - D3D12ActionTreeNode m_ParentAction; - - rdcarray m_RootActionStack; - struct IndirectReplayData { ID3D12CommandSignature *commandSig = NULL; @@ -399,14 +368,6 @@ struct D3D12CommandData UINT64 argsOffset = 0; } m_IndirectData; - rdcarray &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 &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); }; diff --git a/renderdoc/driver/d3d12/d3d12_device.cpp b/renderdoc/driver/d3d12/d3d12_device.cpp index edad40ccc..bbb052526 100644 --- a/renderdoc/driver/d3d12/d3d12_device.cpp +++ b/renderdoc/driver/d3d12/d3d12_device.cpp @@ -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); }