Files
test/source/blender/gpu/vulkan/vk_debug.cc
Jeroen Bakker 488e74a209 Vulkan: Render graph debug groups
This PR implements debug groups in the render graph. Each node contains
a reference to the debug group they belong to. During scheduling the
nodes can be reordered and the correct debug group needs to be
activated.

This is done by keeping track of the current debug group. When a
different debug group is needed, the needed ends/begins are added
to the command buffer.

This mechanism also cleans up debug groups that are not used at all
as they don't have any nodes associated to it.

Pull Request: https://projects.blender.org/blender/blender/pulls/122054
2024-05-21 17:34:55 +02:00

385 lines
13 KiB
C++

/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup gpu
*/
#include <sstream>
#include "BKE_global.hh"
#include "CLG_log.h"
#include "vk_backend.hh"
#include "vk_context.hh"
#include "vk_debug.hh"
#include "vk_to_string.hh"
static CLG_LogRef LOG = {"gpu.vulkan"};
namespace blender::gpu {
void VKContext::debug_group_begin(const char *name, int)
{
if (use_render_graph) {
render_graph.debug_group_begin(name);
}
else {
const VKDevice &device = VKBackend::get().device_get();
debug::push_marker(device, name);
}
}
void VKContext::debug_group_end()
{
if (use_render_graph) {
render_graph.debug_group_end();
}
else {
const VKDevice &device = VKBackend::get().device_get();
debug::pop_marker(device);
}
}
bool VKContext::debug_capture_begin(const char *title)
{
return VKBackend::get().debug_capture_begin(title);
}
bool VKBackend::debug_capture_begin(const char *title)
{
#ifdef WITH_RENDERDOC
bool result = renderdoc_api_.start_frame_capture(device_get().instance_get(), nullptr);
if (result && title) {
renderdoc_api_.set_frame_capture_title(title);
}
return result;
#else
UNUSED_VARS(title);
return false;
#endif
}
void VKContext::debug_capture_end()
{
VKBackend::get().debug_capture_end();
}
void VKBackend::debug_capture_end()
{
#ifdef WITH_RENDERDOC
renderdoc_api_.end_frame_capture(device_get().instance_get(), nullptr);
#endif
}
void *VKContext::debug_capture_scope_create(const char * /*name*/)
{
return nullptr;
}
bool VKContext::debug_capture_scope_begin(void * /*scope*/)
{
return false;
}
void VKContext::debug_capture_scope_end(void * /*scope*/) {}
} // namespace blender::gpu
namespace blender::gpu::debug {
void VKDebuggingTools::init(VkInstance vk_instance)
{
CLG_logref_init(&LOG);
PFN_vkGetInstanceProcAddr instance_proc_addr = vkGetInstanceProcAddr;
enabled = false;
vk_debug_utils_messenger = nullptr;
vkCmdBeginDebugUtilsLabelEXT_r = (PFN_vkCmdBeginDebugUtilsLabelEXT)instance_proc_addr(
vk_instance, "vkCmdBeginDebugUtilsLabelEXT");
vkCmdEndDebugUtilsLabelEXT_r = (PFN_vkCmdEndDebugUtilsLabelEXT)instance_proc_addr(
vk_instance, "vkCmdEndDebugUtilsLabelEXT");
vkCmdInsertDebugUtilsLabelEXT_r = (PFN_vkCmdInsertDebugUtilsLabelEXT)instance_proc_addr(
vk_instance, "vkCmdInsertDebugUtilsLabelEXT");
vkCreateDebugUtilsMessengerEXT_r = (PFN_vkCreateDebugUtilsMessengerEXT)instance_proc_addr(
vk_instance, "vkCreateDebugUtilsMessengerEXT");
vkDestroyDebugUtilsMessengerEXT_r = (PFN_vkDestroyDebugUtilsMessengerEXT)instance_proc_addr(
vk_instance, "vkDestroyDebugUtilsMessengerEXT");
vkQueueBeginDebugUtilsLabelEXT_r = (PFN_vkQueueBeginDebugUtilsLabelEXT)instance_proc_addr(
vk_instance, "vkQueueBeginDebugUtilsLabelEXT");
vkQueueEndDebugUtilsLabelEXT_r = (PFN_vkQueueEndDebugUtilsLabelEXT)instance_proc_addr(
vk_instance, "vkQueueEndDebugUtilsLabelEXT");
vkQueueInsertDebugUtilsLabelEXT_r = (PFN_vkQueueInsertDebugUtilsLabelEXT)instance_proc_addr(
vk_instance, "vkQueueInsertDebugUtilsLabelEXT");
vkSetDebugUtilsObjectNameEXT_r = (PFN_vkSetDebugUtilsObjectNameEXT)instance_proc_addr(
vk_instance, "vkSetDebugUtilsObjectNameEXT");
vkSetDebugUtilsObjectTagEXT_r = (PFN_vkSetDebugUtilsObjectTagEXT)instance_proc_addr(
vk_instance, "vkSetDebugUtilsObjectTagEXT");
vkSubmitDebugUtilsMessageEXT_r = (PFN_vkSubmitDebugUtilsMessageEXT)instance_proc_addr(
vk_instance, "vkSubmitDebugUtilsMessageEXT");
if (vkCmdBeginDebugUtilsLabelEXT_r) {
enabled = true;
init_messenger(vk_instance);
}
}
void VKDebuggingTools::deinit(VkInstance vk_instance)
{
if (enabled) {
destroy_messenger(vk_instance);
}
vkCmdBeginDebugUtilsLabelEXT_r = nullptr;
vkCmdEndDebugUtilsLabelEXT_r = nullptr;
vkCmdInsertDebugUtilsLabelEXT_r = nullptr;
vkCreateDebugUtilsMessengerEXT_r = nullptr;
vkDestroyDebugUtilsMessengerEXT_r = nullptr;
vkQueueBeginDebugUtilsLabelEXT_r = nullptr;
vkQueueEndDebugUtilsLabelEXT_r = nullptr;
vkQueueInsertDebugUtilsLabelEXT_r = nullptr;
vkSetDebugUtilsObjectNameEXT_r = nullptr;
vkSetDebugUtilsObjectTagEXT_r = nullptr;
vkSubmitDebugUtilsMessageEXT_r = nullptr;
enabled = false;
}
void object_label(VkObjectType vk_object_type, uint64_t object_handle, const char *name)
{
if (G.debug & G_DEBUG_GPU) {
const VKDevice &device = VKBackend::get().device_get();
const VKDebuggingTools &debugging_tools = device.debugging_tools_get();
if (debugging_tools.enabled) {
const VKDevice &device = VKBackend::get().device_get();
VkDebugUtilsObjectNameInfoEXT info = {};
info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
info.objectType = vk_object_type;
info.objectHandle = object_handle;
info.pObjectName = name;
debugging_tools.vkSetDebugUtilsObjectNameEXT_r(device.device_get(), &info);
}
}
}
void push_marker(VkCommandBuffer vk_command_buffer, const char *name)
{
if (G.debug & G_DEBUG_GPU) {
const VKDevice &device = VKBackend::get().device_get();
const VKDebuggingTools &debugging_tools = device.debugging_tools_get();
if (debugging_tools.enabled) {
VkDebugUtilsLabelEXT info = {};
info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
info.pLabelName = name;
debugging_tools.vkCmdBeginDebugUtilsLabelEXT_r(vk_command_buffer, &info);
}
}
}
void set_marker(VkCommandBuffer vk_command_buffer, const char *name)
{
if (G.debug & G_DEBUG_GPU) {
const VKDevice &device = VKBackend::get().device_get();
const VKDebuggingTools &debugging_tools = device.debugging_tools_get();
if (debugging_tools.enabled) {
VkDebugUtilsLabelEXT info = {};
info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
info.pLabelName = name;
debugging_tools.vkCmdInsertDebugUtilsLabelEXT_r(vk_command_buffer, &info);
}
}
}
void pop_marker(VkCommandBuffer vk_command_buffer)
{
if (G.debug & G_DEBUG_GPU) {
const VKDevice &device = VKBackend::get().device_get();
const VKDebuggingTools &debugging_tools = device.debugging_tools_get();
if (debugging_tools.enabled) {
debugging_tools.vkCmdEndDebugUtilsLabelEXT_r(vk_command_buffer);
}
}
}
void push_marker(const VKDevice &device, const char *name)
{
if (G.debug & G_DEBUG_GPU) {
const VKDebuggingTools &debugging_tools = device.debugging_tools_get();
if (debugging_tools.enabled) {
VkDebugUtilsLabelEXT info = {};
info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
info.pLabelName = name;
debugging_tools.vkQueueBeginDebugUtilsLabelEXT_r(device.queue_get(), &info);
}
}
}
void set_marker(const VKDevice &device, const char *name)
{
if (G.debug & G_DEBUG_GPU) {
const VKDebuggingTools &debugging_tools = device.debugging_tools_get();
if (debugging_tools.enabled) {
VkDebugUtilsLabelEXT info = {};
info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
info.pLabelName = name;
debugging_tools.vkQueueInsertDebugUtilsLabelEXT_r(device.queue_get(), &info);
}
}
}
void pop_marker(const VKDevice &device)
{
if (G.debug & G_DEBUG_GPU) {
const VKDebuggingTools &debugging_tools = device.debugging_tools_get();
if (debugging_tools.enabled) {
debugging_tools.vkQueueEndDebugUtilsLabelEXT_r(device.queue_get());
}
}
}
} // namespace blender::gpu::debug
namespace blender::gpu::debug {
VKDebuggingTools::~VKDebuggingTools()
{
BLI_assert(vk_debug_utils_messenger == nullptr);
};
void VKDebuggingTools::print_labels(const VkDebugUtilsMessengerCallbackDataEXT *callback_data)
{
std::stringstream ss;
for (uint32_t object = 0; object < callback_data->objectCount; ++object) {
ss << " - ObjectType[" << to_string(callback_data->pObjects[object].objectType) << "],";
ss << "Handle[0x" << std::hex << uintptr_t(callback_data->pObjects[object].objectHandle)
<< "]";
if (callback_data->pObjects[object].pObjectName) {
ss << ",Name[" << callback_data->pObjects[object].pObjectName << "]";
}
ss << std::endl;
}
for (uint32_t label = 0; label < callback_data->cmdBufLabelCount; ++label) {
if (callback_data->pCmdBufLabels[label].pLabelName) {
ss << " - CommandBuffer : " << callback_data->pCmdBufLabels[label].pLabelName << std::endl;
}
}
for (uint32_t label = 0; label < callback_data->queueLabelCount; ++label) {
if (callback_data->pQueueLabels[label].pLabelName) {
ss << " - Queue : " << callback_data->pQueueLabels[label].pLabelName << std::endl;
}
}
ss << std::endl;
printf("%s", ss.str().c_str());
}
static VKAPI_ATTR VkBool32 VKAPI_CALL
messenger_callback(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
VkDebugUtilsMessageTypeFlagsEXT /*message_type*/,
const VkDebugUtilsMessengerCallbackDataEXT *callback_data,
void *user_data)
{
/*
* Some message IDs are turned of globally to reduce console flooding.
*
* - 0xec321b6c: `VUID-VkBufferCreateInfo-size-06409` is disabled as all allocations are reported
* to be larger than the maximum allowed buffer size, although the buffer-size is 4GB. Detected
* on Mesa 23.0.4. This has been confirmed by the Vulkan Tools WG and fixed up-stream.
*/
if (ELEM(callback_data->messageIdNumber, 0xec321b6c)) {
return VK_FALSE;
}
CLG_Severity severity = CLG_SEVERITY_INFO;
if (message_severity & (VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT))
{
severity = CLG_SEVERITY_INFO;
}
if (message_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) {
severity = CLG_SEVERITY_WARN;
}
if (message_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) {
severity = CLG_SEVERITY_ERROR;
}
if ((LOG.type->flag & CLG_FLAG_USE) && (LOG.type->level <= severity)) {
const char *format = "{0x%x}% s\n %s ";
CLG_logf(LOG.type,
severity,
"",
"",
format,
callback_data->messageIdNumber,
callback_data->pMessageIdName,
callback_data->pMessage);
}
const bool do_labels = (callback_data->objectCount + callback_data->cmdBufLabelCount +
callback_data->queueLabelCount) > 0;
if (do_labels) {
VKDebuggingTools &debugging_tools = *reinterpret_cast<VKDebuggingTools *>(user_data);
debugging_tools.print_labels(callback_data);
}
return VK_FALSE;
};
VkResult VKDebuggingTools::init_messenger(VkInstance vk_instance)
{
BLI_assert(enabled);
VkDebugUtilsMessengerCreateInfoEXT create_info;
create_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
create_info.pNext = nullptr;
create_info.flags = 0;
create_info.messageSeverity = message_severity;
create_info.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
create_info.pfnUserCallback = messenger_callback;
create_info.pUserData = this;
VkResult res = vkCreateDebugUtilsMessengerEXT_r(
vk_instance, &create_info, nullptr, &vk_debug_utils_messenger);
BLI_assert(res == VK_SUCCESS);
return res;
}
void VKDebuggingTools::destroy_messenger(VkInstance vk_instance)
{
if (vk_debug_utils_messenger == nullptr) {
return;
}
BLI_assert(enabled);
vkDestroyDebugUtilsMessengerEXT_r(vk_instance, vk_debug_utils_messenger, nullptr);
vk_debug_utils_messenger = nullptr;
return;
}
void raise_message(int32_t id_number,
VkDebugUtilsMessageSeverityFlagBitsEXT vk_severity_flag_bits,
const char *format,
...)
{
const VKDevice &device = VKBackend::get().device_get();
const VKDebuggingTools &debugging_tools = device.debugging_tools_get();
if (debugging_tools.enabled) {
va_list arg;
va_start(arg, format);
char *info = BLI_vsprintfN(format, arg);
va_end(arg);
static VkDebugUtilsMessengerCallbackDataEXT vk_call_back_data;
vk_call_back_data.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT;
vk_call_back_data.pNext = VK_NULL_HANDLE;
vk_call_back_data.messageIdNumber = id_number;
vk_call_back_data.pMessageIdName = "VulkanMessenger";
vk_call_back_data.objectCount = 0;
vk_call_back_data.flags = 0;
vk_call_back_data.pObjects = VK_NULL_HANDLE;
vk_call_back_data.pMessage = info;
debugging_tools.vkSubmitDebugUtilsMessageEXT_r(device.instance_get(),
vk_severity_flag_bits,
VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT,
&vk_call_back_data);
MEM_freeN((void *)info);
}
}
}; // namespace blender::gpu::debug