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.
This commit is contained in:
baldurk
2016-02-07 18:49:53 +01:00
parent 24f9f487c2
commit e1a37d4616
4 changed files with 122 additions and 120 deletions
+1 -1
View File
@@ -467,7 +467,7 @@ private:
DrawcallTreeNode m_ParentDrawcall;
void RefreshIDs(vector<DrawcallTreeNode> &nodes, uint32_t baseEventID, uint32_t baseDrawID);
void InsertDrawsAndRefreshIDs(vector<DrawcallTreeNode> &nodes, vector<DrawcallTreeNode> &cmdBufNodes, uint32_t baseEventID, uint32_t baseDrawID);
list<DrawcallTreeNode *> m_DrawcallStack;
@@ -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;
@@ -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<ResourceId> trimmedCmdIds;
vector<VkCommandBuffer> 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<VkCommandBuffer>(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<ResourceId> trimmedCmdIds;
vector<VkCommandBuffer> 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<VkCommandBuffer>(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<DrawcallTreeNode> &nodes, uint32_t baseEventID, uint32_t baseDrawID)
void WrappedVulkan::InsertDrawsAndRefreshIDs(vector<DrawcallTreeNode> &nodes, vector<DrawcallTreeNode> &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);
}
}
+19 -6
View File
@@ -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++;
}