diff --git a/renderdoc/driver/vulkan/renderdoc.json b/renderdoc/driver/vulkan/renderdoc.json index 872b70c00..cd2b2ff78 100644 --- a/renderdoc/driver/vulkan/renderdoc.json +++ b/renderdoc/driver/vulkan/renderdoc.json @@ -14,6 +14,12 @@ "pre_instance_functions": { "vkEnumerateInstanceExtensionProperties": "VK_LAYER_RENDERDOC_CaptureEnumerateInstanceExtensionProperties" }, + "instance_extensions": [ + { + "name": "VK_EXT_debug_utils", + "spec_version": "1" + } + ], "device_extensions": [ { "name": "VK_EXT_debug_marker", @@ -25,7 +31,6 @@ "vkCmdDebugMarkerInsertEXT" ] } - ], "enable_environment": { "ENABLE_VULKAN_RENDERDOC_CAPTURE": "1" diff --git a/renderdoc/driver/vulkan/vk_common.h b/renderdoc/driver/vulkan/vk_common.h index f150bb0c1..cb3566045 100644 --- a/renderdoc/driver/vulkan/vk_common.h +++ b/renderdoc/driver/vulkan/vk_common.h @@ -474,6 +474,13 @@ enum class VulkanChunk : uint32_t vkBindBufferMemory2KHR, vkBindImageMemory2KHR, vkCmdWriteBufferMarkerAMD, + vkSetDebugUtilsObjectNameEXT, + vkQueueBeginDebugUtilsLabelEXT, + vkQueueEndDebugUtilsLabelEXT, + vkQueueInsertDebugUtilsLabelEXT, + vkCmdBeginDebugUtilsLabelEXT, + vkCmdEndDebugUtilsLabelEXT, + vkCmdInsertDebugUtilsLabelEXT, Max, }; @@ -628,6 +635,7 @@ DECLARE_REFLECTION_STRUCT(VkRenderPassInputAttachmentAspectCreateInfoKHR); DECLARE_REFLECTION_STRUCT(VkVertexInputBindingDivisorDescriptionEXT); DECLARE_REFLECTION_STRUCT(VkPipelineVertexInputDivisorStateCreateInfoEXT); DECLARE_REFLECTION_STRUCT(VkSamplerReductionModeCreateInfoEXT); +DECLARE_REFLECTION_STRUCT(VkDebugUtilsLabelEXT); DECLARE_DESERIALISE_TYPE(VkDeviceCreateInfo); DECLARE_DESERIALISE_TYPE(VkBufferCreateInfo); @@ -673,6 +681,7 @@ DECLARE_DESERIALISE_TYPE(VkImageViewUsageCreateInfoKHR); DECLARE_DESERIALISE_TYPE(VkRenderPassInputAttachmentAspectCreateInfoKHR); DECLARE_DESERIALISE_TYPE(VkPipelineVertexInputDivisorStateCreateInfoEXT); DECLARE_DESERIALISE_TYPE(VkSamplerReductionModeCreateInfoEXT); +DECLARE_DESERIALISE_TYPE(VkDebugUtilsLabelEXT); DECLARE_REFLECTION_ENUM(VkFlagWithNoBits); DECLARE_REFLECTION_ENUM(VkQueueFlagBits); diff --git a/renderdoc/driver/vulkan/vk_core.cpp b/renderdoc/driver/vulkan/vk_core.cpp index 1446e4ece..4d9dac88b 100644 --- a/renderdoc/driver/vulkan/vk_core.cpp +++ b/renderdoc/driver/vulkan/vk_core.cpp @@ -540,9 +540,15 @@ static const VkExtensionProperties supportedExtensions[] = { VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME, VK_EXT_CONSERVATIVE_RASTERIZATION_SPEC_VERSION, }, + { + VK_EXT_DEBUG_MARKER_EXTENSION_NAME, VK_EXT_DEBUG_MARKER_SPEC_VERSION, + }, { VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION, }, + { + VK_EXT_DEBUG_UTILS_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_SPEC_VERSION, + }, { VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME, VK_EXT_DIRECT_MODE_DISPLAY_SPEC_VERSION, }, @@ -737,6 +743,10 @@ static const VkExtensionProperties renderdocProvidedDeviceExtensions[] = { {VK_EXT_DEBUG_MARKER_EXTENSION_NAME, VK_EXT_DEBUG_MARKER_SPEC_VERSION}, }; +static const VkExtensionProperties renderdocProvidedInstanceExtensions[] = { + {VK_EXT_DEBUG_UTILS_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_SPEC_VERSION}, +}; + bool WrappedVulkan::IsSupportedExtension(const char *extName) { for(size_t i = 0; i < ARRAY_COUNT(supportedExtensions); i++) @@ -850,6 +860,12 @@ VkResult WrappedVulkan::FilterInstanceExtensionProperties( FilterToSupportedExtensions(exts, filtered); + // now we can add extensions that we provide ourselves (note this isn't sorted, but we + // don't have to sort the results, the sorting was just so we could filter optimally). + filtered.insert( + filtered.end(), &renderdocProvidedInstanceExtensions[0], + &renderdocProvidedInstanceExtensions[0] + ARRAY_COUNT(renderdocProvidedInstanceExtensions)); + return FillPropertyCountAndList(&filtered[0], (uint32_t)filtered.size(), pPropertyCount, pProperties); } @@ -1946,6 +1962,10 @@ bool WrappedVulkan::ContextProcessChunk(ReadSerialiser &ser, VulkanChunk chunk) { // don't add these events - they will be handled when inserted in-line into queue submit } + else if(chunk == VulkanChunk::vkQueueEndDebugUtilsLabelEXT) + { + // also ignore, this just pops the drawcall stack + } else { if(!m_AddedDrawcall) @@ -2315,6 +2335,28 @@ bool WrappedVulkan::ProcessChunk(ReadSerialiser &ser, VulkanChunk chunk) ser, VK_NULL_HANDLE, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_NULL_HANDLE, 0, 0); break; + case VulkanChunk::vkSetDebugUtilsObjectNameEXT: + return Serialise_vkSetDebugUtilsObjectNameEXT(ser, VK_NULL_HANDLE, NULL); + break; + case VulkanChunk::vkQueueBeginDebugUtilsLabelEXT: + return Serialise_vkQueueBeginDebugUtilsLabelEXT(ser, VK_NULL_HANDLE, NULL); + break; + case VulkanChunk::vkQueueEndDebugUtilsLabelEXT: + return Serialise_vkQueueEndDebugUtilsLabelEXT(ser, VK_NULL_HANDLE); + break; + case VulkanChunk::vkQueueInsertDebugUtilsLabelEXT: + return Serialise_vkQueueInsertDebugUtilsLabelEXT(ser, VK_NULL_HANDLE, NULL); + break; + case VulkanChunk::vkCmdBeginDebugUtilsLabelEXT: + return Serialise_vkCmdBeginDebugUtilsLabelEXT(ser, VK_NULL_HANDLE, NULL); + break; + case VulkanChunk::vkCmdEndDebugUtilsLabelEXT: + return Serialise_vkCmdEndDebugUtilsLabelEXT(ser, VK_NULL_HANDLE); + break; + case VulkanChunk::vkCmdInsertDebugUtilsLabelEXT: + return Serialise_vkCmdInsertDebugUtilsLabelEXT(ser, VK_NULL_HANDLE, NULL); + break; + default: { SystemChunk system = (SystemChunk)chunk; diff --git a/renderdoc/driver/vulkan/vk_core.h b/renderdoc/driver/vulkan/vk_core.h index 457cde1c6..e1d0979d3 100644 --- a/renderdoc/driver/vulkan/vk_core.h +++ b/renderdoc/driver/vulkan/vk_core.h @@ -679,8 +679,8 @@ private: bool EndFrameCapture(void *dev, void *wnd); template - bool Serialise_SetShaderDebugPath(SerialiserType &ser, VkDevice device, - const VkDebugMarkerObjectTagInfoEXT *pTagInfo); + bool Serialise_SetShaderDebugPath(SerialiserType &ser, VkShaderModule ShaderObject, + std::string DebugPath); // replay @@ -1695,7 +1695,45 @@ public: const VkDescriptorSetLayoutCreateInfo *pCreateInfo, VkDescriptorSetLayoutSupport *pSupport); + // VK_AMD_buffer_marker IMPLEMENT_FUNCTION_SERIALISED(void, vkCmdWriteBufferMarkerAMD, VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkBuffer dstBuffer, VkDeviceSize dstOffset, uint32_t marker); + + // VK_EXT_debug_utils + IMPLEMENT_FUNCTION_SERIALISED(VkResult, vkSetDebugUtilsObjectNameEXT, VkDevice device, + const VkDebugUtilsObjectNameInfoEXT *pNameInfo); + + IMPLEMENT_FUNCTION_SERIALISED(VkResult, vkSetDebugUtilsObjectTagEXT, VkDevice device, + const VkDebugUtilsObjectTagInfoEXT *pTagInfo); + + IMPLEMENT_FUNCTION_SERIALISED(void, vkQueueBeginDebugUtilsLabelEXT, VkQueue queue, + const VkDebugUtilsLabelEXT *pLabelInfo); + + IMPLEMENT_FUNCTION_SERIALISED(void, vkQueueEndDebugUtilsLabelEXT, VkQueue queue); + + IMPLEMENT_FUNCTION_SERIALISED(void, vkQueueInsertDebugUtilsLabelEXT, VkQueue queue, + const VkDebugUtilsLabelEXT *pLabelInfo); + + IMPLEMENT_FUNCTION_SERIALISED(void, vkCmdBeginDebugUtilsLabelEXT, VkCommandBuffer commandBuffer, + const VkDebugUtilsLabelEXT *pLabelInfo); + + IMPLEMENT_FUNCTION_SERIALISED(void, vkCmdEndDebugUtilsLabelEXT, VkCommandBuffer commandBuffer); + + IMPLEMENT_FUNCTION_SERIALISED(void, vkCmdInsertDebugUtilsLabelEXT, VkCommandBuffer commandBuffer, + const VkDebugUtilsLabelEXT *pLabelInfo); + + IMPLEMENT_FUNCTION_SERIALISED(VkResult, vkCreateDebugUtilsMessengerEXT, VkInstance instance, + const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo, + const VkAllocationCallbacks *pAllocator, + VkDebugUtilsMessengerEXT *pMessenger); + + IMPLEMENT_FUNCTION_SERIALISED(void, vkDestroyDebugUtilsMessengerEXT, VkInstance instance, + VkDebugUtilsMessengerEXT messenger, + const VkAllocationCallbacks *pAllocator); + + IMPLEMENT_FUNCTION_SERIALISED(void, vkSubmitDebugUtilsMessageEXT, VkInstance instance, + VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageTypes, + const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData); }; diff --git a/renderdoc/driver/vulkan/vk_dispatchtables.cpp b/renderdoc/driver/vulkan/vk_dispatchtables.cpp index 83cdeb9b9..240e89f76 100644 --- a/renderdoc/driver/vulkan/vk_dispatchtables.cpp +++ b/renderdoc/driver/vulkan/vk_dispatchtables.cpp @@ -113,6 +113,7 @@ void InitDeviceExtensionTables(VkDevice device, InstanceDeviceInfo *info) DeviceGPA(func); \ } + CheckInstanceExts(); CheckDeviceExts(); HookInitVulkanDeviceExts(); diff --git a/renderdoc/driver/vulkan/vk_hookset_defs.h b/renderdoc/driver/vulkan/vk_hookset_defs.h index 237fed455..36880e406 100644 --- a/renderdoc/driver/vulkan/vk_hookset_defs.h +++ b/renderdoc/driver/vulkan/vk_hookset_defs.h @@ -295,7 +295,8 @@ CheckExt(EXT_acquire_xlib_display, VKXX); \ CheckExt(KHR_external_memory_capabilities, VK11); \ CheckExt(KHR_external_semaphore_capabilities, VK11); \ - CheckExt(KHR_external_fence_capabilities, VK11); + CheckExt(KHR_external_fence_capabilities, VK11); \ + CheckExt(EXT_debug_utils, VKXX); #define CheckDeviceExts() \ CheckExt(EXT_debug_marker, VKXX); \ @@ -362,6 +363,9 @@ HookInitExtension(KHR_external_semaphore_capabilities, \ GetPhysicalDeviceExternalSemaphorePropertiesKHR); \ HookInitExtension(KHR_external_fence_capabilities, GetPhysicalDeviceExternalFencePropertiesKHR); \ + HookInitExtension(EXT_debug_utils, CreateDebugUtilsMessengerEXT); \ + HookInitExtension(EXT_debug_utils, DestroyDebugUtilsMessengerEXT); \ + HookInitExtension(EXT_debug_utils, SubmitDebugUtilsMessageEXT); \ HookInitInstance_PlatformSpecific() #define HookInitVulkanDeviceExts() \ @@ -401,6 +405,14 @@ HookInitExtension(KHR_bind_memory2, BindImageMemory2KHR); \ HookInitExtension(KHR_maintenance3, GetDescriptorSetLayoutSupportKHR); \ HookInitExtension(AMD_buffer_marker, CmdWriteBufferMarkerAMD); \ + HookInitExtension(EXT_debug_utils, SetDebugUtilsObjectNameEXT); \ + HookInitExtension(EXT_debug_utils, SetDebugUtilsObjectTagEXT); \ + HookInitExtension(EXT_debug_utils, QueueBeginDebugUtilsLabelEXT); \ + HookInitExtension(EXT_debug_utils, QueueEndDebugUtilsLabelEXT); \ + HookInitExtension(EXT_debug_utils, QueueInsertDebugUtilsLabelEXT); \ + HookInitExtension(EXT_debug_utils, CmdBeginDebugUtilsLabelEXT); \ + HookInitExtension(EXT_debug_utils, CmdEndDebugUtilsLabelEXT); \ + HookInitExtension(EXT_debug_utils, CmdInsertDebugUtilsLabelEXT); \ HookInitDevice_PlatformSpecific() #define DefineHooks() \ @@ -847,6 +859,29 @@ HookDefine5(void, vkCmdWriteBufferMarkerAMD, VkCommandBuffer, commandBuffer, \ VkPipelineStageFlagBits, pipelineStage, VkBuffer, dstBuffer, VkDeviceSize, \ dstOffset, uint32_t, marker); \ + HookDefine2(VkResult, vkSetDebugUtilsObjectNameEXT, VkDevice, device, \ + const VkDebugUtilsObjectNameInfoEXT *, pNameInfo); \ + HookDefine2(VkResult, vkSetDebugUtilsObjectTagEXT, VkDevice, device, \ + const VkDebugUtilsObjectTagInfoEXT *, pTagInfo); \ + HookDefine2(void, vkQueueBeginDebugUtilsLabelEXT, VkQueue, queue, const VkDebugUtilsLabelEXT *, \ + pLabelInfo); \ + HookDefine1(void, vkQueueEndDebugUtilsLabelEXT, VkQueue, queue); \ + HookDefine2(void, vkQueueInsertDebugUtilsLabelEXT, VkQueue, queue, const VkDebugUtilsLabelEXT *, \ + pLabelInfo); \ + HookDefine2(void, vkCmdBeginDebugUtilsLabelEXT, VkCommandBuffer, commandBuffer, \ + const VkDebugUtilsLabelEXT *, pLabelInfo); \ + HookDefine1(void, vkCmdEndDebugUtilsLabelEXT, VkCommandBuffer, commandBuffer); \ + HookDefine2(void, vkCmdInsertDebugUtilsLabelEXT, VkCommandBuffer, commandBuffer, \ + const VkDebugUtilsLabelEXT *, pLabelInfo); \ + HookDefine4(VkResult, vkCreateDebugUtilsMessengerEXT, VkInstance, instance, \ + const VkDebugUtilsMessengerCreateInfoEXT *, pCreateInfo, \ + const VkAllocationCallbacks *, pAllocator, VkDebugUtilsMessengerEXT *, pMessenger); \ + HookDefine3(void, vkDestroyDebugUtilsMessengerEXT, VkInstance, instance, \ + VkDebugUtilsMessengerEXT, messenger, const VkAllocationCallbacks *, pAllocator); \ + HookDefine4(void, vkSubmitDebugUtilsMessageEXT, VkInstance, instance, \ + VkDebugUtilsMessageSeverityFlagBitsEXT, messageSeverity, \ + VkDebugUtilsMessageTypeFlagsEXT, messageTypes, \ + const VkDebugUtilsMessengerCallbackDataEXT *, pCallbackData); \ HookDefine_PlatformSpecific() struct VkLayerInstanceDispatchTableExtended : VkLayerInstanceDispatchTable diff --git a/renderdoc/driver/vulkan/vk_layer.cpp b/renderdoc/driver/vulkan/vk_layer.cpp index d385dceb6..46ca57821 100644 --- a/renderdoc/driver/vulkan/vk_layer.cpp +++ b/renderdoc/driver/vulkan/vk_layer.cpp @@ -293,6 +293,7 @@ VK_LAYER_RENDERDOC_CaptureGetDeviceProcAddr(VkDevice device, const char *pName) InstanceDeviceInfo *instDevInfo = GetRecord(device)->instDevInfo; + CheckInstanceExts(); CheckDeviceExts(); HookInitVulkanDeviceExts(); diff --git a/renderdoc/driver/vulkan/vk_serialise.cpp b/renderdoc/driver/vulkan/vk_serialise.cpp index 5afbbcee0..e5dcb4447 100644 --- a/renderdoc/driver/vulkan/vk_serialise.cpp +++ b/renderdoc/driver/vulkan/vk_serialise.cpp @@ -2349,6 +2349,22 @@ void Deserialise(const VkSamplerReductionModeCreateInfoEXT &el) DeserialiseNext(el.pNext); } +template +void DoSerialise(SerialiserType &ser, VkDebugUtilsLabelEXT &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(pLabelName); + SERIALISE_MEMBER(color); +} + +template <> +void Deserialise(const VkDebugUtilsLabelEXT &el) +{ + DeserialiseNext(el.pNext); +} + INSTANTIATE_SERIALISE_TYPE(VkOffset2D); INSTANTIATE_SERIALISE_TYPE(VkExtent2D); INSTANTIATE_SERIALISE_TYPE(VkMemoryType); @@ -2452,6 +2468,7 @@ INSTANTIATE_SERIALISE_TYPE(VkBindImageMemoryInfoKHR); INSTANTIATE_SERIALISE_TYPE(VkPipelineRasterizationConservativeStateCreateInfoEXT); INSTANTIATE_SERIALISE_TYPE(VkPipelineVertexInputDivisorStateCreateInfoEXT); INSTANTIATE_SERIALISE_TYPE(VkSamplerReductionModeCreateInfoEXT); +INSTANTIATE_SERIALISE_TYPE(VkDebugUtilsLabelEXT); INSTANTIATE_SERIALISE_TYPE(DescriptorSetSlot); INSTANTIATE_SERIALISE_TYPE(ImageRegionState); diff --git a/renderdoc/driver/vulkan/vk_stringise.cpp b/renderdoc/driver/vulkan/vk_stringise.cpp index eda7426dd..0dfe98965 100644 --- a/renderdoc/driver/vulkan/vk_stringise.cpp +++ b/renderdoc/driver/vulkan/vk_stringise.cpp @@ -28,7 +28,7 @@ template <> std::string DoStringise(const VulkanChunk &el) { - RDCCOMPILE_ASSERT((uint32_t)VulkanChunk::Max == 1105, "Chunks changed without updating names"); + RDCCOMPILE_ASSERT((uint32_t)VulkanChunk::Max == 1112, "Chunks changed without updating names"); BEGIN_ENUM_STRINGISE(VulkanChunk) { @@ -137,6 +137,13 @@ std::string DoStringise(const VulkanChunk &el) STRINGISE_ENUM_CLASS(vkBindBufferMemory2KHR); STRINGISE_ENUM_CLASS(vkBindImageMemory2KHR); STRINGISE_ENUM_CLASS(vkCmdWriteBufferMarkerAMD); + STRINGISE_ENUM_CLASS(vkSetDebugUtilsObjectNameEXT); + STRINGISE_ENUM_CLASS(vkQueueBeginDebugUtilsLabelEXT); + STRINGISE_ENUM_CLASS(vkQueueEndDebugUtilsLabelEXT); + STRINGISE_ENUM_CLASS(vkQueueInsertDebugUtilsLabelEXT); + STRINGISE_ENUM_CLASS(vkCmdBeginDebugUtilsLabelEXT); + STRINGISE_ENUM_CLASS(vkCmdEndDebugUtilsLabelEXT); + STRINGISE_ENUM_CLASS(vkCmdInsertDebugUtilsLabelEXT); STRINGISE_ENUM_CLASS_NAMED(Max, "Max Chunk"); } END_ENUM_STRINGISE() diff --git a/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp index cafaf2712..cbf202956 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp @@ -3579,6 +3579,217 @@ void WrappedVulkan::vkCmdWriteBufferMarkerAMD(VkCommandBuffer commandBuffer, } } +template +bool WrappedVulkan::Serialise_vkCmdBeginDebugUtilsLabelEXT(SerialiserType &ser, + VkCommandBuffer commandBuffer, + const VkDebugUtilsLabelEXT *pLabelInfo) +{ + SERIALISE_ELEMENT(commandBuffer); + SERIALISE_ELEMENT_LOCAL(Label, *pLabelInfo); + + SERIALISE_CHECK_READ_ERRORS(); + + if(IsReplayingAndReading()) + { + m_LastCmdBufferID = GetResourceManager()->GetOriginalID(GetResID(commandBuffer)); + + if(IsActiveReplaying(m_State)) + { + if(InRerecordRange(m_LastCmdBufferID)) + { + commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); + + m_BakedCmdBufferInfo[m_LastCmdBufferID].markerCount++; + + if(ObjDisp(commandBuffer)->CmdBeginDebugUtilsLabelEXT) + ObjDisp(commandBuffer)->CmdBeginDebugUtilsLabelEXT(Unwrap(commandBuffer), &Label); + } + } + else + { + if(ObjDisp(commandBuffer)->CmdBeginDebugUtilsLabelEXT) + ObjDisp(commandBuffer)->CmdBeginDebugUtilsLabelEXT(Unwrap(commandBuffer), &Label); + + DrawcallDescription draw; + draw.name = Label.pLabelName; + draw.flags |= DrawFlags::PushMarker; + + draw.markerColor[0] = RDCCLAMP(Label.color[0], 0.0f, 1.0f); + draw.markerColor[1] = RDCCLAMP(Label.color[1], 0.0f, 1.0f); + draw.markerColor[2] = RDCCLAMP(Label.color[2], 0.0f, 1.0f); + draw.markerColor[3] = RDCCLAMP(Label.color[3], 0.0f, 1.0f); + + AddEvent(); + AddDrawcall(draw, false); + } + } + + return true; +} + +void WrappedVulkan::vkCmdBeginDebugUtilsLabelEXT(VkCommandBuffer commandBuffer, + const VkDebugUtilsLabelEXT *pLabelInfo) +{ + if(ObjDisp(commandBuffer)->CmdBeginDebugUtilsLabelEXT) + { + SERIALISE_TIME_CALL( + ObjDisp(commandBuffer)->CmdBeginDebugUtilsLabelEXT(Unwrap(commandBuffer), pLabelInfo)); + } + + if(IsCaptureMode(m_State)) + { + VkResourceRecord *record = GetRecord(commandBuffer); + + CACHE_THREAD_SERIALISER(); + ser.SetDrawChunk(); + SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdBeginDebugUtilsLabelEXT); + Serialise_vkCmdBeginDebugUtilsLabelEXT(ser, commandBuffer, pLabelInfo); + + record->AddChunk(scope.Get()); + } +} + +template +bool WrappedVulkan::Serialise_vkCmdEndDebugUtilsLabelEXT(SerialiserType &ser, + VkCommandBuffer commandBuffer) +{ + SERIALISE_ELEMENT(commandBuffer); + + SERIALISE_CHECK_READ_ERRORS(); + + if(IsReplayingAndReading()) + { + m_LastCmdBufferID = GetResourceManager()->GetOriginalID(GetResID(commandBuffer)); + + if(IsActiveReplaying(m_State)) + { + if(InRerecordRange(m_LastCmdBufferID)) + { + commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); + + int &markerCount = m_BakedCmdBufferInfo[m_LastCmdBufferID].markerCount; + markerCount = RDCMAX(0, markerCount - 1); + + if(ObjDisp(commandBuffer)->CmdEndDebugUtilsLabelEXT) + ObjDisp(commandBuffer)->CmdEndDebugUtilsLabelEXT(Unwrap(commandBuffer)); + } + } + else + { + if(ObjDisp(commandBuffer)->CmdEndDebugUtilsLabelEXT) + ObjDisp(commandBuffer)->CmdEndDebugUtilsLabelEXT(Unwrap(commandBuffer)); + + if(!m_BakedCmdBufferInfo[m_LastCmdBufferID].curEvents.empty()) + { + DrawcallDescription draw; + draw.name = "API Calls"; + draw.flags = DrawFlags::APICalls; + + AddDrawcall(draw, true); + } + + // dummy draw that is consumed when this command buffer + // is being in-lined into the call stream + DrawcallDescription draw; + draw.name = "Pop()"; + draw.flags = DrawFlags::PopMarker; + + AddEvent(); + AddDrawcall(draw, false); + } + } + + return true; +} + +void WrappedVulkan::vkCmdEndDebugUtilsLabelEXT(VkCommandBuffer commandBuffer) +{ + if(ObjDisp(commandBuffer)->CmdEndDebugUtilsLabelEXT) + { + SERIALISE_TIME_CALL(ObjDisp(commandBuffer)->CmdEndDebugUtilsLabelEXT(Unwrap(commandBuffer))); + } + + if(IsCaptureMode(m_State)) + { + VkResourceRecord *record = GetRecord(commandBuffer); + + CACHE_THREAD_SERIALISER(); + ser.SetDrawChunk(); + SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdEndDebugUtilsLabelEXT); + Serialise_vkCmdEndDebugUtilsLabelEXT(ser, commandBuffer); + + record->AddChunk(scope.Get()); + } +} + +template +bool WrappedVulkan::Serialise_vkCmdInsertDebugUtilsLabelEXT(SerialiserType &ser, + VkCommandBuffer commandBuffer, + const VkDebugUtilsLabelEXT *pLabelInfo) +{ + SERIALISE_ELEMENT(commandBuffer); + SERIALISE_ELEMENT_LOCAL(Label, *pLabelInfo); + + SERIALISE_CHECK_READ_ERRORS(); + + if(IsReplayingAndReading()) + { + m_LastCmdBufferID = GetResourceManager()->GetOriginalID(GetResID(commandBuffer)); + + if(IsActiveReplaying(m_State)) + { + if(InRerecordRange(m_LastCmdBufferID)) + { + commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); + + if(ObjDisp(commandBuffer)->CmdInsertDebugUtilsLabelEXT) + ObjDisp(commandBuffer)->CmdInsertDebugUtilsLabelEXT(Unwrap(commandBuffer), &Label); + } + } + else + { + if(ObjDisp(commandBuffer)->CmdInsertDebugUtilsLabelEXT) + ObjDisp(commandBuffer)->CmdInsertDebugUtilsLabelEXT(Unwrap(commandBuffer), &Label); + + DrawcallDescription draw; + draw.name = Label.pLabelName; + draw.flags |= DrawFlags::SetMarker; + + draw.markerColor[0] = RDCCLAMP(Label.color[0], 0.0f, 1.0f); + draw.markerColor[1] = RDCCLAMP(Label.color[1], 0.0f, 1.0f); + draw.markerColor[2] = RDCCLAMP(Label.color[2], 0.0f, 1.0f); + draw.markerColor[3] = RDCCLAMP(Label.color[3], 0.0f, 1.0f); + + AddEvent(); + AddDrawcall(draw, false); + } + } + + return true; +} + +void WrappedVulkan::vkCmdInsertDebugUtilsLabelEXT(VkCommandBuffer commandBuffer, + const VkDebugUtilsLabelEXT *pLabelInfo) +{ + if(ObjDisp(commandBuffer)->CmdInsertDebugUtilsLabelEXT) + { + SERIALISE_TIME_CALL( + ObjDisp(commandBuffer)->CmdInsertDebugUtilsLabelEXT(Unwrap(commandBuffer), pLabelInfo)); + } + + if(IsCaptureMode(m_State)) + { + VkResourceRecord *record = GetRecord(commandBuffer); + + CACHE_THREAD_SERIALISER(); + ser.SetDrawChunk(); + SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdInsertDebugUtilsLabelEXT); + Serialise_vkCmdInsertDebugUtilsLabelEXT(ser, commandBuffer, pLabelInfo); + + record->AddChunk(scope.Get()); + } +} + INSTANTIATE_FUNCTION_SERIALISED(VkResult, vkCreateCommandPool, VkDevice device, const VkCommandPoolCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkCommandPool *pCommandPool); @@ -3679,4 +3890,12 @@ INSTANTIATE_FUNCTION_SERIALISED(void, vkCmdPushDescriptorSetWithTemplateKHR, INSTANTIATE_FUNCTION_SERIALISED(void, vkCmdWriteBufferMarkerAMD, VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkBuffer dstBuffer, - VkDeviceSize dstOffset, uint32_t marker); \ No newline at end of file + VkDeviceSize dstOffset, uint32_t marker); + +INSTANTIATE_FUNCTION_SERIALISED(void, vkCmdBeginDebugUtilsLabelEXT, VkCommandBuffer commandBuffer, + const VkDebugUtilsLabelEXT *pLabelInfo); + +INSTANTIATE_FUNCTION_SERIALISED(void, vkCmdEndDebugUtilsLabelEXT, VkCommandBuffer commandBuffer); + +INSTANTIATE_FUNCTION_SERIALISED(void, vkCmdInsertDebugUtilsLabelEXT, VkCommandBuffer commandBuffer, + const VkDebugUtilsLabelEXT *pLabelInfo); diff --git a/renderdoc/driver/vulkan/wrappers/vk_misc_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_misc_funcs.cpp index fd692b2ce..ad0fdff98 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_misc_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_misc_funcs.cpp @@ -1011,7 +1011,7 @@ VkResult WrappedVulkan::vkGetQueryPoolResults(VkDevice device, VkQueryPool query queryCount, dataSize, pData, stride, flags); } -struct UserDebugCallbackData +struct UserDebugReportCallbackData { VkInstance wrappedInstance; VkDebugReportCallbackCreateInfoEXT createInfo; @@ -1020,12 +1020,13 @@ struct UserDebugCallbackData VkDebugReportCallbackEXT realObject; }; -VkBool32 VKAPI_PTR UserDebugCallback(VkDebugReportFlagsEXT flags, - VkDebugReportObjectTypeEXT objectType, uint64_t object, - size_t location, int32_t messageCode, const char *pLayerPrefix, - const char *pMessage, void *pUserData) +VkBool32 VKAPI_PTR UserDebugReportCallback(VkDebugReportFlagsEXT flags, + VkDebugReportObjectTypeEXT objectType, uint64_t object, + size_t location, int32_t messageCode, + const char *pLayerPrefix, const char *pMessage, + void *pUserData) { - UserDebugCallbackData *user = (UserDebugCallbackData *)pUserData; + UserDebugReportCallbackData *user = (UserDebugReportCallbackData *)pUserData; if(RenderDoc::Inst().GetCaptureOptions().debugOutputMute) { @@ -1061,22 +1062,77 @@ VkBool32 VKAPI_PTR UserDebugCallback(VkDebugReportFlagsEXT flags, return user->createInfo.pfnCallback(flags, objectType, object, location, messageCode, pLayerPrefix, pMessage, user->createInfo.pUserData); } +struct UserDebugUtilsCallbackData +{ + VkDebugUtilsMessengerCreateInfoEXT createInfo; + bool muteWarned; + + VkDebugUtilsMessengerEXT realObject; +}; + +VkBool32 VKAPI_PTR UserDebugUtilsCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageType, + const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, + void *pUserData) +{ + UserDebugUtilsCallbackData *user = (UserDebugUtilsCallbackData *)pUserData; + + if(RenderDoc::Inst().GetCaptureOptions().debugOutputMute) + { + if(user->muteWarned) + return false; + + // once only insert a fake message notifying of the muting + user->muteWarned = true; + + // we insert as an information message, since some trigger-happy applications might + // debugbreak/crash/messagebox/etc on even warnings. This puts us in the same pool + // as extremely spammy messages, but there's not much alternative. + if(user->createInfo.messageSeverity & (VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT)) + { + // use information type if possible, or if it's not accepted but debug is - use debug type. + messageSeverity = + (user->createInfo.messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) + ? VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT + : VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT; + + VkDebugUtilsMessengerCallbackDataEXT data = {}; + + data.messageIdNumber = 1; + data.pMessageIdName = NULL; + data.pMessage = + "While debugging through RenderDoc, debug output through validation layers is " + "suppressed.\n" + "To show debug output look at the 'DebugOutputMute' capture option in RenderDoc's API, " + "but be aware of false positives from the validation layers."; + data.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT; + + user->createInfo.pfnUserCallback(messageSeverity, VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, + &data, user->createInfo.pUserData); + } + + return false; + } + + return user->createInfo.pfnUserCallback(messageSeverity, messageType, pCallbackData, + user->createInfo.pUserData); +} VkResult WrappedVulkan::vkCreateDebugReportCallbackEXT( VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pCallback) { // we create an interception object here so that we can dynamically check the state of API - // messages - // being muted, since it's quite likely that the application will initialise Vulkan (and so create - // a debug report callback) before it messes with RenderDoc's API to unmute messages. - UserDebugCallbackData *user = new UserDebugCallbackData(); + // messages being muted, since it's quite likely that the application will initialise Vulkan (and + // so create a debug report callback) before it messes with RenderDoc's API to unmute messages. + UserDebugReportCallbackData *user = new UserDebugReportCallbackData(); user->wrappedInstance = instance; user->createInfo = *pCreateInfo; user->muteWarned = false; VkDebugReportCallbackCreateInfoEXT wrappedCreateInfo = *pCreateInfo; - wrappedCreateInfo.pfnCallback = &UserDebugCallback; + wrappedCreateInfo.pfnCallback = &UserDebugReportCallback; wrappedCreateInfo.pUserData = user; VkResult vkr = ObjDisp(instance)->CreateDebugReportCallbackEXT( @@ -1098,7 +1154,8 @@ void WrappedVulkan::vkDestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks *pAllocator) { - UserDebugCallbackData *user = (UserDebugCallbackData *)(uintptr_t)NON_DISP_TO_UINT64(callback); + UserDebugReportCallbackData *user = + (UserDebugReportCallbackData *)(uintptr_t)NON_DISP_TO_UINT64(callback); ObjDisp(instance)->DestroyDebugReportCallbackEXT(Unwrap(instance), user->realObject, pAllocator); @@ -1114,82 +1171,177 @@ void WrappedVulkan::vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFl location, messageCode, pLayerPrefix, pMessage); } -static VkResourceRecord *GetObjRecord(VkDebugReportObjectTypeEXT objType, uint64_t object) +// we use VkObjectType as the object type since it mostly overlaps with the debug report enum so in +// most cases we can upcast it. There's an overload to translate the few that might conflict. +// Likewise to re-use the switch in most cases, we return both the record and the unwrapped +// object at once. In *most* cases the unwrapped object comes from the record, but there are a few +// exceptions which don't have records, or aren't wrapped, etc. +struct ObjData { + VkResourceRecord *record; + uint64_t unwrapped; +}; + +static ObjData GetObjData(VkObjectType objType, uint64_t object) +{ + ObjData ret = {}; + switch(objType) { - case VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT: return GetRecord((VkInstance)object); - case VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT: - return GetRecord((VkPhysicalDevice)object); - case VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT: return GetRecord((VkDevice)object); - case VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT: return GetRecord((VkQueue)object); - case VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT: return GetRecord((VkCommandBuffer)object); - case VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT: return GetRecord((VkDeviceMemory)object); - case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT: return GetRecord((VkBuffer)object); - case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT: return GetRecord((VkBufferView)object); - case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT: return GetRecord((VkImage)object); - case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT: return GetRecord((VkImageView)object); - case VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT: return GetRecord((VkShaderModule)object); - case VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT: return GetRecord((VkPipeline)object); - case VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT: - return GetRecord((VkPipelineLayout)object); - case VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT: return GetRecord((VkSampler)object); - case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT: return GetRecord((VkDescriptorSet)object); - case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT: - return GetRecord((VkDescriptorSetLayout)object); - case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT: - return GetRecord((VkDescriptorPool)object); - case VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT: return GetRecord((VkFence)object); - case VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT: return GetRecord((VkSemaphore)object); - case VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT: return GetRecord((VkEvent)object); - case VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT: return GetRecord((VkQueryPool)object); - case VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT: return GetRecord((VkFramebuffer)object); - case VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT: return GetRecord((VkRenderPass)object); - case VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT: return GetRecord((VkPipelineCache)object); - case VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT: return GetRecord((VkSurfaceKHR)object); - case VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT: return GetRecord((VkSwapchainKHR)object); - case VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT: return GetRecord((VkCommandPool)object); - case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT: - return GetRecord((VkDescriptorUpdateTemplateKHR)object); - case VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT: - case VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT: - case VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT: - case VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT: - case VK_DEBUG_REPORT_OBJECT_TYPE_RANGE_SIZE_EXT: - case VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT: - case VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT: - case VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT: - case VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT: - case VK_DEBUG_REPORT_OBJECT_TYPE_MAX_ENUM_EXT: break; + case VK_OBJECT_TYPE_INSTANCE: ret.record = GetRecord((VkInstance)object); break; + case VK_OBJECT_TYPE_PHYSICAL_DEVICE: ret.record = GetRecord((VkPhysicalDevice)object); break; + case VK_OBJECT_TYPE_DEVICE: ret.record = GetRecord((VkDevice)object); break; + case VK_OBJECT_TYPE_QUEUE: ret.record = GetRecord((VkQueue)object); break; + case VK_OBJECT_TYPE_SEMAPHORE: ret.record = GetRecord((VkSemaphore)object); break; + case VK_OBJECT_TYPE_COMMAND_BUFFER: ret.record = GetRecord((VkCommandBuffer)object); break; + case VK_OBJECT_TYPE_FENCE: ret.record = GetRecord((VkFence)object); break; + case VK_OBJECT_TYPE_DEVICE_MEMORY: ret.record = GetRecord((VkDeviceMemory)object); break; + case VK_OBJECT_TYPE_BUFFER: ret.record = GetRecord((VkBuffer)object); break; + case VK_OBJECT_TYPE_IMAGE: ret.record = GetRecord((VkImage)object); break; + case VK_OBJECT_TYPE_EVENT: ret.record = GetRecord((VkEvent)object); break; + case VK_OBJECT_TYPE_QUERY_POOL: ret.record = GetRecord((VkQueryPool)object); break; + case VK_OBJECT_TYPE_BUFFER_VIEW: ret.record = GetRecord((VkBufferView)object); break; + case VK_OBJECT_TYPE_IMAGE_VIEW: ret.record = GetRecord((VkImageView)object); break; + case VK_OBJECT_TYPE_SHADER_MODULE: ret.record = GetRecord((VkShaderModule)object); break; + case VK_OBJECT_TYPE_PIPELINE_CACHE: ret.record = GetRecord((VkPipelineCache)object); break; + case VK_OBJECT_TYPE_PIPELINE_LAYOUT: ret.record = GetRecord((VkPipelineLayout)object); break; + case VK_OBJECT_TYPE_RENDER_PASS: ret.record = GetRecord((VkRenderPass)object); break; + case VK_OBJECT_TYPE_PIPELINE: ret.record = GetRecord((VkPipeline)object); break; + case VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT: + ret.record = GetRecord((VkDescriptorSetLayout)object); + break; + case VK_OBJECT_TYPE_SAMPLER: ret.record = GetRecord((VkSampler)object); break; + case VK_OBJECT_TYPE_DESCRIPTOR_POOL: ret.record = GetRecord((VkDescriptorPool)object); break; + case VK_OBJECT_TYPE_DESCRIPTOR_SET: ret.record = GetRecord((VkDescriptorSet)object); break; + case VK_OBJECT_TYPE_FRAMEBUFFER: ret.record = GetRecord((VkFramebuffer)object); break; + case VK_OBJECT_TYPE_COMMAND_POOL: ret.record = GetRecord((VkCommandPool)object); break; + + case VK_OBJECT_TYPE_SWAPCHAIN_KHR: ret.record = GetRecord((VkSwapchainKHR)object); break; + case VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE: + ret.record = GetRecord((VkDescriptorUpdateTemplateKHR)object); + break; + + ///////////////////////////// + // special cases + + // VkSurfaceKHR doesn't have a record + case VK_OBJECT_TYPE_SURFACE_KHR: + ret.unwrapped = GetWrapped((VkSurfaceKHR)object)->real.handle; + break; + + // VkDisplayKHR and VkDisplayModeKHR are not wrapped + case VK_OBJECT_TYPE_DISPLAY_KHR: + case VK_OBJECT_TYPE_DISPLAY_MODE_KHR: + ret.unwrapped = object; + break; + + // debug report callback and messenger are not wrapped in the conventional way + case VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT: + { + UserDebugReportCallbackData *user = (UserDebugReportCallbackData *)(uintptr_t)object; + ret.unwrapped = NON_DISP_TO_UINT64(user->realObject); + break; + } + + case VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT: + { + UserDebugUtilsCallbackData *user = (UserDebugUtilsCallbackData *)(uintptr_t)object; + ret.unwrapped = NON_DISP_TO_UINT64(user->realObject); + break; + } + + // these objects are not supported + case VK_OBJECT_TYPE_OBJECT_TABLE_NVX: + case VK_OBJECT_TYPE_VALIDATION_CACHE_EXT: + case VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX: + case VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION: + case VK_OBJECT_TYPE_UNKNOWN: + case VK_OBJECT_TYPE_RANGE_SIZE: + case VK_OBJECT_TYPE_MAX_ENUM: break; } - return NULL; + + RDCCOMPILE_ASSERT(VK_OBJECT_TYPE_END_RANGE == VK_OBJECT_TYPE_COMMAND_POOL, + "Enum added to object type"); + + // if we have a record and no unwrapped object, fetch it out of the record + if(ret.record && ret.unwrapped == 0) + { + switch(objType) + { + // dispatchable objects + case VK_OBJECT_TYPE_INSTANCE: + case VK_OBJECT_TYPE_PHYSICAL_DEVICE: + case VK_OBJECT_TYPE_QUEUE: + case VK_OBJECT_TYPE_DEVICE: + case VK_OBJECT_TYPE_COMMAND_BUFFER: + { + WrappedVkDispRes *res = (WrappedVkDispRes *)ret.record->Resource; + ret.unwrapped = res->real.handle; + break; + } + + // non-dispatchable objects + default: + { + WrappedVkNonDispRes *res = (WrappedVkNonDispRes *)ret.record->Resource; + ret.unwrapped = res->real.handle; + break; + } + } + } + + return ret; +} + +// overload to silently cast +static ObjData GetObjData(VkDebugReportObjectTypeEXT objType, uint64_t object) +{ + VkObjectType castType = (VkObjectType)objType; + + // a few special cases don't overlap and will conflict when more core objects are added to + // VkObjectType so we don't cast them. + if(objType == VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT) + castType = VK_OBJECT_TYPE_SWAPCHAIN_KHR; + else if(objType == VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT) + castType = VK_OBJECT_TYPE_SURFACE_KHR; + else if(objType == VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT) + castType = VK_OBJECT_TYPE_DISPLAY_KHR; + else if(objType == VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT) + castType = VK_OBJECT_TYPE_DISPLAY_MODE_KHR; + else if(objType == VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT) + castType = VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT; + else if(objType == VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT) + castType = VK_OBJECT_TYPE_OBJECT_TABLE_NVX; + else if(objType == VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT) + castType = VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX; + else if(objType == VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT) + castType = VK_OBJECT_TYPE_VALIDATION_CACHE_EXT; + else if(objType == VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT) + castType = VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION; + else if(objType == VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT) + castType = VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE; + + RDCCOMPILE_ASSERT(VK_DEBUG_REPORT_OBJECT_TYPE_END_RANGE_EXT == + VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT, + "Enum added to debug report object type"); + + return GetObjData((VkObjectType)objType, object); } template -bool WrappedVulkan::Serialise_SetShaderDebugPath(SerialiserType &ser, VkDevice device, - const VkDebugMarkerObjectTagInfoEXT *pTagInfo) +bool WrappedVulkan::Serialise_SetShaderDebugPath(SerialiserType &ser, VkShaderModule ShaderObject, + std::string DebugPath) { - SERIALISE_ELEMENT_LOCAL(ShaderObject, - GetObjRecord(pTagInfo->objectType, pTagInfo->object)->GetResourceID()) - .TypedAs("VkShaderModule"); - - std::string DebugPath; - if(IsCaptureMode(m_State)) - { - char *tag = (char *)pTagInfo->pTag; - DebugPath = std::string(tag, tag + pTagInfo->tagSize); - } - + SERIALISE_ELEMENT(ShaderObject); SERIALISE_ELEMENT(DebugPath); SERIALISE_CHECK_READ_ERRORS(); if(IsReplayingAndReading()) { - m_CreationInfo.m_ShaderModule[GetResourceManager()->GetLiveID(ShaderObject)].unstrippedPath = - DebugPath; + m_CreationInfo.m_ShaderModule[GetResID(ShaderObject)].unstrippedPath = DebugPath; - AddResourceCurChunk(ShaderObject); + AddResourceCurChunk(GetResourceManager()->GetOriginalID(GetResID(ShaderObject))); } return true; @@ -1200,50 +1352,25 @@ VkResult WrappedVulkan::vkDebugMarkerSetObjectTagEXT(VkDevice device, { if(IsCaptureMode(m_State) && pTagInfo) { - VkResourceRecord *record = GetObjRecord(pTagInfo->objectType, pTagInfo->object); + ObjData data = GetObjData(pTagInfo->objectType, pTagInfo->object); - if(!record) - { - RDCERR("Unrecognised object %d %llu", pTagInfo->objectType, pTagInfo->object); - return VK_SUCCESS; - } - - if(pTagInfo->tagName == RENDERDOC_ShaderDebugMagicValue_truncated && + if(data.record && pTagInfo->tagName == RENDERDOC_ShaderDebugMagicValue_truncated && pTagInfo->objectType == VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT) { CACHE_THREAD_SERIALISER(); + char *tag = (char *)pTagInfo->pTag; + std::string DebugPath = std::string(tag, tag + pTagInfo->tagSize); + SCOPED_SERIALISE_CHUNK(VulkanChunk::SetShaderDebugPath); - Serialise_SetShaderDebugPath(ser, device, pTagInfo); - record->AddChunk(scope.Get()); + Serialise_SetShaderDebugPath(ser, (VkShaderModule)data.record->Resource, DebugPath); + data.record->AddChunk(scope.Get()); } else if(ObjDisp(device)->DebugMarkerSetObjectTagEXT) { VkDebugMarkerObjectTagInfoEXT unwrapped = *pTagInfo; - // special case for VkSurfaceKHR - the record pointer is actually just the underlying native - // window handle, so instead we unwrap and call through. - if(unwrapped.objectType == VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT) - { - unwrapped.object = GetWrapped((VkSurfaceKHR)unwrapped.object)->real.handle; - - return ObjDisp(device)->DebugMarkerSetObjectTagEXT(device, &unwrapped); - } - - if(unwrapped.objectType == VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT || - unwrapped.objectType == VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT || - unwrapped.objectType == VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT || - unwrapped.objectType == VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT || - unwrapped.objectType == VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT) - { - WrappedVkDispRes *res = (WrappedVkDispRes *)record->Resource; - unwrapped.object = res->real.handle; - } - else - { - WrappedVkNonDispRes *res = (WrappedVkNonDispRes *)record->Resource; - unwrapped.object = res->real.handle; - } + unwrapped.object = data.unwrapped; return ObjDisp(device)->DebugMarkerSetObjectTagEXT(device, &unwrapped); } @@ -1256,8 +1383,8 @@ template bool WrappedVulkan::Serialise_vkDebugMarkerSetObjectNameEXT( SerialiserType &ser, VkDevice device, const VkDebugMarkerObjectNameInfoEXT *pNameInfo) { - SERIALISE_ELEMENT_LOCAL(Object, - GetObjRecord(pNameInfo->objectType, pNameInfo->object)->GetResourceID()); + SERIALISE_ELEMENT_LOCAL( + Object, GetObjData(pNameInfo->objectType, pNameInfo->object).record->GetResourceID()); SERIALISE_ELEMENT_LOCAL(ObjectName, pNameInfo->pObjectName); SERIALISE_CHECK_READ_ERRORS(); @@ -1286,58 +1413,166 @@ VkResult WrappedVulkan::vkDebugMarkerSetObjectNameEXT(VkDevice device, { if(IsCaptureMode(m_State) && pNameInfo) { - Chunk *chunk = NULL; - - VkResourceRecord *record = GetObjRecord(pNameInfo->objectType, pNameInfo->object); - - if(!record) - { - RDCERR("Unrecognised object %d %llu", pNameInfo->objectType, pNameInfo->object); - return VK_SUCCESS; - } + ObjData data = GetObjData(pNameInfo->objectType, pNameInfo->object); VkDebugMarkerObjectNameInfoEXT unwrapped = *pNameInfo; - - // special case for VkSurfaceKHR - the record pointer is actually just the underlying native - // window handle, so instead we unwrap and call through. - if(unwrapped.objectType == VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT) - { - unwrapped.object = GetWrapped((VkSurfaceKHR)unwrapped.object)->real.handle; - - if(ObjDisp(device)->DebugMarkerSetObjectNameEXT) - return ObjDisp(device)->DebugMarkerSetObjectNameEXT(device, &unwrapped); - - return VK_SUCCESS; - } - - if(unwrapped.objectType == VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT || - unwrapped.objectType == VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT || - unwrapped.objectType == VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT || - unwrapped.objectType == VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT || - unwrapped.objectType == VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT) - { - WrappedVkDispRes *res = (WrappedVkDispRes *)record->Resource; - unwrapped.object = res->real.handle; - } - else - { - WrappedVkNonDispRes *res = (WrappedVkNonDispRes *)record->Resource; - unwrapped.object = res->real.handle; - } + unwrapped.object = data.unwrapped; if(ObjDisp(device)->DebugMarkerSetObjectNameEXT) ObjDisp(device)->DebugMarkerSetObjectNameEXT(device, &unwrapped); + if(data.record) { CACHE_THREAD_SERIALISER(); SCOPED_SERIALISE_CHUNK(VulkanChunk::vkDebugMarkerSetObjectNameEXT); Serialise_vkDebugMarkerSetObjectNameEXT(ser, device, pNameInfo); - chunk = scope.Get(); - } + Chunk *chunk = scope.Get(); - record->AddChunk(chunk); + data.record->AddChunk(chunk); + } + } + + return VK_SUCCESS; +} + +VkResult WrappedVulkan::vkCreateDebugUtilsMessengerEXT( + VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo, + const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerEXT *pMessenger) +{ + // we create an interception object here so that we can dynamically check the state of API + // messages being muted, since it's quite likely that the application will initialise Vulkan (and + // so create a debug report callback) before it messes with RenderDoc's API to unmute messages. + UserDebugUtilsCallbackData *user = new UserDebugUtilsCallbackData(); + user->createInfo = *pCreateInfo; + user->muteWarned = false; + + VkDebugUtilsMessengerCreateInfoEXT wrappedCreateInfo = *pCreateInfo; + wrappedCreateInfo.pfnUserCallback = &UserDebugUtilsCallback; + wrappedCreateInfo.pUserData = user; + + VkResult vkr = ObjDisp(instance)->CreateDebugUtilsMessengerEXT( + Unwrap(instance), &wrappedCreateInfo, pAllocator, &user->realObject); + + if(vkr != VK_SUCCESS) + { + *pMessenger = VK_NULL_HANDLE; + delete user; + return vkr; + } + + *pMessenger = (VkDebugUtilsMessengerEXT)(uint64_t)user; + + return vkr; +} + +void WrappedVulkan::vkDestroyDebugUtilsMessengerEXT(VkInstance instance, + VkDebugUtilsMessengerEXT messenger, + const VkAllocationCallbacks *pAllocator) +{ + UserDebugReportCallbackData *user = + (UserDebugReportCallbackData *)(uintptr_t)NON_DISP_TO_UINT64(messenger); + + ObjDisp(instance)->DestroyDebugReportCallbackEXT(Unwrap(instance), user->realObject, pAllocator); + + delete user; +} + +void WrappedVulkan::vkSubmitDebugUtilsMessageEXT( + VkInstance instance, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageTypes, + const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData) +{ + return ObjDisp(instance)->SubmitDebugUtilsMessageEXT(Unwrap(instance), messageSeverity, + messageTypes, pCallbackData); +} + +template +bool WrappedVulkan::Serialise_vkSetDebugUtilsObjectNameEXT( + SerialiserType &ser, VkDevice device, const VkDebugUtilsObjectNameInfoEXT *pNameInfo) +{ + SERIALISE_ELEMENT_LOCAL( + Object, GetObjData(pNameInfo->objectType, pNameInfo->objectHandle).record->GetResourceID()); + SERIALISE_ELEMENT_LOCAL(ObjectName, pNameInfo->pObjectName); + + SERIALISE_CHECK_READ_ERRORS(); + + if(IsReplayingAndReading()) + { + // if we don't have a live resource, this is probably a command buffer being named on the + // virtual non-existant parent, not any of the baked IDs. Just save the name on the original ID + // and we'll propagate it in Serialise_vkBeginCommandBuffer + if(!GetResourceManager()->HasLiveResource(Object) || GetResourceManager()->HasReplacement(Object)) + m_CreationInfo.m_Names[Object] = ObjectName; + else + m_CreationInfo.m_Names[GetResourceManager()->GetLiveID(Object)] = ObjectName; + + ResourceDescription &descr = GetReplay()->GetResourceDesc(Object); + + AddResourceCurChunk(descr); + descr.SetCustomName(ObjectName); + } + + return true; +} + +VkResult WrappedVulkan::vkSetDebugUtilsObjectNameEXT(VkDevice device, + const VkDebugUtilsObjectNameInfoEXT *pNameInfo) +{ + if(IsCaptureMode(m_State) && pNameInfo) + { + ObjData data = GetObjData(pNameInfo->objectType, pNameInfo->objectHandle); + + VkDebugUtilsObjectNameInfoEXT unwrapped = *pNameInfo; + unwrapped.objectHandle = data.unwrapped; + + if(ObjDisp(device)->SetDebugUtilsObjectNameEXT) + ObjDisp(device)->SetDebugUtilsObjectNameEXT(device, &unwrapped); + + if(data.record) + { + CACHE_THREAD_SERIALISER(); + + SCOPED_SERIALISE_CHUNK(VulkanChunk::vkSetDebugUtilsObjectNameEXT); + Serialise_vkSetDebugUtilsObjectNameEXT(ser, device, pNameInfo); + + Chunk *chunk = scope.Get(); + + data.record->AddChunk(chunk); + } + } + + return VK_SUCCESS; +} + +VkResult WrappedVulkan::vkSetDebugUtilsObjectTagEXT(VkDevice device, + const VkDebugUtilsObjectTagInfoEXT *pTagInfo) +{ + if(IsCaptureMode(m_State) && pTagInfo) + { + ObjData data = GetObjData(pTagInfo->objectType, pTagInfo->objectHandle); + + if(data.record && pTagInfo->tagName == RENDERDOC_ShaderDebugMagicValue_truncated && + pTagInfo->objectType == VK_OBJECT_TYPE_SHADER_MODULE) + { + CACHE_THREAD_SERIALISER(); + + char *tag = (char *)pTagInfo->pTag; + std::string DebugPath = std::string(tag, tag + pTagInfo->tagSize); + + SCOPED_SERIALISE_CHUNK(VulkanChunk::SetShaderDebugPath); + Serialise_SetShaderDebugPath(ser, (VkShaderModule)data.record->Resource, DebugPath); + data.record->AddChunk(scope.Get()); + } + else if(ObjDisp(device)->SetDebugUtilsObjectTagEXT) + { + VkDebugUtilsObjectTagInfoEXT unwrapped = *pTagInfo; + + unwrapped.objectHandle = data.unwrapped; + + return ObjDisp(device)->SetDebugUtilsObjectTagEXT(device, &unwrapped); + } } return VK_SUCCESS; @@ -1359,8 +1594,28 @@ INSTANTIATE_FUNCTION_SERIALISED(VkResult, vkCreateQueryPool, VkDevice device, const VkQueryPoolCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkQueryPool *pQueryPool); -INSTANTIATE_FUNCTION_SERIALISED(void, SetShaderDebugPath, VkDevice device, - const VkDebugMarkerObjectTagInfoEXT *pTagInfo); +INSTANTIATE_FUNCTION_SERIALISED(void, SetShaderDebugPath, VkShaderModule ShaderObject, + std::string DebugPath); INSTANTIATE_FUNCTION_SERIALISED(VkResult, vkDebugMarkerSetObjectNameEXT, VkDevice device, const VkDebugMarkerObjectNameInfoEXT *pNameInfo); + +INSTANTIATE_FUNCTION_SERIALISED(VkResult, vkSetDebugUtilsObjectNameEXT, VkDevice device, + const VkDebugUtilsObjectNameInfoEXT *pNameInfo); + +INSTANTIATE_FUNCTION_SERIALISED(VkResult, vkSetDebugUtilsObjectTagEXT, VkDevice device, + const VkDebugUtilsObjectTagInfoEXT *pTagInfo); + +INSTANTIATE_FUNCTION_SERIALISED(VkResult, vkCreateDebugUtilsMessengerEXT, VkInstance instance, + const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo, + const VkAllocationCallbacks *pAllocator, + VkDebugUtilsMessengerEXT *pMessenger); + +INSTANTIATE_FUNCTION_SERIALISED(void, vkDestroyDebugUtilsMessengerEXT, VkInstance instance, + VkDebugUtilsMessengerEXT messenger, + const VkAllocationCallbacks *pAllocator); + +INSTANTIATE_FUNCTION_SERIALISED(void, vkSubmitDebugUtilsMessageEXT, VkInstance instance, + VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageTypes, + const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData); \ No newline at end of file diff --git a/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp index 9841bfc1b..6916a9b8b 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp @@ -1105,6 +1105,161 @@ VkResult WrappedVulkan::vkQueueWaitIdle(VkQueue queue) return ret; } +template +bool WrappedVulkan::Serialise_vkQueueBeginDebugUtilsLabelEXT(SerialiserType &ser, VkQueue queue, + const VkDebugUtilsLabelEXT *pLabelInfo) +{ + SERIALISE_ELEMENT(queue); + SERIALISE_ELEMENT_LOCAL(Label, *pLabelInfo); + + SERIALISE_CHECK_READ_ERRORS(); + + if(IsReplayingAndReading()) + { + if(ObjDisp(queue)->QueueBeginDebugUtilsLabelEXT) + ObjDisp(queue)->QueueBeginDebugUtilsLabelEXT(Unwrap(queue), &Label); + + if(IsLoading(m_State)) + { + DrawcallDescription draw; + draw.name = Label.pLabelName; + draw.flags |= DrawFlags::PushMarker; + + draw.markerColor[0] = RDCCLAMP(Label.color[0], 0.0f, 1.0f); + draw.markerColor[1] = RDCCLAMP(Label.color[1], 0.0f, 1.0f); + draw.markerColor[2] = RDCCLAMP(Label.color[2], 0.0f, 1.0f); + draw.markerColor[3] = RDCCLAMP(Label.color[3], 0.0f, 1.0f); + + AddEvent(); + m_RootEventID++; + AddDrawcall(draw, false); + + // now push the drawcall stack + GetDrawcallStack().push_back(&GetDrawcallStack().back()->children.back()); + } + else + { + m_RootEventID++; + } + } + + return true; +} + +void WrappedVulkan::vkQueueBeginDebugUtilsLabelEXT(VkQueue queue, + const VkDebugUtilsLabelEXT *pLabelInfo) +{ + if(ObjDisp(queue)->QueueBeginDebugUtilsLabelEXT) + { + SERIALISE_TIME_CALL(ObjDisp(queue)->QueueBeginDebugUtilsLabelEXT(Unwrap(queue), pLabelInfo)); + } + + if(IsActiveCapturing(m_State)) + { + CACHE_THREAD_SERIALISER(); + ser.SetDrawChunk(); + SCOPED_SERIALISE_CHUNK(VulkanChunk::vkQueueBeginDebugUtilsLabelEXT); + Serialise_vkQueueBeginDebugUtilsLabelEXT(ser, queue, pLabelInfo); + + m_FrameCaptureRecord->AddChunk(scope.Get()); + GetResourceManager()->MarkResourceFrameReferenced(GetResID(queue), eFrameRef_Read); + } +} + +template +bool WrappedVulkan::Serialise_vkQueueEndDebugUtilsLabelEXT(SerialiserType &ser, VkQueue queue) +{ + SERIALISE_ELEMENT(queue); + + SERIALISE_CHECK_READ_ERRORS(); + + if(IsReplayingAndReading()) + { + if(ObjDisp(queue)->QueueEndDebugUtilsLabelEXT) + ObjDisp(queue)->QueueEndDebugUtilsLabelEXT(Unwrap(queue)); + + if(IsLoading(m_State)) + { + if(GetDrawcallStack().size() > 1) + GetDrawcallStack().pop_back(); + } + } + + return true; +} + +void WrappedVulkan::vkQueueEndDebugUtilsLabelEXT(VkQueue queue) +{ + if(ObjDisp(queue)->QueueEndDebugUtilsLabelEXT) + { + SERIALISE_TIME_CALL(ObjDisp(queue)->QueueEndDebugUtilsLabelEXT(Unwrap(queue))); + } + + if(IsActiveCapturing(m_State)) + { + CACHE_THREAD_SERIALISER(); + ser.SetDrawChunk(); + SCOPED_SERIALISE_CHUNK(VulkanChunk::vkQueueEndDebugUtilsLabelEXT); + Serialise_vkQueueEndDebugUtilsLabelEXT(ser, queue); + + m_FrameCaptureRecord->AddChunk(scope.Get()); + GetResourceManager()->MarkResourceFrameReferenced(GetResID(queue), eFrameRef_Read); + } +} + +template +bool WrappedVulkan::Serialise_vkQueueInsertDebugUtilsLabelEXT(SerialiserType &ser, VkQueue queue, + const VkDebugUtilsLabelEXT *pLabelInfo) +{ + SERIALISE_ELEMENT(queue); + SERIALISE_ELEMENT_LOCAL(Label, *pLabelInfo); + + SERIALISE_CHECK_READ_ERRORS(); + + if(IsReplayingAndReading()) + { + if(ObjDisp(queue)->QueueInsertDebugUtilsLabelEXT) + ObjDisp(queue)->QueueInsertDebugUtilsLabelEXT(Unwrap(queue), &Label); + + if(IsLoading(m_State)) + { + DrawcallDescription draw; + draw.name = Label.pLabelName; + draw.flags |= DrawFlags::SetMarker; + + draw.markerColor[0] = RDCCLAMP(Label.color[0], 0.0f, 1.0f); + draw.markerColor[1] = RDCCLAMP(Label.color[1], 0.0f, 1.0f); + draw.markerColor[2] = RDCCLAMP(Label.color[2], 0.0f, 1.0f); + draw.markerColor[3] = RDCCLAMP(Label.color[3], 0.0f, 1.0f); + + AddEvent(); + AddDrawcall(draw, false); + } + } + + return true; +} + +void WrappedVulkan::vkQueueInsertDebugUtilsLabelEXT(VkQueue queue, + const VkDebugUtilsLabelEXT *pLabelInfo) +{ + if(ObjDisp(queue)->QueueInsertDebugUtilsLabelEXT) + { + SERIALISE_TIME_CALL(ObjDisp(queue)->QueueInsertDebugUtilsLabelEXT(Unwrap(queue), pLabelInfo)); + } + + if(IsActiveCapturing(m_State)) + { + CACHE_THREAD_SERIALISER(); + ser.SetDrawChunk(); + SCOPED_SERIALISE_CHUNK(VulkanChunk::vkQueueInsertDebugUtilsLabelEXT); + Serialise_vkQueueInsertDebugUtilsLabelEXT(ser, queue, pLabelInfo); + + m_FrameCaptureRecord->AddChunk(scope.Get()); + GetResourceManager()->MarkResourceFrameReferenced(GetResID(queue), eFrameRef_Read); + } +} + INSTANTIATE_FUNCTION_SERIALISED(void, vkGetDeviceQueue, VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue *pQueue); @@ -1115,3 +1270,11 @@ INSTANTIATE_FUNCTION_SERIALISED(VkResult, vkQueueBindSparse, VkQueue queue, uint const VkBindSparseInfo *pBindInfo, VkFence fence); INSTANTIATE_FUNCTION_SERIALISED(VkResult, vkQueueWaitIdle, VkQueue queue); + +INSTANTIATE_FUNCTION_SERIALISED(void, vkQueueBeginDebugUtilsLabelEXT, VkQueue queue, + const VkDebugUtilsLabelEXT *pLabelInfo); + +INSTANTIATE_FUNCTION_SERIALISED(void, vkQueueEndDebugUtilsLabelEXT, VkQueue queue); + +INSTANTIATE_FUNCTION_SERIALISED(void, vkQueueInsertDebugUtilsLabelEXT, VkQueue queue, + const VkDebugUtilsLabelEXT *pLabelInfo);