143 lines
		
	
	
	
		
			4.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			143 lines
		
	
	
	
		
			4.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#pragma once
 | 
						|
 | 
						|
#include <memory/pointer_types/null_on_move.hpp>
 | 
						|
#include <renderer/vk/context/instance.hpp>
 | 
						|
#include <renderer/vk/vulkan.hpp>
 | 
						|
 | 
						|
namespace lt::renderer::vk {
 | 
						|
 | 
						|
class Messenger
 | 
						|
{
 | 
						|
public:
 | 
						|
	// NOLINTNEXTLINE(performance-enum-size)
 | 
						|
	enum Severity : decltype(std::to_underlying(
 | 
						|
	    VK_DEBUG_UTILS_MESSAGE_SEVERITY_FLAG_BITS_MAX_ENUM_EXT
 | 
						|
	))
 | 
						|
	{
 | 
						|
		verbose = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT,
 | 
						|
		info = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT,
 | 
						|
		warning = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT,
 | 
						|
		error = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
 | 
						|
 | 
						|
		all_severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT
 | 
						|
		               | VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT
 | 
						|
		               | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT
 | 
						|
		               | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
 | 
						|
	};
 | 
						|
 | 
						|
	// NOLINTNEXTLINE(performance-enum-size)
 | 
						|
	enum Type : decltype(std::to_underlying(VK_DEBUG_UTILS_MESSAGE_TYPE_FLAG_BITS_MAX_ENUM_EXT))
 | 
						|
	{
 | 
						|
		general = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT,
 | 
						|
		validation = VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
 | 
						|
		performance = VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT,
 | 
						|
 | 
						|
		// address_binding = VK_DEBUG_UTILS_MESSAGE_TYPE_DEVICE_ADDRESS_BINDING_BIT_EXT,
 | 
						|
 | 
						|
		/** @note: does not include address binding yet. */
 | 
						|
		all_type = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT
 | 
						|
		           | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT
 | 
						|
		           | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT,
 | 
						|
	};
 | 
						|
 | 
						|
	using CallbackData_T = const VkDebugUtilsMessengerCallbackDataEXT *;
 | 
						|
 | 
						|
	using Callback_T = std::function<void(
 | 
						|
	    Severity message_severity,
 | 
						|
	    Type message_type,
 | 
						|
	    CallbackData_T vulkan_data,
 | 
						|
	    void *user_data
 | 
						|
	)>;
 | 
						|
 | 
						|
	struct CreateInfo
 | 
						|
	{
 | 
						|
		Severity severity;
 | 
						|
 | 
						|
		Type type;
 | 
						|
 | 
						|
		Callback_T callback;
 | 
						|
 | 
						|
		void *user_data;
 | 
						|
	};
 | 
						|
 | 
						|
	explicit Messenger(CreateInfo info)
 | 
						|
	    : m_callback(std::move(info.callback))
 | 
						|
	    , m_user_data(info.user_data)
 | 
						|
	{
 | 
						|
		ensure(m_callback, "Failed to initialize vk::Messenger: null callback");
 | 
						|
		ensure(info.severity != Severity {}, "Failed to initialize vk::Messenger: null severity");
 | 
						|
		ensure(info.type != Type {}, "Failed to initialize vk::Messenger: null type");
 | 
						|
 | 
						|
		// Instance may not be initialized yet
 | 
						|
		// Making it get initialized inside a call to vk_create_debug_messenger
 | 
						|
		// Which would invoke a nullptr...
 | 
						|
		if (!vk_create_debug_messenger)
 | 
						|
		{
 | 
						|
			Instance::get();
 | 
						|
		}
 | 
						|
 | 
						|
		const auto vulkan_info = VkDebugUtilsMessengerCreateInfoEXT {
 | 
						|
			.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
 | 
						|
			.messageSeverity = info.severity,
 | 
						|
			.messageType = info.type,
 | 
						|
			.pfnUserCallback = &validation_layers_callback,
 | 
						|
			.pUserData = this,
 | 
						|
		};
 | 
						|
 | 
						|
		ensure(
 | 
						|
		    !vk_create_debug_messenger(Instance::get(), &vulkan_info, nullptr, &m_debug_messenger),
 | 
						|
		    "Failed to create vulkan debug utils messenger"
 | 
						|
		);
 | 
						|
	}
 | 
						|
 | 
						|
	~Messenger()
 | 
						|
	{
 | 
						|
		vk_destroy_debug_messenger(Instance::get(), m_debug_messenger, nullptr);
 | 
						|
	}
 | 
						|
 | 
						|
	Messenger(Messenger &&) = default;
 | 
						|
 | 
						|
	Messenger(const Messenger &) = delete;
 | 
						|
 | 
						|
	auto operator=(Messenger &&) -> Messenger & = default;
 | 
						|
 | 
						|
	auto operator=(const Messenger &) const -> Messenger & = delete;
 | 
						|
 | 
						|
 | 
						|
private:
 | 
						|
	static auto validation_layers_callback(
 | 
						|
	    VkDebugUtilsMessageSeverityFlagBitsEXT const message_severity,
 | 
						|
	    VkDebugUtilsMessageTypeFlagsEXT const message_type,
 | 
						|
	    VkDebugUtilsMessengerCallbackDataEXT const *const callback_data,
 | 
						|
	    void *const vulkan_user_data
 | 
						|
	) -> VkBool32
 | 
						|
	{
 | 
						|
		auto *messenger = (Messenger *)vulkan_user_data; // NOLINT
 | 
						|
		ensure(messenger, "Null vulkan_user_data received in messenger callback");
 | 
						|
 | 
						|
		messenger->validation_layers_callback_impl(message_severity, message_type, callback_data);
 | 
						|
		return VK_FALSE;
 | 
						|
	}
 | 
						|
 | 
						|
	void validation_layers_callback_impl(
 | 
						|
	    VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
 | 
						|
	    VkDebugUtilsMessageTypeFlagsEXT message_type,
 | 
						|
	    const VkDebugUtilsMessengerCallbackDataEXT *callback_data
 | 
						|
	)
 | 
						|
	{
 | 
						|
		m_callback(
 | 
						|
		    static_cast<Severity>(message_severity),
 | 
						|
		    static_cast<Type>(message_type),
 | 
						|
		    callback_data,
 | 
						|
		    m_user_data
 | 
						|
		);
 | 
						|
	}
 | 
						|
 | 
						|
	memory::NullOnMove<VkDebugUtilsMessengerEXT> m_debug_messenger = VK_NULL_HANDLE;
 | 
						|
 | 
						|
	Callback_T m_callback;
 | 
						|
 | 
						|
	void *m_user_data;
 | 
						|
};
 | 
						|
 | 
						|
} // namespace lt::renderer::vk
 |