GPU/Vulkan: Add debug utility functions

Adds a way to set the name of vulkan
objects, and automatically determining their `VkObjectType` enum value
at compile-time. As well as a utility-object for creating debug-scopes
for `VkQueue` and `VkCommandBuffer` objects. `DebugScope` objects will
automatically emit `Begin` and `End` commands within the ctor and dtor
and allow for C++ scopes to name and color sections of a vulkan command.
These DebugScopes are also able to be nested within each other and will
automatically pick a color depending on the current recursive depth.

These functions are all null-stubbed in non-debug compilations.
This commit is contained in:
Wunkolo
2021-07-23 16:46:01 -07:00
parent 494b6e029f
commit 98089180c0
7 changed files with 579 additions and 44 deletions

View File

@ -209,7 +209,7 @@ bool Context::SelectInstanceExtensions(ExtensionList* extension_list, const Wind
if (wi && wi->type == WindowInfo::Type::Display && !SupportsExtension(VK_KHR_DISPLAY_EXTENSION_NAME, true))
return false;
// VK_EXT_debug_utils
// VK_EXT_debug_utils
if (enable_debug_utils && !SupportsExtension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, false))
Log_WarningPrintf("Vulkan: Debug report requested, but extension is not available.");
@ -632,6 +632,7 @@ bool Context::CreateCommandBuffers()
{
VkResult res;
uint32_t frame_index = 0;
for (FrameResources& resources : m_frame_resources)
{
resources.needs_fence_wait = false;
@ -644,6 +645,8 @@ bool Context::CreateCommandBuffers()
LOG_VULKAN_ERROR(res, "vkCreateCommandPool failed: ");
return false;
}
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), resources.command_pool, "Frame Command Pool %u",
frame_index);
VkCommandBufferAllocateInfo buffer_info = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr,
resources.command_pool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1};
@ -654,6 +657,8 @@ bool Context::CreateCommandBuffers()
LOG_VULKAN_ERROR(res, "vkAllocateCommandBuffers failed: ");
return false;
}
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), resources.command_buffer, "Frame Command Buffer %u",
frame_index);
VkFenceCreateInfo fence_info = {VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, nullptr, VK_FENCE_CREATE_SIGNALED_BIT};
@ -663,7 +668,7 @@ bool Context::CreateCommandBuffers()
LOG_VULKAN_ERROR(res, "vkCreateFence failed: ");
return false;
}
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), resources.fence, "Frame Fence %u", frame_index);
// TODO: A better way to choose the number of descriptors.
VkDescriptorPoolSize pool_sizes[] = {{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1024},
{VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1024},
@ -683,6 +688,10 @@ bool Context::CreateCommandBuffers()
LOG_VULKAN_ERROR(res, "vkCreateDescriptorPool failed: ");
return false;
}
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), resources.descriptor_pool, "Frame Descriptor Pool %u",
frame_index);
++frame_index;
}
ActivateCommandBuffer(0);
@ -741,7 +750,7 @@ bool Context::CreateGlobalDescriptorPool()
LOG_VULKAN_ERROR(res, "vkCreateDescriptorPool failed: ");
return false;
}
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_global_descriptor_pool, "Global Descriptor Pool");
return true;
}
@ -909,6 +918,7 @@ void Context::DoSubmitCommandBuffer(u32 index, VkSemaphore wait_semaphore, VkSem
submit_info.signalSemaphoreCount = 1;
submit_info.pSignalSemaphores = &signal_semaphore;
}
const Vulkan::Util::DebugScope debugScope(m_graphics_queue, "Context::DoSubmitCommandBuffer: %u", index);
VkResult res = vkQueueSubmit(m_graphics_queue, 1, &submit_info, resources.fence);
if (res != VK_SUCCESS)
@ -930,7 +940,7 @@ void Context::DoPresent(VkSemaphore wait_semaphore, VkSwapchainKHR present_swap_
&present_swap_chain,
&present_image_index,
nullptr};
const Vulkan::Util::DebugScope debugScope(m_present_queue, "Context::DoPresent: %u", present_image_index);
VkResult res = vkQueuePresentKHR(m_present_queue, &present_info);
if (res != VK_SUCCESS)
{
@ -1103,11 +1113,10 @@ void Context::DeferPipelineDestruction(VkPipeline pipeline)
resources.cleanup_resources.push_back([this, pipeline]() { vkDestroyPipeline(m_device, pipeline, nullptr); });
}
VKAPI_ATTR VkBool32 VKAPI_CALL DebugMessengerCallback(VkDebugUtilsMessageSeverityFlagBitsEXT severity,
VkDebugUtilsMessageTypeFlagsEXT messageType,
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
void* pUserData)
VkDebugUtilsMessageTypeFlagsEXT messageType,
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
void* pUserData)
{
LOGLEVEL level;
if (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)
@ -1137,10 +1146,15 @@ bool Context::EnableDebugUtils()
}
VkDebugUtilsMessengerCreateInfoEXT messenger_info = {
VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, nullptr, 0,
VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT,
VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
DebugMessengerCallback, nullptr};
VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
nullptr,
0,
VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT,
VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
DebugMessengerCallback,
nullptr};
VkResult res = vkCreateDebugUtilsMessengerEXT(m_instance, &messenger_info, nullptr, &m_debug_messenger_callback);
if (res != VK_SUCCESS)