mirror of
https://github.com/WinampDesktop/winamp.git
synced 2025-06-21 18:05:39 -04:00
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:
@ -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)
|
||||
|
@ -100,6 +100,10 @@ void StagingTexture::CopyFromTexture(VkCommandBuffer command_buffer, Texture& sr
|
||||
Assert((src_x + width) <= src_texture.GetWidth() && (src_y + height) <= src_texture.GetHeight());
|
||||
Assert((dst_x + width) <= m_width && (dst_y + height) <= m_height);
|
||||
|
||||
const Vulkan::Util::DebugScope debugScope(command_buffer,
|
||||
"StagingTexture::CopyFromTexture: {%u,%u} Lyr:%u Lvl:%u {%u,%u} %ux%u",
|
||||
src_x, src_y, src_layer, src_level, dst_x, dst_y, width, height);
|
||||
|
||||
VkImageLayout old_layout = src_texture.GetLayout();
|
||||
src_texture.TransitionToLayout(command_buffer, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||
|
||||
@ -123,6 +127,9 @@ void StagingTexture::CopyFromTexture(VkCommandBuffer command_buffer, Texture& sr
|
||||
void StagingTexture::CopyFromTexture(Texture& src_texture, u32 src_x, u32 src_y, u32 src_layer, u32 src_level,
|
||||
u32 dst_x, u32 dst_y, u32 width, u32 height)
|
||||
{
|
||||
const Vulkan::Util::DebugScope debugScope(g_vulkan_context->GetCurrentCommandBuffer(),
|
||||
"StagingTexture::CopyFromTexture: {%u,%u} Lyr:%u Lvl:%u {%u,%u} %ux%u",
|
||||
src_x, src_y, src_layer, src_level, dst_x, dst_y, width, height);
|
||||
CopyFromTexture(g_vulkan_context->GetCurrentCommandBuffer(), src_texture, src_x, src_y, src_layer, src_level, dst_x,
|
||||
dst_y, width, height);
|
||||
|
||||
@ -162,6 +169,9 @@ void StagingTexture::CopyToTexture(VkCommandBuffer command_buffer, u32 src_x, u3
|
||||
void StagingTexture::CopyToTexture(u32 src_x, u32 src_y, Texture& dst_texture, u32 dst_x, u32 dst_y, u32 dst_layer,
|
||||
u32 dst_level, u32 width, u32 height)
|
||||
{
|
||||
const Vulkan::Util::DebugScope debugScope(g_vulkan_context->GetCurrentCommandBuffer(),
|
||||
"StagingTexture::CopyToTexture: {%u,%u} | {%u,%u} Lyr:%u Lvl:%u %ux%u",
|
||||
src_x, src_y, dst_x, dst_y, dst_layer, dst_level, width, height);
|
||||
CopyToTexture(g_vulkan_context->GetCurrentCommandBuffer(), src_x, src_y, dst_texture, dst_x, dst_y, dst_layer,
|
||||
dst_level, width, height);
|
||||
|
||||
|
@ -239,6 +239,8 @@ void Texture::TransitionToLayout(VkCommandBuffer command_buffer, VkImageLayout n
|
||||
{
|
||||
if (m_layout == new_layout)
|
||||
return;
|
||||
const Vulkan::Util::DebugScope debugScope(command_buffer, "Texture::TransitionToLayout: %s",
|
||||
Vulkan::Util::VkImageLayoutToString(new_layout));
|
||||
|
||||
TransitionSubresourcesToLayout(command_buffer, 0, m_levels, 0, m_layers, m_layout, new_layout);
|
||||
|
||||
@ -249,6 +251,11 @@ void Texture::TransitionSubresourcesToLayout(VkCommandBuffer command_buffer, u32
|
||||
u32 start_layer, u32 num_layers, VkImageLayout old_layout,
|
||||
VkImageLayout new_layout)
|
||||
{
|
||||
const Vulkan::Util::DebugScope debugScope(
|
||||
command_buffer, "Texture::TransitionSubresourcesToLayout: Lvl:[%u,%u) Lyr:[%u,%u) %s -> %s", start_level,
|
||||
start_level + num_levels, start_layer, start_layer + num_layers, Vulkan::Util::VkImageLayoutToString(old_layout),
|
||||
Vulkan::Util::VkImageLayoutToString(new_layout));
|
||||
|
||||
VkImageMemoryBarrier barrier = {
|
||||
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
|
||||
nullptr, // const void* pNext
|
||||
@ -359,7 +366,6 @@ void Texture::TransitionSubresourcesToLayout(VkCommandBuffer command_buffer, u32
|
||||
dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
||||
break;
|
||||
}
|
||||
|
||||
vkCmdPipelineBarrier(command_buffer, srcStageMask, dstStageMask, 0, 0, nullptr, 0, nullptr, 1, &barrier);
|
||||
}
|
||||
|
||||
@ -382,6 +388,8 @@ void Texture::UpdateFromBuffer(VkCommandBuffer cmdbuf, u32 level, u32 layer, u32
|
||||
VkBuffer buffer, u32 buffer_offset)
|
||||
{
|
||||
const VkImageLayout old_layout = m_layout;
|
||||
const Vulkan::Util::DebugScope debugScope(cmdbuf, "Texture::UpdateFromBuffer: Lvl:%u Lyr:%u {%u,%u} %ux%u", level,
|
||||
layer, x, y, width, height);
|
||||
TransitionToLayout(cmdbuf, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
|
||||
const VkBufferImageCopy bic = {static_cast<VkDeviceSize>(buffer_offset),
|
||||
|
@ -10,6 +10,8 @@
|
||||
#include "context.h"
|
||||
#include "shader_compiler.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace Vulkan {
|
||||
namespace Util {
|
||||
bool IsDepthFormat(VkFormat format)
|
||||
@ -417,6 +419,71 @@ const char* VkResultToString(VkResult res)
|
||||
return "UNKNOWN_VK_RESULT";
|
||||
}
|
||||
}
|
||||
const char* VkImageLayoutToString(VkImageLayout layout)
|
||||
{
|
||||
switch (layout)
|
||||
{
|
||||
case VK_IMAGE_LAYOUT_UNDEFINED:
|
||||
return "VK_IMAGE_LAYOUT_UNDEFINED";
|
||||
|
||||
case VK_IMAGE_LAYOUT_GENERAL:
|
||||
return "VK_IMAGE_LAYOUT_GENERAL";
|
||||
|
||||
case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
|
||||
return "VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL";
|
||||
|
||||
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
|
||||
return "VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL";
|
||||
|
||||
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
|
||||
return "VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL";
|
||||
|
||||
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
|
||||
return "VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL";
|
||||
|
||||
case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
|
||||
return "VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL";
|
||||
|
||||
case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
|
||||
return "VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL";
|
||||
|
||||
case VK_IMAGE_LAYOUT_PREINITIALIZED:
|
||||
return "VK_IMAGE_LAYOUT_PREINITIALIZED";
|
||||
|
||||
case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL:
|
||||
return "VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL";
|
||||
|
||||
case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL:
|
||||
return "VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL";
|
||||
|
||||
case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL:
|
||||
return "VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL";
|
||||
|
||||
case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL:
|
||||
return "VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL";
|
||||
|
||||
case VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL:
|
||||
return "VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL";
|
||||
|
||||
case VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL:
|
||||
return "VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL";
|
||||
|
||||
case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
|
||||
return "VK_IMAGE_LAYOUT_PRESENT_SRC_KHR";
|
||||
|
||||
case VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR:
|
||||
return "VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR";
|
||||
|
||||
case VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV:
|
||||
return "VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV";
|
||||
|
||||
case VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT:
|
||||
return "VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT";
|
||||
|
||||
default:
|
||||
return "UNKNOWN_VK_RESULT";
|
||||
}
|
||||
}
|
||||
|
||||
void LogVulkanResult(int level, const char* func_name, VkResult res, const char* msg, ...)
|
||||
{
|
||||
@ -429,6 +496,78 @@ void LogVulkanResult(int level, const char* func_name, VkResult res, const char*
|
||||
static_cast<int>(res), VkResultToString(res));
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
||||
u8 DebugScope<VkCommandBuffer>::depth = 0;
|
||||
u8 DebugScope<VkQueue>::depth = 0;
|
||||
|
||||
static std::array<float, 4> Palette(float phase, const std::array<float, 3>& a, const std::array<float, 3>& b,
|
||||
const std::array<float, 3>& c, const std::array<float, 3>& d)
|
||||
{
|
||||
std::array<float, 4> result;
|
||||
result[0] = a[0] + b[0] * std::cos(6.28318f * (c[0] * phase + d[0]));
|
||||
result[1] = a[1] + b[1] * std::cos(6.28318f * (c[1] * phase + d[1]));
|
||||
result[2] = a[2] + b[2] * std::cos(6.28318f * (c[2] * phase + d[2]));
|
||||
result[3] = 1.0f;
|
||||
return result;
|
||||
}
|
||||
|
||||
DebugScope<VkCommandBuffer>::DebugScope(VkCommandBuffer context, const char* format, ...) : command_buffer(context)
|
||||
{
|
||||
if (command_buffer)
|
||||
{
|
||||
std::va_list ap;
|
||||
|
||||
SmallString str;
|
||||
va_start(ap, format);
|
||||
str.FormatVA(format, ap);
|
||||
va_end(ap);
|
||||
|
||||
++depth;
|
||||
const float depth_phase = depth / static_cast<float>(max_depth);
|
||||
BeginDebugScope(command_buffer, str,
|
||||
Palette(depth_phase, {0.5, 0.5, 0.5}, {0.5, 0.5, 0.5}, {1.0, 1.0, 0.5}, {0.8, 0.90, 0.30}));
|
||||
}
|
||||
}
|
||||
|
||||
DebugScope<VkCommandBuffer>::~DebugScope()
|
||||
{
|
||||
if (command_buffer)
|
||||
{
|
||||
--depth;
|
||||
EndDebugScope(command_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
DebugScope<VkQueue>::DebugScope(VkQueue context, const char* format, ...) : queue(context)
|
||||
{
|
||||
if (queue)
|
||||
{
|
||||
std::va_list ap;
|
||||
va_start(ap, format);
|
||||
|
||||
SmallString str;
|
||||
str.FormatVA(format, ap);
|
||||
va_end(ap);
|
||||
|
||||
const float depth_phase = depth / static_cast<float>(max_depth);
|
||||
BeginDebugScope(queue, str,
|
||||
Palette(depth_phase, {0.5, 0.5, 0.5}, {0.5, 0.5, 0.5}, {2.0, 1.0, 0.0}, {0.5, 0.20, 0.25}));
|
||||
++depth;
|
||||
}
|
||||
}
|
||||
|
||||
DebugScope<VkQueue>::~DebugScope()
|
||||
{
|
||||
if (queue)
|
||||
{
|
||||
--depth;
|
||||
EndDebugScope(queue);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace Util
|
||||
|
||||
} // namespace Vulkan
|
||||
|
@ -5,11 +5,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../string.h"
|
||||
#include "../types.h"
|
||||
#include "vulkan_loader.h"
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstdarg>
|
||||
#include <string_view>
|
||||
|
||||
namespace Vulkan {
|
||||
namespace Util {
|
||||
|
||||
@ -74,10 +76,202 @@ VkShaderModule CompileAndCreateFragmentShader(std::string_view source_code);
|
||||
VkShaderModule CompileAndCreateComputeShader(std::string_view source_code);
|
||||
|
||||
const char* VkResultToString(VkResult res);
|
||||
const char* VkImageLayoutToString(VkImageLayout layout);
|
||||
void LogVulkanResult(int level, const char* func_name, VkResult res, const char* msg, ...) printflike(4, 5);
|
||||
|
||||
#define LOG_VULKAN_ERROR(res, ...) ::Vulkan::Util::LogVulkanResult(1, __func__, res, __VA_ARGS__)
|
||||
|
||||
// Provides a compile-time mapping between a Vulkan-type into its matching VkObjectType
|
||||
template<typename T>
|
||||
struct VkObjectTypeMap;
|
||||
|
||||
// clang-format off
|
||||
template<> struct VkObjectTypeMap<VkInstance > { using type = VkInstance ; static constexpr VkObjectType value = VK_OBJECT_TYPE_INSTANCE; };
|
||||
template<> struct VkObjectTypeMap<VkPhysicalDevice > { using type = VkPhysicalDevice ; static constexpr VkObjectType value = VK_OBJECT_TYPE_PHYSICAL_DEVICE; };
|
||||
template<> struct VkObjectTypeMap<VkDevice > { using type = VkDevice ; static constexpr VkObjectType value = VK_OBJECT_TYPE_DEVICE; };
|
||||
template<> struct VkObjectTypeMap<VkQueue > { using type = VkQueue ; static constexpr VkObjectType value = VK_OBJECT_TYPE_QUEUE; };
|
||||
template<> struct VkObjectTypeMap<VkSemaphore > { using type = VkSemaphore ; static constexpr VkObjectType value = VK_OBJECT_TYPE_SEMAPHORE; };
|
||||
template<> struct VkObjectTypeMap<VkCommandBuffer > { using type = VkCommandBuffer ; static constexpr VkObjectType value = VK_OBJECT_TYPE_COMMAND_BUFFER; };
|
||||
template<> struct VkObjectTypeMap<VkFence > { using type = VkFence ; static constexpr VkObjectType value = VK_OBJECT_TYPE_FENCE; };
|
||||
template<> struct VkObjectTypeMap<VkDeviceMemory > { using type = VkDeviceMemory ; static constexpr VkObjectType value = VK_OBJECT_TYPE_DEVICE_MEMORY; };
|
||||
template<> struct VkObjectTypeMap<VkBuffer > { using type = VkBuffer ; static constexpr VkObjectType value = VK_OBJECT_TYPE_BUFFER; };
|
||||
template<> struct VkObjectTypeMap<VkImage > { using type = VkImage ; static constexpr VkObjectType value = VK_OBJECT_TYPE_IMAGE; };
|
||||
template<> struct VkObjectTypeMap<VkEvent > { using type = VkEvent ; static constexpr VkObjectType value = VK_OBJECT_TYPE_EVENT; };
|
||||
template<> struct VkObjectTypeMap<VkQueryPool > { using type = VkQueryPool ; static constexpr VkObjectType value = VK_OBJECT_TYPE_QUERY_POOL; };
|
||||
template<> struct VkObjectTypeMap<VkBufferView > { using type = VkBufferView ; static constexpr VkObjectType value = VK_OBJECT_TYPE_BUFFER_VIEW; };
|
||||
template<> struct VkObjectTypeMap<VkImageView > { using type = VkImageView ; static constexpr VkObjectType value = VK_OBJECT_TYPE_IMAGE_VIEW; };
|
||||
template<> struct VkObjectTypeMap<VkShaderModule > { using type = VkShaderModule ; static constexpr VkObjectType value = VK_OBJECT_TYPE_SHADER_MODULE; };
|
||||
template<> struct VkObjectTypeMap<VkPipelineCache > { using type = VkPipelineCache ; static constexpr VkObjectType value = VK_OBJECT_TYPE_PIPELINE_CACHE; };
|
||||
template<> struct VkObjectTypeMap<VkPipelineLayout > { using type = VkPipelineLayout ; static constexpr VkObjectType value = VK_OBJECT_TYPE_PIPELINE_LAYOUT; };
|
||||
template<> struct VkObjectTypeMap<VkRenderPass > { using type = VkRenderPass ; static constexpr VkObjectType value = VK_OBJECT_TYPE_RENDER_PASS; };
|
||||
template<> struct VkObjectTypeMap<VkPipeline > { using type = VkPipeline ; static constexpr VkObjectType value = VK_OBJECT_TYPE_PIPELINE; };
|
||||
template<> struct VkObjectTypeMap<VkDescriptorSetLayout > { using type = VkDescriptorSetLayout ; static constexpr VkObjectType value = VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT; };
|
||||
template<> struct VkObjectTypeMap<VkSampler > { using type = VkSampler ; static constexpr VkObjectType value = VK_OBJECT_TYPE_SAMPLER; };
|
||||
template<> struct VkObjectTypeMap<VkDescriptorPool > { using type = VkDescriptorPool ; static constexpr VkObjectType value = VK_OBJECT_TYPE_DESCRIPTOR_POOL; };
|
||||
template<> struct VkObjectTypeMap<VkDescriptorSet > { using type = VkDescriptorSet ; static constexpr VkObjectType value = VK_OBJECT_TYPE_DESCRIPTOR_SET; };
|
||||
template<> struct VkObjectTypeMap<VkFramebuffer > { using type = VkFramebuffer ; static constexpr VkObjectType value = VK_OBJECT_TYPE_FRAMEBUFFER; };
|
||||
template<> struct VkObjectTypeMap<VkCommandPool > { using type = VkCommandPool ; static constexpr VkObjectType value = VK_OBJECT_TYPE_COMMAND_POOL; };
|
||||
template<> struct VkObjectTypeMap<VkDescriptorUpdateTemplate> { using type = VkDescriptorUpdateTemplate; static constexpr VkObjectType value = VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE; };
|
||||
template<> struct VkObjectTypeMap<VkSurfaceKHR > { using type = VkSurfaceKHR ; static constexpr VkObjectType value = VK_OBJECT_TYPE_SURFACE_KHR; };
|
||||
template<> struct VkObjectTypeMap<VkSwapchainKHR > { using type = VkSwapchainKHR ; static constexpr VkObjectType value = VK_OBJECT_TYPE_SWAPCHAIN_KHR; };
|
||||
template<> struct VkObjectTypeMap<VkDebugUtilsMessengerEXT > { using type = VkDebugUtilsMessengerEXT ; static constexpr VkObjectType value = VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT; };
|
||||
// clang-format on
|
||||
|
||||
inline void SetObjectName(VkDevice device, void* object_handle, VkObjectType object_type, const char* format, ...)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
if (!vkSetDebugUtilsObjectNameEXT)
|
||||
{
|
||||
return;
|
||||
}
|
||||
std::va_list ap;
|
||||
|
||||
SmallString str;
|
||||
va_start(ap, format);
|
||||
str.FormatVA(format, ap);
|
||||
va_end(ap);
|
||||
|
||||
const VkDebugUtilsObjectNameInfoEXT nameInfo{VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, nullptr, object_type,
|
||||
reinterpret_cast<uint64_t>(object_handle), str};
|
||||
vkSetDebugUtilsObjectNameEXT(device, &nameInfo);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void SetObjectName(VkDevice device, T object_handle, const char* format, ...)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
std::va_list ap;
|
||||
va_start(ap, format);
|
||||
SetObjectName(device, reinterpret_cast<void*>((typename VkObjectTypeMap<T>::type)object_handle),
|
||||
VkObjectTypeMap<T>::value, format, ap);
|
||||
va_end(ap);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Command buffer debug utils
|
||||
inline void BeginDebugScope(VkCommandBuffer command_buffer, const char* scope_name,
|
||||
const std::array<float, 4>& scope_color = {0.5, 0.5, 0.5, 1.0})
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
if (!vkCmdBeginDebugUtilsLabelEXT)
|
||||
{
|
||||
return;
|
||||
}
|
||||
const VkDebugUtilsLabelEXT label{VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT,
|
||||
nullptr,
|
||||
scope_name,
|
||||
{scope_color[0], scope_color[1], scope_color[2], scope_color[3]}};
|
||||
vkCmdBeginDebugUtilsLabelEXT(command_buffer, &label);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void EndDebugScope(VkCommandBuffer command_buffer)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
if (!vkCmdEndDebugUtilsLabelEXT)
|
||||
{
|
||||
return;
|
||||
}
|
||||
vkCmdEndDebugUtilsLabelEXT(command_buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void InsertDebugLabel(VkCommandBuffer command_buffer, const char* label_name,
|
||||
const std::array<float, 4>& label_color = {0.5, 0.5, 0.5, 1.0})
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
if (!vkCmdInsertDebugUtilsLabelEXT)
|
||||
{
|
||||
return;
|
||||
}
|
||||
const VkDebugUtilsLabelEXT label{VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT,
|
||||
nullptr,
|
||||
label_name,
|
||||
{label_color[0], label_color[1], label_color[2], label_color[3]}};
|
||||
vkCmdInsertDebugUtilsLabelEXT(command_buffer, &label);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Queue debug utils
|
||||
inline void BeginDebugScope(VkQueue queue, const char* scope_name,
|
||||
const std::array<float, 4>& scope_color = {0.75, 0.75, 0.75, 1.0})
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
if (!vkQueueBeginDebugUtilsLabelEXT)
|
||||
{
|
||||
return;
|
||||
}
|
||||
const VkDebugUtilsLabelEXT label{VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT,
|
||||
nullptr,
|
||||
scope_name,
|
||||
{scope_color[0], scope_color[1], scope_color[2], scope_color[3]}};
|
||||
vkQueueBeginDebugUtilsLabelEXT(queue, &label);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void EndDebugScope(VkQueue queue)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
if (!vkQueueEndDebugUtilsLabelEXT)
|
||||
{
|
||||
return;
|
||||
}
|
||||
vkQueueEndDebugUtilsLabelEXT(queue);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void InsertDebugLabel(VkQueue queue, const char* label_name,
|
||||
const std::array<float, 4>& label_color = {0.75, 0.75, 0.75, 1.0})
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
if (!vkQueueInsertDebugUtilsLabelEXT)
|
||||
{
|
||||
return;
|
||||
}
|
||||
const VkDebugUtilsLabelEXT label{VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT,
|
||||
nullptr,
|
||||
label_name,
|
||||
{label_color[0], label_color[1], label_color[2], label_color[3]}};
|
||||
vkQueueInsertDebugUtilsLabelEXT(queue, &label);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
class DebugScope
|
||||
{
|
||||
public:
|
||||
DebugScope(T context, const char* format, ...) {}
|
||||
};
|
||||
|
||||
#ifdef _DEBUG
|
||||
template<>
|
||||
class DebugScope<VkCommandBuffer>
|
||||
{
|
||||
public:
|
||||
DebugScope(VkCommandBuffer context, const char* format, ...);
|
||||
~DebugScope();
|
||||
|
||||
private:
|
||||
static constexpr u8 max_depth = 8u;
|
||||
static u8 depth;
|
||||
VkCommandBuffer command_buffer;
|
||||
};
|
||||
|
||||
template<>
|
||||
class DebugScope<VkQueue>
|
||||
{
|
||||
public:
|
||||
DebugScope(VkQueue context, const char* format, ...);
|
||||
~DebugScope();
|
||||
|
||||
private:
|
||||
static constexpr u8 max_depth = 8u;
|
||||
static u8 depth;
|
||||
VkQueue queue;
|
||||
};
|
||||
#endif
|
||||
|
||||
} // namespace Util
|
||||
|
||||
} // namespace Vulkan
|
||||
|
Reference in New Issue
Block a user