From e1a37d4616e4e3f0164b59e7c16f49ac9a59b0f9 Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 30 Dec 2015 19:45:31 +0100 Subject: [PATCH] Reorganise hierarchy so that vkQueueSubmit is just labels * Rather than explicitly having vkQueueSubmit as a node with command buffer children, and those with the contents, we now inline everything and just add labels at beginning and end. * Also tweaked slightly the fake pass algorithm to handle labels being present and merging a bit more aggressively to merge adjacent command buffers that are doing the same pass. --- renderdoc/driver/vulkan/vk_core.h | 2 +- .../driver/vulkan/wrappers/vk_cmd_funcs.cpp | 33 ++-- .../driver/vulkan/wrappers/vk_queue_funcs.cpp | 182 +++++++++--------- renderdocui/Code/Core.cs | 25 ++- 4 files changed, 122 insertions(+), 120 deletions(-) diff --git a/renderdoc/driver/vulkan/vk_core.h b/renderdoc/driver/vulkan/vk_core.h index ec6bbd11e..627e60183 100644 --- a/renderdoc/driver/vulkan/vk_core.h +++ b/renderdoc/driver/vulkan/vk_core.h @@ -467,7 +467,7 @@ private: DrawcallTreeNode m_ParentDrawcall; - void RefreshIDs(vector &nodes, uint32_t baseEventID, uint32_t baseDrawID); + void InsertDrawsAndRefreshIDs(vector &nodes, vector &cmdBufNodes, uint32_t baseEventID, uint32_t baseDrawID); list m_DrawcallStack; diff --git a/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp index f3b74ee8a..d8fb0c526 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp @@ -378,7 +378,7 @@ bool WrappedVulkan::Serialise_vkBeginCommandBuffer( ObjDisp(cmd)->BeginCommandBuffer(Unwrap(cmd), &info); } - m_BakedCmdBufferInfo[cmdId].curEventID = 1; + m_BakedCmdBufferInfo[cmdId].curEventID = 0; } else if(m_State == READING) { @@ -415,8 +415,8 @@ bool WrappedVulkan::Serialise_vkBeginCommandBuffer( m_BakedCmdBufferInfo[cmdId].draw = draw; // On queue submit we increment all child events/drawcalls by - // m_RootEventID insert them into the tree. - m_BakedCmdBufferInfo[cmdId].curEventID = 1; + // m_RootEventID and insert them into the tree. + m_BakedCmdBufferInfo[cmdId].curEventID = 0; m_BakedCmdBufferInfo[cmdId].eventCount = 0; m_BakedCmdBufferInfo[cmdId].drawCount = 0; @@ -497,7 +497,9 @@ bool WrappedVulkan::Serialise_vkEndCommandBuffer(Serialiser* localSerialiser, Vk commandBuffer = RerecordCmdBuf(cmdid); RDCDEBUG("Ending partial command buffer for %llu baked to %llu", cmdid, bakeId); - if(m_PartialReplayData.renderPassActive) + bool recordAll = m_DrawcallCallback && m_DrawcallCallback->RecordAllCmds(); + + if(!recordAll && m_PartialReplayData.renderPassActive) ObjDisp(commandBuffer)->CmdEndRenderPass(Unwrap(commandBuffer)); ObjDisp(commandBuffer)->EndCommandBuffer(Unwrap(commandBuffer)); @@ -519,21 +521,6 @@ bool WrappedVulkan::Serialise_vkEndCommandBuffer(Serialiser* localSerialiser, Vk ObjDisp(commandBuffer)->EndCommandBuffer(Unwrap(commandBuffer)); - if(!m_BakedCmdBufferInfo[m_LastCmdBufferID].curEvents.empty()) - { - FetchDrawcall draw; - draw.name = "API Calls"; - draw.flags |= eDraw_SetMarker; - - // VKTODOLOW hack, give this drawcall the same event ID as its last child, by - // decrementing then incrementing again. - m_BakedCmdBufferInfo[m_LastCmdBufferID].curEventID--; - - AddDrawcall(draw, true); - - m_BakedCmdBufferInfo[m_LastCmdBufferID].curEventID++; - } - { if(GetDrawcallStack().size() > 1) GetDrawcallStack().pop_back(); @@ -542,8 +529,7 @@ bool WrappedVulkan::Serialise_vkEndCommandBuffer(Serialiser* localSerialiser, Vk { m_BakedCmdBufferInfo[bakeId].draw = m_BakedCmdBufferInfo[m_LastCmdBufferID].draw; m_BakedCmdBufferInfo[bakeId].curEventID = 0; - m_BakedCmdBufferInfo[bakeId].eventCount = m_BakedCmdBufferInfo[m_LastCmdBufferID].curEventID-1; - RDCASSERT(m_BakedCmdBufferInfo[m_LastCmdBufferID].curEventID >= 1); + m_BakedCmdBufferInfo[bakeId].eventCount = m_BakedCmdBufferInfo[m_LastCmdBufferID].curEventID; m_BakedCmdBufferInfo[bakeId].drawCount = m_BakedCmdBufferInfo[m_LastCmdBufferID].drawCount; m_BakedCmdBufferInfo[m_LastCmdBufferID].draw = NULL; @@ -894,6 +880,11 @@ bool WrappedVulkan::Serialise_vkCmdEndRenderPass( draw.flags |= eDraw_PassBoundary|eDraw_EndPass; AddDrawcall(draw, true); + + // track while reading, reset this to empty so AddDrawcall sets no outputs, + // but only AFTER the above AddDrawcall (we want it grouped together) + m_BakedCmdBufferInfo[m_LastCmdBufferID].state.renderPass = ResourceId(); + m_BakedCmdBufferInfo[m_LastCmdBufferID].state.framebuffer = ResourceId(); } return true; diff --git a/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp index cb2144ca0..413ec62fa 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp @@ -199,58 +199,46 @@ bool WrappedVulkan::Serialise_vkQueueSubmit( } AddEvent(QUEUE_SUBMIT, desc); - string name = "vkQueueSubmit(" + - ToStr::Get(numCmds) + ")"; - - FetchDrawcall draw; - draw.name = name; - - draw.flags |= eDraw_PushMarker; - - AddDrawcall(draw, true); - - // add command buffer draws under here - GetDrawcallStack().push_back(&GetDrawcallStack().back()->children.back()); + // we're adding multiple events, need to increment ourselves m_RootEventID++; + string basename = "vkQueueSubmit(" + ToStr::Get(numCmds) + ")"; + for(uint32_t c=0; c < numCmds; c++) { - string name = "[" + ToStr::Get(cmdIds[c]) + "]"; - - AddEvent(QUEUE_SUBMIT, "cmd " + name); + string name = StringFormat::Fmt("=> %s[%u]: vkBeginCommandBuffer(%s)", basename.c_str(), c, ToStr::Get(cmdIds[c]).c_str()); + // add a fake marker FetchDrawcall draw; draw.name = name; - - draw.flags |= eDraw_PushMarker; - + draw.flags |= eDraw_SetMarker; + AddEvent(SET_MARKER, name); AddDrawcall(draw, true); - - DrawcallTreeNode &d = GetDrawcallStack().back()->children.back(); - - // copy DrawcallTreeNode children - d.children = m_BakedCmdBufferInfo[cmdIds[c]].draw->children; - - // assign new event and drawIDs - RefreshIDs(d.children, m_RootEventID, m_RootDrawcallID); + m_RootEventID++; + + // insert the baked command buffer in-line into this list of notes, assigning new event and drawIDs + InsertDrawsAndRefreshIDs(GetDrawcallStack().back()->children, m_BakedCmdBufferInfo[cmdIds[c]].draw->children, m_RootEventID, m_RootDrawcallID); m_PartialReplayData.cmdBufferSubmits[cmdIds[c]].push_back(m_RootEventID); - // 1 extra for the [0] virtual event for the command buffer - m_RootEventID += 1+m_BakedCmdBufferInfo[cmdIds[c]].eventCount; + m_RootEventID += m_BakedCmdBufferInfo[cmdIds[c]].eventCount; m_RootDrawcallID += m_BakedCmdBufferInfo[cmdIds[c]].drawCount; + + name = StringFormat::Fmt("=> %s[%u]: vkEndCommandBuffer(%s)", basename.c_str(), c, ToStr::Get(cmdIds[c]).c_str()); + draw.name = name; + AddEvent(SET_MARKER, name); + AddDrawcall(draw, true); + m_RootEventID++; } - // the outer loop will increment the event ID but we've handled - // it ourselves, so 'undo' that. + // account for the outer loop thinking we've added one event and incrementing, + // since we've done all the handling ourselves this will be off by one. m_RootEventID--; - - // done adding command buffers - m_DrawcallStack.pop_back(); } else if(m_State == EXECUTING) { + // account for the queue submit event m_RootEventID++; uint32_t startEID = m_RootEventID; @@ -258,67 +246,22 @@ bool WrappedVulkan::Serialise_vkQueueSubmit( // advance m_CurEventID to match the events added when reading for(uint32_t c=0; c < numCmds; c++) { - // 1 extra for the [0] virtual event for the command buffer - m_RootEventID += 1+m_BakedCmdBufferInfo[cmdIds[c]].eventCount; - m_RootDrawcallID += m_BakedCmdBufferInfo[cmdIds[c]].drawCount; + // 2 extra for the virtual labels around the command buffer + m_RootEventID += 2+m_BakedCmdBufferInfo[cmdIds[c]].eventCount; + m_RootDrawcallID += 2+m_BakedCmdBufferInfo[cmdIds[c]].drawCount; } + // same accounting for the outer loop as above m_RootEventID--; if(numCmds == 0) { // do nothing, don't bother with the logic below } - else if(m_LastEventID == startEID) + else if(m_LastEventID <= startEID) { RDCDEBUG("Queue Submit no replay %u == %u", m_LastEventID, startEID); } - else if(m_LastEventID > startEID && m_LastEventID < m_RootEventID) - { - RDCDEBUG("Queue Submit partial replay %u < %u", m_LastEventID, m_RootEventID); - - uint32_t eid = startEID; - - vector trimmedCmdIds; - vector trimmedCmds; - - for(uint32_t c=0; c < numCmds; c++) - { - uint32_t end = eid + m_BakedCmdBufferInfo[cmdIds[c]].eventCount; - - if(eid == m_PartialReplayData.baseEvent) - { - ResourceId partial = GetResID(RerecordCmdBuf(cmdIds[c])); - RDCDEBUG("Queue Submit partial replay of %llu at %u, using %llu", cmdIds[c], eid, partial); - trimmedCmdIds.push_back(partial); - trimmedCmds.push_back(Unwrap(RerecordCmdBuf(cmdIds[c]))); - } - else if(m_LastEventID >= end) - { - RDCDEBUG("Queue Submit full replay %llu", cmdIds[c]); - trimmedCmdIds.push_back(cmdIds[c]); - trimmedCmds.push_back(Unwrap(GetResourceManager()->GetLiveHandle(cmdIds[c]))); - } - else - { - RDCDEBUG("Queue not submitting %llu", cmdIds[c]); - } - - eid += 1+m_BakedCmdBufferInfo[cmdIds[c]].eventCount; - } - - RDCASSERT(trimmedCmds.size() > 0); - - submitInfo.commandBufferCount = (uint32_t)trimmedCmds.size(); - submitInfo.pCommandBuffers = &trimmedCmds[0]; - ObjDisp(queue)->QueueSubmit(Unwrap(queue), 1, &submitInfo, Unwrap(fence)); - - for(uint32_t i=0; i < trimmedCmdIds.size(); i++) - { - ResourceId cmd = trimmedCmdIds[i]; - GetResourceManager()->ApplyBarriers(m_BakedCmdBufferInfo[cmd].imgbarriers, m_ImageLayouts); - } - } else if(m_DrawcallCallback && m_DrawcallCallback->RecordAllCmds()) { RDCDEBUG("Queue Submit re-recording from %u", m_RootEventID); @@ -339,6 +282,57 @@ bool WrappedVulkan::Serialise_vkQueueSubmit( submitInfo.pCommandBuffers = &rerecordedCmds[0]; ObjDisp(queue)->QueueSubmit(Unwrap(queue), 1, &submitInfo, Unwrap(fence)); } + else if(m_LastEventID > startEID && m_LastEventID < m_RootEventID) + { + RDCDEBUG("Queue Submit partial replay %u < %u", m_LastEventID, m_RootEventID); + + uint32_t eid = startEID; + + vector trimmedCmdIds; + vector trimmedCmds; + + for(uint32_t c=0; c < numCmds; c++) + { + // account for the virtual vkBeginCommandBuffer label at the start of the events here + // so it matches up to baseEvent + eid++; + + uint32_t end = eid + m_BakedCmdBufferInfo[cmdIds[c]].eventCount; + + if(eid == m_PartialReplayData.baseEvent) + { + ResourceId partial = GetResID(RerecordCmdBuf(cmdIds[c])); + RDCDEBUG("Queue Submit partial replay of %llu at %u, using %llu", cmdIds[c], eid, partial); + trimmedCmdIds.push_back(partial); + trimmedCmds.push_back(Unwrap(RerecordCmdBuf(cmdIds[c]))); + } + else if(m_LastEventID >= end) + { + RDCDEBUG("Queue Submit full replay %llu", cmdIds[c]); + trimmedCmdIds.push_back(cmdIds[c]); + trimmedCmds.push_back(Unwrap(GetResourceManager()->GetLiveHandle(cmdIds[c]))); + } + else + { + RDCDEBUG("Queue not submitting %llu", cmdIds[c]); + } + + // 1 extra to account for the virtual end command buffer label (begin is accounted for above) + eid += 1+m_BakedCmdBufferInfo[cmdIds[c]].eventCount; + } + + RDCASSERT(trimmedCmds.size() > 0); + + submitInfo.commandBufferCount = (uint32_t)trimmedCmds.size(); + submitInfo.pCommandBuffers = &trimmedCmds[0]; + ObjDisp(queue)->QueueSubmit(Unwrap(queue), 1, &submitInfo, Unwrap(fence)); + + for(uint32_t i=0; i < trimmedCmdIds.size(); i++) + { + ResourceId cmd = trimmedCmdIds[i]; + GetResourceManager()->ApplyBarriers(m_BakedCmdBufferInfo[cmd].imgbarriers, m_ImageLayouts); + } + } else { RDCDEBUG("Queue Submit full replay %u >= %u", m_LastEventID, m_RootEventID); @@ -358,27 +352,31 @@ bool WrappedVulkan::Serialise_vkQueueSubmit( return true; } -void WrappedVulkan::RefreshIDs(vector &nodes, uint32_t baseEventID, uint32_t baseDrawID) +void WrappedVulkan::InsertDrawsAndRefreshIDs(vector &nodes, vector &cmdBufNodes, + uint32_t baseEventID, uint32_t baseDrawID) { // assign new drawcall IDs - for(size_t i=0; i < nodes.size(); i++) + for(size_t i=0; i < cmdBufNodes.size(); i++) { - nodes[i].draw.eventID += baseEventID; - nodes[i].draw.drawcallID += baseDrawID; + DrawcallTreeNode n = cmdBufNodes[i]; + n.draw.eventID += baseEventID; + n.draw.drawcallID += baseDrawID; - for(int32_t e=0; e < nodes[i].draw.events.count; e++) + for(int32_t e=0; e < n.draw.events.count; e++) { - nodes[i].draw.events[e].eventID += baseEventID; - m_Events.push_back(nodes[i].draw.events[e]); + n.draw.events[e].eventID += baseEventID; + m_Events.push_back(n.draw.events[e]); } - DrawcallUse use(m_Events.back().fileOffset, nodes[i].draw.eventID); + DrawcallUse use(m_Events.back().fileOffset, n.draw.eventID); // insert in sorted location auto it = std::lower_bound(m_DrawcallUses.begin(), m_DrawcallUses.end(), use); m_DrawcallUses.insert(it, use); - RefreshIDs(nodes[i].children, baseEventID, baseDrawID); + InsertDrawsAndRefreshIDs(n.children, cmdBufNodes[i].children, baseEventID, baseDrawID); + + nodes.push_back(n); } } diff --git a/renderdocui/Code/Core.cs b/renderdocui/Code/Core.cs index b231756cb..8341c16e1 100644 --- a/renderdocui/Code/Core.cs +++ b/renderdocui/Code/Core.cs @@ -293,7 +293,7 @@ namespace renderdocui.Code foreach (var d in draws) { - ret |= (d.flags & (DrawcallFlags.PushMarker | DrawcallFlags.SetMarker)) > 0 && (d.flags & DrawcallFlags.CmdList) == 0; + ret |= (d.flags & DrawcallFlags.PushMarker) > 0 && (d.flags & DrawcallFlags.CmdList) == 0; ret |= ContainsMarker(d.children); } @@ -315,20 +315,30 @@ namespace renderdocui.Code int passID = 1; int start = 0; + int refdraw = 0; int counter = 1; for (int i = 1; i < draws.Length; i++) { - if (PassEquivalent(draws[i], draws[start])) + if ((draws[refdraw].flags & (DrawcallFlags.Copy | DrawcallFlags.SetMarker)) > 0) + { + refdraw = i; + continue; + } + + if ((draws[i].flags & (DrawcallFlags.Copy | DrawcallFlags.SetMarker)) > 0) + continue; + + if (PassEquivalent(draws[i], draws[refdraw])) continue; int end = i-1; if (end - start < 2 || - draws[i].children.Length > 0 || draws[start].children.Length > 0 || + draws[i].children.Length > 0 || draws[refdraw].children.Length > 0 || draws[i].context != m_FrameInfo[frameID].immContextId || - draws[start].context != m_FrameInfo[frameID].immContextId) + draws[refdraw].context != m_FrameInfo[frameID].immContextId) { for (int j = start; j <= end; j++) { @@ -337,6 +347,7 @@ namespace renderdocui.Code } start = i; + refdraw = i; continue; } @@ -365,12 +376,13 @@ namespace renderdocui.Code mark.name = "Guessed Pass"; + minOutCount = Math.Max(1, minOutCount); - if((draws[end].flags & DrawcallFlags.Dispatch) != 0) + if ((draws[end].flags & DrawcallFlags.Dispatch) != 0) mark.name = String.Format("Compute Pass #{0}", computepassID++); else if (maxOutCount == 0) mark.name = String.Format("Depth-only Pass #{0}", depthpassID++); - else if(minOutCount == maxOutCount) + else if (minOutCount == maxOutCount) mark.name = String.Format("Colour Pass #{0} ({1} Targets{2})", passID++, minOutCount, draws[end].depthOut == ResourceId.Null ? "" : " + Depth"); else mark.name = String.Format("Colour Pass #{0} ({1}-{2} Targets{3})", passID++, minOutCount, maxOutCount, draws[end].depthOut == ResourceId.Null ? "" : " + Depth"); @@ -386,6 +398,7 @@ namespace renderdocui.Code ret.Add(mark); start = i; + refdraw = i; counter++; }