diff --git a/renderdoc/driver/vulkan/vk_common.h b/renderdoc/driver/vulkan/vk_common.h index 9e3d4edb8..d99fe6ef0 100644 --- a/renderdoc/driver/vulkan/vk_common.h +++ b/renderdoc/driver/vulkan/vk_common.h @@ -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); diff --git a/renderdoc/driver/vulkan/vk_core.cpp b/renderdoc/driver/vulkan/vk_core.cpp index 03117b4fc..ebed63868 100644 --- a/renderdoc/driver/vulkan/vk_core.cpp +++ b/renderdoc/driver/vulkan/vk_core.cpp @@ -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 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) diff --git a/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp index 4c04dfd14..e405201e7 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp @@ -102,8 +102,6 @@ ReplayStatus WrappedVulkan::Initialise(VkInitParams ¶ms, 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 ¶ms, 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; diff --git a/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp index b6c6953c0..b27df2b1b 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp @@ -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 &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());