Add checks for drawcalls outside of render passes (primary/secondary)

This commit is contained in:
baldurk
2016-09-16 19:43:17 +02:00
parent a2a63104dd
commit 778d1399ea
5 changed files with 161 additions and 21 deletions
+36
View File
@@ -1562,6 +1562,12 @@ void WrappedVulkan::ContextReplayLog(LogState readType, uint32_t startEventID, u
m_FirstEventID = startEventID;
m_LastEventID = endEventID;
// when selecting a marker we can get into an inconsistent state -
// make sure that we make things consistent again here, replay the event
// that we ended up selecting (the one that was closest)
if(startEventID == endEventID && m_RootEventID != m_FirstEventID)
m_FirstEventID = m_LastEventID = m_RootEventID;
}
else if(m_State == READING)
{
@@ -2333,6 +2339,36 @@ vector<DebugMessage> WrappedVulkan::GetDebugMessages()
return ret;
}
void WrappedVulkan::AddDebugMessage(DebugMessageCategory c, DebugMessageSeverity sv,
DebugMessageSource src, std::string d)
{
DebugMessage msg;
msg.eventID = 0;
if(m_State == EXECUTING)
{
// look up the EID this drawcall came from
DrawcallUse use(m_CurChunkOffset, 0);
auto it = std::lower_bound(m_DrawcallUses.begin(), m_DrawcallUses.end(), use);
RDCASSERT(it != m_DrawcallUses.end());
msg.eventID = it->eventID;
}
msg.messageID = 0;
msg.source = src;
msg.category = c;
msg.severity = sv;
msg.description = d;
AddDebugMessage(msg);
}
void WrappedVulkan::AddDebugMessage(DebugMessage msg)
{
if(m_State == READING)
m_EventMessages.push_back(msg);
else
m_DebugMessages.push_back(msg);
}
VkBool32 WrappedVulkan::DebugCallback(VkDebugReportFlagsEXT flags,
VkDebugReportObjectTypeEXT objectType, uint64_t object,
size_t location, int32_t messageCode,
+17 -1
View File
@@ -191,6 +191,9 @@ private:
vector<DebugMessage> m_DebugMessages;
void Serialise_DebugMessages(Serialiser *localSerialiser, bool isDrawcall);
vector<DebugMessage> GetDebugMessages();
void AddDebugMessage(DebugMessage msg);
void AddDebugMessage(DebugMessageCategory c, DebugMessageSeverity sv, DebugMessageSource src,
std::string d);
enum
{
@@ -368,12 +371,23 @@ private:
struct BakedCmdBufferInfo
{
BakedCmdBufferInfo() : draw(NULL), eventCount(0), curEventID(0), drawCount(0) {}
BakedCmdBufferInfo()
: draw(NULL),
eventCount(0),
curEventID(0),
drawCount(0),
level(VK_COMMAND_BUFFER_LEVEL_PRIMARY),
beginFlags(0)
{
}
~BakedCmdBufferInfo() { SAFE_DELETE(draw); }
vector<FetchAPIEvent> curEvents;
vector<DebugMessage> debugMessages;
list<VulkanDrawcallTreeNode *> drawStack;
VkCommandBufferLevel level;
VkCommandBufferUsageFlags beginFlags;
vector<pair<ResourceId, EventUsage> > resourceUsage;
struct CmdBufferState
@@ -575,6 +589,8 @@ private:
void MakeSubpassLoadRP(VkRenderPassCreateInfo &info, const VkRenderPassCreateInfo *origInfo,
uint32_t s);
bool IsDrawInRenderPass();
void StartFrameCapture(void *dev, void *wnd);
bool EndFrameCapture(void *dev, void *wnd);
+1 -1
View File
@@ -6350,7 +6350,7 @@ void VulkanDebugManager::InitPostVSBuffers(uint32_t eventID)
const VulkanRenderState &state = m_pDriver->m_RenderState;
VulkanCreationInfo &creationInfo = m_pDriver->m_CreationInfo;
if(state.graphics.pipeline == ResourceId())
if(state.graphics.pipeline == ResourceId() || state.renderPass == ResourceId())
return;
const VulkanCreationInfo::Pipeline &pipeInfo = creationInfo.m_Pipeline[state.graphics.pipeline];
@@ -466,8 +466,13 @@ bool WrappedVulkan::Serialise_vkBeginCommandBuffer(Serialiser *localSerialiser,
localSerialiser->Serialise("allocInfo", allocInfo);
if(m_State < WRITING)
{
device = GetResourceManager()->GetLiveHandle<VkDevice>(devId);
m_BakedCmdBufferInfo[cmdId].level = m_BakedCmdBufferInfo[bakeId].level = allocInfo.level;
m_BakedCmdBufferInfo[cmdId].beginFlags = m_BakedCmdBufferInfo[bakeId].beginFlags = info.flags;
}
if(m_State == EXECUTING)
{
const uint32_t length = m_BakedCmdBufferInfo[bakeId].eventCount;
@@ -2344,6 +2349,14 @@ bool WrappedVulkan::Serialise_vkCmdExecuteCommands(Serialiser *localSerialiser,
BakedCmdBufferInfo &cmdBufInfo = m_BakedCmdBufferInfo[cmdids[c]];
if(m_BakedCmdBufferInfo[m_LastCmdBufferID].state.renderPass == ResourceId() &&
(cmdBufInfo.beginFlags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT))
{
AddDebugMessage(
eDbgCategory_Execution, eDbgSeverity_High, eDbgSource_IncorrectAPIUse,
"Executing a command buffer with RENDER_PASS_CONTINUE_BIT outside of render pass");
}
// insert the baked command buffer in-line into this list of notes, assigning new event and
// drawIDs
parentCmdBufInfo.draw->InsertAndUpdateIDs(*cmdBufInfo.draw, parentCmdBufInfo.curEventID,
@@ -25,6 +25,46 @@
#include "../vk_core.h"
#include "../vk_debug.h"
bool WrappedVulkan::IsDrawInRenderPass()
{
ResourceId rp;
if(m_State == READING)
rp = m_BakedCmdBufferInfo[m_LastCmdBufferID].state.renderPass;
else
rp = m_RenderState.renderPass;
ResourceId cmdid = m_LastCmdBufferID;
bool rpActive = true;
if(m_State == EXECUTING)
{
cmdid = GetResID(RerecordCmdBuf(cmdid));
rpActive =
m_Partial[m_BakedCmdBufferInfo[cmdid].level == VK_COMMAND_BUFFER_LEVEL_PRIMARY ? Primary : Secondary]
.renderPassActive;
}
if(m_BakedCmdBufferInfo[cmdid].level == VK_COMMAND_BUFFER_LEVEL_PRIMARY &&
(rp == ResourceId() || !rpActive))
{
return false;
}
else if(m_BakedCmdBufferInfo[cmdid].level == VK_COMMAND_BUFFER_LEVEL_SECONDARY &&
(m_BakedCmdBufferInfo[cmdid].beginFlags &
VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT) == 0 &&
(rp == ResourceId() || !rpActive))
{
return false;
}
// assume a secondary buffer with RENDER_PASS_CONTINUE_BIT is in a render pass.
return true;
}
bool WrappedVulkan::Serialise_vkCmdDraw(Serialiser *localSerialiser, VkCommandBuffer commandBuffer,
uint32_t vertexCount, uint32_t instanceCount,
uint32_t firstVertex, uint32_t firstInstance)
@@ -42,7 +82,7 @@ bool WrappedVulkan::Serialise_vkCmdDraw(Serialiser *localSerialiser, VkCommandBu
if(m_State == EXECUTING)
{
if(ShouldRerecordCmd(cmdid) && InRerecordRange(cmdid))
if(ShouldRerecordCmd(cmdid) && InRerecordRange(cmdid) && m_RenderState.renderPass != ResourceId())
{
commandBuffer = RerecordCmdBuf(cmdid);
@@ -65,6 +105,13 @@ bool WrappedVulkan::Serialise_vkCmdDraw(Serialiser *localSerialiser, VkCommandBu
const string desc = localSerialiser->GetDebugStr();
if(!IsDrawInRenderPass())
{
AddDebugMessage(eDbgCategory_Execution, eDbgSeverity_High, eDbgSource_IncorrectAPIUse,
"Drawcall in happening outside of render pass, or in secondary command "
"buffer without RENDER_PASS_CONTINUE_BIT");
}
{
AddEvent(DRAW, desc);
string name = "vkCmdDraw(" + ToStr::Get(vtxCount) + "," + ToStr::Get(instCount) + ")";
@@ -127,7 +174,7 @@ bool WrappedVulkan::Serialise_vkCmdDrawIndexed(Serialiser *localSerialiser,
if(m_State == EXECUTING)
{
if(ShouldRerecordCmd(cmdid) && InRerecordRange(cmdid))
if(ShouldRerecordCmd(cmdid) && InRerecordRange(cmdid) && IsDrawInRenderPass())
{
commandBuffer = RerecordCmdBuf(cmdid);
@@ -154,6 +201,13 @@ bool WrappedVulkan::Serialise_vkCmdDrawIndexed(Serialiser *localSerialiser,
const string desc = localSerialiser->GetDebugStr();
if(!IsDrawInRenderPass())
{
AddDebugMessage(eDbgCategory_Execution, eDbgSeverity_High, eDbgSource_IncorrectAPIUse,
"Drawcall in happening outside of render pass, or in secondary command "
"buffer without RENDER_PASS_CONTINUE_BIT");
}
{
AddEvent(DRAW_INDEXED, desc);
string name = "vkCmdDrawIndexed(" + ToStr::Get(idxCount) + "," + ToStr::Get(instCount) + ")";
@@ -228,7 +282,7 @@ bool WrappedVulkan::Serialise_vkCmdDrawIndirect(Serialiser *localSerialiser,
// for single draws, it's pretty simple
buffer = GetResourceManager()->GetLiveHandle<VkBuffer>(bufid);
if(ShouldRerecordCmd(cmdid) && InRerecordRange(cmdid))
if(ShouldRerecordCmd(cmdid) && InRerecordRange(cmdid) && IsDrawInRenderPass())
{
commandBuffer = RerecordCmdBuf(cmdid);
@@ -271,7 +325,7 @@ bool WrappedVulkan::Serialise_vkCmdDrawIndirect(Serialiser *localSerialiser,
uint32_t baseEventID = it->eventID;
// when re-recording all, submit every drawcall individually to the callback
if(m_DrawcallCallback && m_DrawcallCallback->RecordAllCmds())
if(ShouldRerecordCmd(cmdid) && InRerecordRange(cmdid) && IsDrawInRenderPass())
{
for(uint32_t i = 0; i < cnt; i++)
{
@@ -314,14 +368,18 @@ bool WrappedVulkan::Serialise_vkCmdDrawIndirect(Serialiser *localSerialiser,
cnt = 1;
}
uint32_t eventID = HandlePreCallback(commandBuffer, false, drawidx + 1);
ObjDisp(commandBuffer)->CmdDrawIndirect(Unwrap(commandBuffer), Unwrap(buffer), offs, cnt, strd);
if(eventID && m_DrawcallCallback->PostDraw(eventID, commandBuffer))
if(IsDrawInRenderPass())
{
uint32_t eventID = HandlePreCallback(commandBuffer, false, drawidx + 1);
ObjDisp(commandBuffer)->CmdDrawIndirect(Unwrap(commandBuffer), Unwrap(buffer), offs, cnt, strd);
m_DrawcallCallback->PostRedraw(eventID, commandBuffer);
if(eventID && m_DrawcallCallback->PostDraw(eventID, commandBuffer))
{
ObjDisp(commandBuffer)
->CmdDrawIndirect(Unwrap(commandBuffer), Unwrap(buffer), offs, cnt, strd);
m_DrawcallCallback->PostRedraw(eventID, commandBuffer);
}
}
}
}
@@ -340,6 +398,13 @@ bool WrappedVulkan::Serialise_vkCmdDrawIndirect(Serialiser *localSerialiser,
string name = "vkCmdDrawIndirect(" + ToStr::Get(cnt) + ")";
if(!IsDrawInRenderPass())
{
AddDebugMessage(eDbgCategory_Execution, eDbgSeverity_High, eDbgSource_IncorrectAPIUse,
"Drawcall in happening outside of render pass, or in secondary command "
"buffer without RENDER_PASS_CONTINUE_BIT");
}
// for 'single' draws, don't do complex multi-draw just inline it
if(cnt <= 1)
{
@@ -482,7 +547,7 @@ bool WrappedVulkan::Serialise_vkCmdDrawIndexedIndirect(Serialiser *localSerialis
// for single draws, it's pretty simple
buffer = GetResourceManager()->GetLiveHandle<VkBuffer>(bufid);
if(ShouldRerecordCmd(cmdid) && InRerecordRange(cmdid))
if(ShouldRerecordCmd(cmdid) && InRerecordRange(cmdid) && IsDrawInRenderPass())
{
commandBuffer = RerecordCmdBuf(cmdid);
@@ -527,7 +592,7 @@ bool WrappedVulkan::Serialise_vkCmdDrawIndexedIndirect(Serialiser *localSerialis
uint32_t baseEventID = it->eventID;
// when re-recording all, submit every drawcall individually to the callback
if(m_DrawcallCallback && m_DrawcallCallback->RecordAllCmds())
if(m_DrawcallCallback && m_DrawcallCallback->RecordAllCmds() && IsDrawInRenderPass())
{
for(uint32_t i = 0; i < cnt; i++)
{
@@ -584,16 +649,19 @@ bool WrappedVulkan::Serialise_vkCmdDrawIndexedIndirect(Serialiser *localSerialis
}
}
uint32_t eventID = HandlePreCallback(commandBuffer, false, drawidx + 1);
ObjDisp(commandBuffer)
->CmdDrawIndexedIndirect(Unwrap(commandBuffer), Unwrap(buffer), offs, cnt, strd);
if(eventID && m_DrawcallCallback->PostDraw(eventID, commandBuffer))
if(IsDrawInRenderPass())
{
uint32_t eventID = HandlePreCallback(commandBuffer, false, drawidx + 1);
ObjDisp(commandBuffer)
->CmdDrawIndexedIndirect(Unwrap(commandBuffer), Unwrap(buffer), offs, cnt, strd);
m_DrawcallCallback->PostRedraw(eventID, commandBuffer);
if(eventID && m_DrawcallCallback->PostDraw(eventID, commandBuffer))
{
ObjDisp(commandBuffer)
->CmdDrawIndexedIndirect(Unwrap(commandBuffer), Unwrap(buffer), offs, cnt, strd);
m_DrawcallCallback->PostRedraw(eventID, commandBuffer);
}
}
}
}
@@ -612,6 +680,13 @@ bool WrappedVulkan::Serialise_vkCmdDrawIndexedIndirect(Serialiser *localSerialis
string name = "vkCmdDrawIndexedIndirect(" + ToStr::Get(cnt) + ")";
if(!IsDrawInRenderPass())
{
AddDebugMessage(eDbgCategory_Execution, eDbgSeverity_High, eDbgSource_IncorrectAPIUse,
"Drawcall in happening outside of render pass, or in secondary command "
"buffer without RENDER_PASS_CONTINUE_BIT");
}
// for 'single' draws, don't do complex multi-draw just inline it
if(cnt <= 1)
{