Support initing postvs for a whole pass via a per-draw callback

This commit is contained in:
baldurk
2016-02-07 18:49:40 +01:00
parent 7aca368cc7
commit 00e0946112
4 changed files with 107 additions and 24 deletions
+39 -16
View File
@@ -283,11 +283,13 @@ WrappedVulkan::WrappedVulkan(const char *logFilename)
m_FirstEventID = 0;
m_LastEventID = ~0U;
m_DrawcallCallback = NULL;
m_LastCmdBufferID = ResourceId();
m_PartialReplayData.renderPassActive = false;
m_PartialReplayData.resultPartialCmdBuffer = VK_NULL_HANDLE;
m_PartialReplayData.singleDrawCmdBuffer = VK_NULL_HANDLE;
m_PartialReplayData.outsideCmdBuffer = VK_NULL_HANDLE;
m_PartialReplayData.partialParent = ResourceId();
m_PartialReplayData.baseEvent = 0;
@@ -1277,16 +1279,21 @@ void WrappedVulkan::ContextReplayLog(LogState readType, uint32_t startEventID, u
if(m_State == EXECUTING && startEventID == endEventID)
break;
if(m_LastCmdBufferID != ResourceId())
// increment root event ID either if we didn't just replay a cmd
// buffer event, OR if we are doing a frame sub-section replay,
// in which case it's up to the calling code to make sure we only
// replay inside a command buffer (if we crossed command buffer
// boundaries, the event IDs would no longer match up).
if(m_LastCmdBufferID == ResourceId() || startEventID > 1)
{
m_RootEventID++;
}
else
{
// these events are completely omitted, so don't increment the curEventID
if(context != BEGIN_CMD_BUFFER && context != END_CMD_BUFFER)
m_BakedCmdBufferInfo[m_LastCmdBufferID].curEventID++;
}
else
{
m_RootEventID++;
}
}
if(m_State == READING)
@@ -1766,6 +1773,22 @@ void WrappedVulkan::ReplayLog(uint32_t frameID, uint32_t startEventID, uint32_t
m_RenderState.m_ResourceManager = GetResourceManager();
}
VkResult vkr = VK_SUCCESS;
// we'll need our own command buffer if we're replaying just a subsection
// of events within a single command buffer record - always if it's only
// one drawcall, or if start event ID is > 0 we assume the outside code
// has chosen a subsection that lies within a command buffer
if(partial)
{
VkCommandBuffer cmd = m_PartialReplayData.outsideCmdBuffer = GetNextCmd();
VkCommandBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, NULL, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT };
vkr = ObjDisp(cmd)->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
RDCASSERT(vkr == VK_SUCCESS);
}
if(replayType == eReplay_Full)
{
ContextReplayLog(EXECUTING, startEventID, endEventID, partial);
@@ -1776,13 +1799,8 @@ void WrappedVulkan::ReplayLog(uint32_t frameID, uint32_t startEventID, uint32_t
}
else if(replayType == eReplay_OnlyDraw)
{
VkCommandBuffer cmd = m_PartialReplayData.singleDrawCmdBuffer = GetNextCmd();
VkCommandBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, NULL, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT };
VkCommandBuffer cmd = m_PartialReplayData.outsideCmdBuffer;
VkResult vkr = ObjDisp(cmd)->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
RDCASSERT(vkr == VK_SUCCESS);
bool rpWasActive = m_PartialReplayData.renderPassActive;
// if a render pass was active, begin it and set up the partial replay state
@@ -1800,15 +1818,20 @@ void WrappedVulkan::ReplayLog(uint32_t frameID, uint32_t startEventID, uint32_t
// but we want to keep the partial replay data state intact, so restore
// whether or not a render pass was active.
m_PartialReplayData.renderPassActive = rpWasActive;
}
else
RDCFATAL("Unexpected replay type");
if(m_PartialReplayData.outsideCmdBuffer != VK_NULL_HANDLE)
{
VkCommandBuffer cmd = m_PartialReplayData.outsideCmdBuffer;
ObjDisp(cmd)->EndCommandBuffer(Unwrap(cmd));
SubmitCmds();
m_PartialReplayData.singleDrawCmdBuffer = VK_NULL_HANDLE;
m_PartialReplayData.outsideCmdBuffer = VK_NULL_HANDLE;
}
else
RDCFATAL("Unexpected replay type");
}
}
+17 -6
View File
@@ -96,6 +96,12 @@ struct DrawcallTreeNode
#undef SERIALISED_PARAMETER
#define SERIALISED_PARAMETER Serialiser *localSerialiser,
struct DrawcallCallback
{
virtual void PreDraw(uint32_t eid) = 0;
virtual void PostDraw(uint32_t eid) = 0;
};
class WrappedVulkan : public IFrameCapturer
{
private:
@@ -147,6 +153,8 @@ private:
VulkanDebugManager *m_DebugManager;
Threading::CriticalSection m_CapTransitionLock;
DrawcallCallback *m_DrawcallCallback;
uint32_t m_FrameCounter;
@@ -284,10 +292,11 @@ private:
VkCommandBuffer resultPartialCmdBuffer;
VkDevice partialDevice; // device for above cmd buffer
// if we're replaying just a single draw we don't go through the
// if we're replaying just a single draw or a particular command
// buffer subsection of command events, we don't go through the
// whole original command buffers to set up the partial replay,
// so we just set this command buffer
VkCommandBuffer singleDrawCmdBuffer;
VkCommandBuffer outsideCmdBuffer;
// this records where in the frame a command buffer was submitted,
// so that we know if our replay range ends in one of these ranges
@@ -332,18 +341,18 @@ private:
bool IsPartialCmd(ResourceId cmdid)
{
return m_PartialReplayData.singleDrawCmdBuffer != VK_NULL_HANDLE ||
return m_PartialReplayData.outsideCmdBuffer != VK_NULL_HANDLE ||
cmdid == m_PartialReplayData.partialParent;
}
bool InPartialRange()
{
return m_PartialReplayData.singleDrawCmdBuffer != VK_NULL_HANDLE ||
return m_PartialReplayData.outsideCmdBuffer != VK_NULL_HANDLE ||
m_BakedCmdBufferInfo[m_PartialReplayData.partialParent].curEventID <= m_LastEventID - m_PartialReplayData.baseEvent;
}
VkCommandBuffer PartialCmdBuf()
{
if(m_PartialReplayData.singleDrawCmdBuffer != VK_NULL_HANDLE)
return m_PartialReplayData.singleDrawCmdBuffer;
if(m_PartialReplayData.outsideCmdBuffer != VK_NULL_HANDLE)
return m_PartialReplayData.outsideCmdBuffer;
return m_PartialReplayData.resultPartialCmdBuffer;
}
@@ -494,6 +503,8 @@ public:
FetchAPIEvent GetEvent(uint32_t eventID);
const FetchDrawcall *GetDrawcall(uint32_t frameID, uint32_t eventID);
void SetDrawcallCB(DrawcallCallback *cb) { m_DrawcallCallback = cb; }
// Device initialization
IMPLEMENT_FUNCTION_SERIALISED(VkResult, vkCreateInstance,
+43 -2
View File
@@ -583,7 +583,11 @@ vector<uint32_t> VulkanReplay::GetPassEvents(uint32_t frameID, uint32_t eventID)
if(start == draw)
break;
if(start->flags & eDraw_Drawcall)
// include pass boundaries, these will be filtered out later
// so we don't actually do anything (init postvs/draw overlay)
// but it's useful to have the first part of the pass as part
// of the list
if(start->flags & (eDraw_Drawcall|eDraw_PassBoundary))
passEvents.push_back(start->eventID);
start = m_pDriver->GetDrawcall(frameID, (uint32_t)start->next);
@@ -3772,9 +3776,46 @@ void VulkanReplay::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
GetDebugManager()->InitPostVSBuffers(frameID, eventID);
}
struct InitPostVSCallback : public DrawcallCallback
{
InitPostVSCallback(WrappedVulkan *vk, VulkanReplay *rp, uint32_t frameID, const vector<uint32_t> &events)
: m_pDriver(vk)
, m_pReplay(rp)
, m_FrameID(frameID)
, m_Events(events)
{ m_pDriver->SetDrawcallCB(this); }
~InitPostVSCallback()
{ m_pDriver->SetDrawcallCB(NULL); }
void PreDraw(uint32_t eid)
{
if(std::find(m_Events.begin(), m_Events.end(), eid) != m_Events.end())
m_pReplay->InitPostVSBuffers(m_FrameID, eid);
}
void PostDraw(uint32_t eid)
{
}
uint32_t m_FrameID;
WrappedVulkan *m_pDriver;
VulkanReplay *m_pReplay;
const vector<uint32_t> &m_Events;
};
void VulkanReplay::InitPostVSBuffers(uint32_t frameID, const vector<uint32_t> &events)
{
// Stub, will implement this in a minute
// first we must replay up to the first event without replaying it. This ensures any
// non-command buffer calls like memory unmaps etc all happen correctly before this
// command buffer
m_pDriver->ReplayLog(frameID, 0, events.front(), eReplay_WithoutDraw);
InitPostVSCallback cb(m_pDriver, this, frameID, events);
// now we replay the events, which are guaranteed (because we generated them in
// GetPassEvents above) to come from the same command buffer, so the event IDs are
// still locally continuous, even if we jump into replaying.
m_pDriver->ReplayLog(frameID, events.front(), events.back(), eReplay_Full);
}
vector<EventUsage> VulkanReplay::GetUsage(ResourceId id)
@@ -45,8 +45,12 @@ bool WrappedVulkan::Serialise_vkCmdDraw(
{
if(IsPartialCmd(cmdid) && InPartialRange())
{
if(m_DrawcallCallback) m_DrawcallCallback->PreDraw(m_RootEventID);
commandBuffer = PartialCmdBuf();
ObjDisp(commandBuffer)->CmdDraw(Unwrap(commandBuffer), vtxCount, instCount, firstVtx, firstInst);
if(m_DrawcallCallback) m_DrawcallCallback->PostDraw(m_RootEventID);
}
}
else if(m_State == READING)
@@ -975,8 +979,12 @@ bool WrappedVulkan::Serialise_vkCmdDrawIndexed(
{
if(IsPartialCmd(cmdid) && InPartialRange())
{
if(m_DrawcallCallback) m_DrawcallCallback->PreDraw(m_RootEventID);
commandBuffer = PartialCmdBuf();
ObjDisp(commandBuffer)->CmdDrawIndexed(Unwrap(commandBuffer), idxCount, instCount, firstIdx, vtxOffs, firstInst);
if(m_DrawcallCallback) m_DrawcallCallback->PostDraw(m_RootEventID);
}
}
else if(m_State == READING)