mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-13 21:40:41 +00:00
Add checks for drawcalls outside of render passes (primary/secondary)
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user