Add option to fetch debug messages at runtime and display them in the UI

* By default this is off as it will continually add more and more
  messages each time the frame is replayed. It could be useful to turn
  on to
* We also enable VK_EXT_debug_report any time it's available, not just
  when we're enabling the validation layers.
This commit is contained in:
baldurk
2018-01-11 13:48:34 +00:00
parent da5cefbac2
commit 3170d8fa53
4 changed files with 72 additions and 18 deletions
+15 -6
View File
@@ -63,19 +63,28 @@
#include "serialise/serialiser.h"
#include "vk_dispatchtables.h"
// uncomment this to cause every internal QueueSubmit to immediately call
// DeviceWaitIdle(), and to only submit one command buffer at once to narrow
// down the cause of device lost errors
// enable this to cause every internal QueueSubmit to immediately call DeviceWaitIdle(), and to only
// submit one command buffer at once to narrow down the cause of device lost errors
#define SINGLE_FLUSH_VALIDATE OPTION_OFF
// uncomment this to get verbose debugging about when/where/why partial command
// buffer replay is happening
// enable this to get verbose debugging about when/where/why partial command buffer replay is
// happening
#define VERBOSE_PARTIAL_REPLAY OPTION_OFF
// uncomment this to enable validation layers on replay, useful for debugging
// enable this to enable validation layers on replay, useful for debugging
// problems with new replay code
#define FORCE_VALIDATION_LAYERS OPTION_OFF
// enable this to send replay-time validation layer messages to the UI.
// By default we only display saved validation layer messages from capture, and then any runtime
// messages we generate ourselves. With this option, every time the catpure is replayed, any
// messages will be bubbled up and added to the list in the UI - there is no deduplication so this
// will be an ever-growing list.
// This is independent of FORCE_VALIDATION_LAYERS above. We will listen to debug report if it's
// available whether or not we enabled the validation layers, and output any messages. This allows
// the ICD to generate messages for display
#define DISPLAY_RUNTIME_DEBUG_MESSAGES OPTION_OFF
ResourceFormat MakeResourceFormat(VkFormat fmt);
VkFormat MakeVkFormat(ResourceFormat fmt);
Topology MakePrimitiveTopology(VkPrimitiveTopology Topo, uint32_t patchControlPoints);
+33 -2
View File
@@ -1807,7 +1807,28 @@ bool WrappedVulkan::ContextProcessChunk(ReadSerialiser &ser, VulkanChunk chunk)
{
m_AddedDrawcall = false;
bool success = ProcessChunk(ser, chunk);
bool success = false;
#if ENABLED(DISPLAY_RUNTIME_DEBUG_MESSAGES)
// see the definition of DISPLAY_RUNTIME_DEBUG_MESSAGES for more information. During replay, add a
// debug sink to catch any replay-time messages
{
ScopedDebugMessageSink sink(this);
success = ProcessChunk(ser, chunk);
if(IsActiveReplaying(m_State))
{
std::vector<DebugMessage> DebugMessages;
DebugMessages.swap(sink.msgs);
for(const DebugMessage &msg : DebugMessages)
AddDebugMessage(msg);
}
}
#else
success = ProcessChunk(ser, chunk);
#endif
if(!success)
return false;
@@ -2465,7 +2486,6 @@ VkBool32 WrappedVulkan::DebugCallback(VkDebugReportFlagsEXT flags,
else if(!strcmp(pLayerPrefix, "PARAMCHECK") || !strcmp(pLayerPrefix, "ParameterValidation"))
isPARAM = true;
if(IsCaptureMode(m_State))
{
ScopedDebugMessageSink *sink = GetDebugMessageSink();
@@ -2480,6 +2500,17 @@ VkBool32 WrappedVulkan::DebugCallback(VkDebugReportFlagsEXT flags,
msg.messageID = messageCode;
msg.source = MessageSource::API;
// during replay we can get an eventId to correspond to this message.
if(IsActiveReplaying(m_State))
{
// 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);
if(it != m_DrawcallUses.end())
msg.eventId = it->eventId;
}
if(flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT)
msg.severity = MessageSeverity::Info;
else if(flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT)
@@ -102,8 +102,6 @@ ReplayStatus WrappedVulkan::Initialise(VkInitParams &params, uint64_t sectionVer
#if ENABLED(FORCE_VALIDATION_LAYERS) && DISABLED(RDOC_ANDROID)
params.Layers.push_back("VK_LAYER_LUNARG_standard_validation");
params.Extensions.push_back("VK_EXT_debug_report");
#endif
// strip out any WSI/direct display extensions. We'll add the ones we want for creating windows
@@ -181,6 +179,13 @@ ReplayStatus WrappedVulkan::Initialise(VkInitParams &params, uint64_t sectionVer
}
}
// we always want this extension if it's available
if(supportedExtensions.find(VK_EXT_DEBUG_REPORT_EXTENSION_NAME) != supportedExtensions.end())
{
RDCLOG("Enabling VK_EXT_debug_report");
params.Extensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
}
const char **layerscstr = new const char *[params.Layers.size()];
for(size_t i = 0; i < params.Layers.size(); i++)
layerscstr[i] = params.Layers[i].c_str();
@@ -955,10 +960,6 @@ bool WrappedVulkan::Serialise_vkCreateDevice(SerialiserType &ser, VkPhysicalDevi
RDCLOG("Enabling VK_AMD_shader_info");
}
#if ENABLED(FORCE_VALIDATION_LAYERS) && DISABLED(RDOC_ANDROID)
Layers.push_back("VK_LAYER_LUNARG_standard_validation");
#endif
createInfo.enabledLayerCount = (uint32_t)Layers.size();
const char **layerArray = NULL;
@@ -150,6 +150,16 @@ bool WrappedVulkan::Serialise_vkQueueSubmit(SerialiserType &ser, VkQueue queue,
if(doWait)
ObjDisp(queue)->QueueWaitIdle(Unwrap(queue));
// add a drawcall use for this submission, to tally up with any debug messages that come from it
if(IsLoading(m_State))
{
DrawcallUse use(m_CurChunkOffset, m_RootEventID);
// insert in sorted location
auto drawit = std::lower_bound(m_DrawcallUses.begin(), m_DrawcallUses.end(), use);
m_DrawcallUses.insert(drawit, use);
}
for(uint32_t sub = 0; sub < submitCount; sub++)
{
VkSubmitInfo submitInfo = pSubmits[sub];
@@ -382,11 +392,14 @@ void WrappedVulkan::InsertDrawsAndRefreshIDs(vector<VulkanDrawcallTreeNode> &cmd
m_Events.push_back(ev);
}
DrawcallUse use(m_Events.back().fileOffset, n.draw.eventId);
if(!n.draw.events.empty())
{
DrawcallUse use(n.draw.events.back().fileOffset, n.draw.eventId);
// insert in sorted location
auto drawit = std::lower_bound(m_DrawcallUses.begin(), m_DrawcallUses.end(), use);
m_DrawcallUses.insert(drawit, use);
// insert in sorted location
auto drawit = std::lower_bound(m_DrawcallUses.begin(), m_DrawcallUses.end(), use);
m_DrawcallUses.insert(drawit, use);
}
RDCASSERT(n.children.empty());