diff --git a/include/Nazara/VulkanRenderer/Wrapper/DebugReportCallbackEXT.hpp b/include/Nazara/VulkanRenderer/Wrapper/DebugReportCallbackEXT.hpp new file mode 100644 index 000000000..40583267d --- /dev/null +++ b/include/Nazara/VulkanRenderer/Wrapper/DebugReportCallbackEXT.hpp @@ -0,0 +1,38 @@ +// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - Vulkan renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_VULKANRENDERER_WRAPPER_DEBUGREPORTCALLBACKEXT_HPP +#define NAZARA_VULKANRENDERER_WRAPPER_DEBUGREPORTCALLBACKEXT_HPP + +#include +#include + +namespace Nz::Vk +{ + class DebugReportCallbackEXT : public InstanceObject + { + friend InstanceObject; + + public: + DebugReportCallbackEXT() = default; + DebugReportCallbackEXT(const DebugReportCallbackEXT&) = delete; + DebugReportCallbackEXT(DebugReportCallbackEXT&&) = default; + ~DebugReportCallbackEXT() = default; + + DebugReportCallbackEXT& operator=(const DebugReportCallbackEXT&) = delete; + DebugReportCallbackEXT& operator=(DebugReportCallbackEXT&&) = delete; + + static inline bool IsSupported(Instance& instance); + + private: + static inline VkResult CreateHelper(Instance& instance, const VkDebugReportCallbackCreateInfoEXT* createInfo, const VkAllocationCallbacks* allocator, VkDebugReportCallbackEXT* handle); + static inline void DestroyHelper(Instance& instance, VkDebugReportCallbackEXT handle, const VkAllocationCallbacks* allocator); + }; +} + +#include + +#endif // NAZARA_VULKANRENDERER_WRAPPER_DEBUGREPORTCALLBACKEXT_HPP diff --git a/include/Nazara/VulkanRenderer/Wrapper/DebugReportCallbackEXT.inl b/include/Nazara/VulkanRenderer/Wrapper/DebugReportCallbackEXT.inl new file mode 100644 index 000000000..1135958bc --- /dev/null +++ b/include/Nazara/VulkanRenderer/Wrapper/DebugReportCallbackEXT.inl @@ -0,0 +1,26 @@ +// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - Vulkan renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz::Vk +{ + inline bool DebugReportCallbackEXT::IsSupported(Instance& instance) + { + return instance.vkCreateDebugReportCallbackEXT != nullptr; + } + + inline VkResult DebugReportCallbackEXT::CreateHelper(Instance& instance, const VkDebugReportCallbackCreateInfoEXT* createInfo, const VkAllocationCallbacks* allocator, VkDebugReportCallbackEXT* handle) + { + return instance.vkCreateDebugReportCallbackEXT(instance, createInfo, allocator, handle); + } + + inline void DebugReportCallbackEXT::DestroyHelper(Instance& instance, VkDebugReportCallbackEXT handle, const VkAllocationCallbacks* allocator) + { + return instance.vkDestroyDebugReportCallbackEXT(instance, handle, allocator); + } +} + +#include diff --git a/include/Nazara/VulkanRenderer/Wrapper/DebugUtilsMessengerEXT.hpp b/include/Nazara/VulkanRenderer/Wrapper/DebugUtilsMessengerEXT.hpp index a462d1396..790c706ab 100644 --- a/include/Nazara/VulkanRenderer/Wrapper/DebugUtilsMessengerEXT.hpp +++ b/include/Nazara/VulkanRenderer/Wrapper/DebugUtilsMessengerEXT.hpp @@ -10,30 +10,27 @@ #include #include -namespace Nz +namespace Nz::Vk { - namespace Vk + class DebugUtilsMessengerEXT : public InstanceObject { - class DebugUtilsMessengerEXT : public InstanceObject - { - friend InstanceObject; + friend InstanceObject; - public: - DebugUtilsMessengerEXT() = default; - DebugUtilsMessengerEXT(const DebugUtilsMessengerEXT&) = delete; - DebugUtilsMessengerEXT(DebugUtilsMessengerEXT&&) = default; - ~DebugUtilsMessengerEXT() = default; + public: + DebugUtilsMessengerEXT() = default; + DebugUtilsMessengerEXT(const DebugUtilsMessengerEXT&) = delete; + DebugUtilsMessengerEXT(DebugUtilsMessengerEXT&&) = default; + ~DebugUtilsMessengerEXT() = default; - DebugUtilsMessengerEXT& operator=(const DebugUtilsMessengerEXT&) = delete; - DebugUtilsMessengerEXT& operator=(DebugUtilsMessengerEXT&&) = delete; + DebugUtilsMessengerEXT& operator=(const DebugUtilsMessengerEXT&) = delete; + DebugUtilsMessengerEXT& operator=(DebugUtilsMessengerEXT&&) = delete; - static inline bool IsSupported(Instance& instance); + static inline bool IsSupported(Instance& instance); - private: - static inline VkResult CreateHelper(Instance& instance, const VkDebugUtilsMessengerCreateInfoEXT* createInfo, const VkAllocationCallbacks* allocator, VkDebugUtilsMessengerEXT* handle); - static inline void DestroyHelper(Instance& instance, VkDebugUtilsMessengerEXT handle, const VkAllocationCallbacks* allocator); - }; - } + private: + static inline VkResult CreateHelper(Instance& instance, const VkDebugUtilsMessengerCreateInfoEXT* createInfo, const VkAllocationCallbacks* allocator, VkDebugUtilsMessengerEXT* handle); + static inline void DestroyHelper(Instance& instance, VkDebugUtilsMessengerEXT handle, const VkAllocationCallbacks* allocator); + }; } #include diff --git a/include/Nazara/VulkanRenderer/Wrapper/DebugUtilsMessengerEXT.inl b/include/Nazara/VulkanRenderer/Wrapper/DebugUtilsMessengerEXT.inl index aa2901c3e..d33a32933 100644 --- a/include/Nazara/VulkanRenderer/Wrapper/DebugUtilsMessengerEXT.inl +++ b/include/Nazara/VulkanRenderer/Wrapper/DebugUtilsMessengerEXT.inl @@ -5,24 +5,21 @@ #include #include -namespace Nz +namespace Nz::Vk { - namespace Vk + inline bool DebugUtilsMessengerEXT::IsSupported(Instance& instance) { - inline bool DebugUtilsMessengerEXT::IsSupported(Instance& instance) - { - return instance.vkCreateDebugUtilsMessengerEXT != nullptr; - } + return instance.vkCreateDebugUtilsMessengerEXT != nullptr; + } - inline VkResult DebugUtilsMessengerEXT::CreateHelper(Instance& instance, const VkDebugUtilsMessengerCreateInfoEXT* createInfo, const VkAllocationCallbacks* allocator, VkDebugUtilsMessengerEXT* handle) - { - return instance.vkCreateDebugUtilsMessengerEXT(instance, createInfo, allocator, handle); - } + inline VkResult DebugUtilsMessengerEXT::CreateHelper(Instance& instance, const VkDebugUtilsMessengerCreateInfoEXT* createInfo, const VkAllocationCallbacks* allocator, VkDebugUtilsMessengerEXT* handle) + { + return instance.vkCreateDebugUtilsMessengerEXT(instance, createInfo, allocator, handle); + } - inline void DebugUtilsMessengerEXT::DestroyHelper(Instance& instance, VkDebugUtilsMessengerEXT handle, const VkAllocationCallbacks* allocator) - { - return instance.vkDestroyDebugUtilsMessengerEXT(instance, handle, allocator); - } + inline void DebugUtilsMessengerEXT::DestroyHelper(Instance& instance, VkDebugUtilsMessengerEXT handle, const VkAllocationCallbacks* allocator) + { + return instance.vkDestroyDebugUtilsMessengerEXT(instance, handle, allocator); } } diff --git a/include/Nazara/VulkanRenderer/Wrapper/DeviceObject.inl b/include/Nazara/VulkanRenderer/Wrapper/DeviceObject.inl index dbbadeacb..1af78d288 100644 --- a/include/Nazara/VulkanRenderer/Wrapper/DeviceObject.inl +++ b/include/Nazara/VulkanRenderer/Wrapper/DeviceObject.inl @@ -41,7 +41,7 @@ namespace Nz::Vk m_lastErrorCode = C::CreateHelper(*m_device, &createInfo, allocator, &m_handle); if (m_lastErrorCode != VkResult::VK_SUCCESS) { - NazaraError("Failed to create Vulkan object: " + TranslateVulkanError(m_lastErrorCode)); + NazaraError("Failed to create Vulkan device object: " + TranslateVulkanError(m_lastErrorCode)); return false; } diff --git a/include/Nazara/VulkanRenderer/Wrapper/InstanceFunctions.hpp b/include/Nazara/VulkanRenderer/Wrapper/InstanceFunctions.hpp index dbbd79e3d..0c1a3250c 100644 --- a/include/Nazara/VulkanRenderer/Wrapper/InstanceFunctions.hpp +++ b/include/Nazara/VulkanRenderer/Wrapper/InstanceFunctions.hpp @@ -55,6 +55,12 @@ NAZARA_VULKANRENDERER_INSTANCE_EXT_BEGIN(VK_KHR_surface) NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkGetPhysicalDeviceSurfaceSupportKHR) NAZARA_VULKANRENDERER_INSTANCE_EXT_END() +NAZARA_VULKANRENDERER_INSTANCE_EXT_BEGIN(VK_EXT_debug_report) + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkCreateDebugReportCallbackEXT) + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkDestroyDebugReportCallbackEXT) + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkDebugReportMessageEXT) +NAZARA_VULKANRENDERER_INSTANCE_EXT_END() + NAZARA_VULKANRENDERER_INSTANCE_EXT_BEGIN(VK_EXT_debug_utils) NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkCreateDebugUtilsMessengerEXT) NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkDestroyDebugUtilsMessengerEXT) diff --git a/include/Nazara/VulkanRenderer/Wrapper/InstanceObject.inl b/include/Nazara/VulkanRenderer/Wrapper/InstanceObject.inl index 958b6b240..24ba4481a 100644 --- a/include/Nazara/VulkanRenderer/Wrapper/InstanceObject.inl +++ b/include/Nazara/VulkanRenderer/Wrapper/InstanceObject.inl @@ -40,7 +40,7 @@ namespace Nz m_lastErrorCode = C::CreateHelper(*m_instance, &createInfo, allocator, &m_handle); if (m_lastErrorCode != VkResult::VK_SUCCESS) { - NazaraError("Failed to create Vulkan object: " + TranslateVulkanError(m_lastErrorCode)); + NazaraError("Failed to create Vulkan instance object: " + TranslateVulkanError(m_lastErrorCode)); return false; } diff --git a/include/Nazara/VulkanRenderer/Wrapper/Pipeline.inl b/include/Nazara/VulkanRenderer/Wrapper/Pipeline.inl index a77a680f0..79131f018 100644 --- a/include/Nazara/VulkanRenderer/Wrapper/Pipeline.inl +++ b/include/Nazara/VulkanRenderer/Wrapper/Pipeline.inl @@ -75,7 +75,7 @@ namespace Nz m_lastErrorCode = result; if (m_lastErrorCode != VkResult::VK_SUCCESS) { - NazaraError("Failed to create Vulkan object: " + TranslateVulkanError(m_lastErrorCode)); + NazaraError("Failed to create Vulkan pipeline: " + TranslateVulkanError(m_lastErrorCode)); return false; } diff --git a/src/Nazara/VulkanRenderer/Vulkan.cpp b/src/Nazara/VulkanRenderer/Vulkan.cpp index b8043cc15..9d3c8c073 100644 --- a/src/Nazara/VulkanRenderer/Vulkan.cpp +++ b/src/Nazara/VulkanRenderer/Vulkan.cpp @@ -251,6 +251,8 @@ namespace Nz if (availableExtensions.count(VK_EXT_DEBUG_UTILS_EXTENSION_NAME)) enabledExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + else if (availableExtensions.count(VK_EXT_DEBUG_REPORT_EXTENSION_NAME)) + enabledExtensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); } std::vector additionalExtensions; // Just to keep the String alive diff --git a/src/Nazara/VulkanRenderer/Wrapper/Instance.cpp b/src/Nazara/VulkanRenderer/Wrapper/Instance.cpp index f84193771..25ee5a880 100644 --- a/src/Nazara/VulkanRenderer/Wrapper/Instance.cpp +++ b/src/Nazara/VulkanRenderer/Wrapper/Instance.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -17,7 +18,7 @@ namespace Nz { namespace { - VKAPI_ATTR VkBool32 VKAPI_CALL DebugCallback( + VKAPI_ATTR VkBool32 VKAPI_CALL DebugMessengerCallback( VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageTypes, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, @@ -77,10 +78,55 @@ namespace Nz return VK_FALSE; //< Should the Vulkan call be aborted } + + VKAPI_ATTR VkBool32 VKAPI_CALL DebugReportCallback( + VkDebugReportFlagsEXT flags, + VkDebugReportObjectTypeEXT /*objectType*/, + uint64_t /*object*/, + size_t /*location*/, + int32_t messageCode, + const char* pLayerPrefix, + const char* pMessage, + void* /*pUserData*/) + { + std::stringstream ss; + ss << "Vulkan log: "; + + if (flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) + ss << "[Info]"; + + if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) + ss << "[Warning]"; + + if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) + ss << "[Error]"; + + if (flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) + ss << "[Performance]"; + + if (flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) + ss << "[Debug]"; + + ss << "[" << messageCode << "]"; + if (pLayerPrefix) + ss << "[layer " << pLayerPrefix << "]"; + + ss << ": " << pMessage; + + if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) + NazaraError(ss.str()); + else if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) + NazaraWarning(ss.str()); + else + NazaraNotice(ss.str()); + + return VK_FALSE; //< Should the Vulkan call be aborted + } } struct Instance::InternalData { + DebugReportCallbackEXT debugCallback; DebugUtilsMessengerEXT debugMessenger; }; @@ -125,9 +171,12 @@ namespace Nz { ErrorFlags flags(ErrorMode::ThrowException, true); -#define NAZARA_VULKANRENDERER_INSTANCE_EXT_BEGIN(ext) if (IsExtensionLoaded(#ext)) { +#define NAZARA_VULKANRENDERER_INSTANCE_EXT_BEGIN(ext) if (IsExtensionLoaded(#ext)) { \ + NazaraDebug(#ext " extension is supported"); #define NAZARA_VULKANRENDERER_INSTANCE_EXT_END() } -#define NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(func) func = reinterpret_cast(GetProcAddr(#func)); +#define NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(func) func = reinterpret_cast(GetProcAddr(#func)); \ + if (!func) \ + NazaraWarning("failed to get a function pointer for " #func " despite its being reported as supported"); #define NAZARA_VULKANRENDERER_INSTANCE_CORE_EXT_FUNCTION(func, coreVersion, suffix, extName) \ if (m_apiVersion >= coreVersion) \ @@ -226,24 +275,43 @@ namespace Nz { NazaraAssert(m_internalData, "Instance must be created before callbacks are installed"); - if (!Vk::DebugUtilsMessengerEXT::IsSupported(*this)) + if (Vk::DebugUtilsMessengerEXT::IsSupported(*this)) { - NazaraWarning(VK_EXT_DEBUG_UTILS_EXTENSION_NAME " is not supported, cannot install debug message callback"); + VkDebugUtilsMessengerCreateInfoEXT callbackCreateInfo = {}; + callbackCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; + callbackCreateInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT; + callbackCreateInfo.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; + callbackCreateInfo.pfnUserCallback = &DebugMessengerCallback; + callbackCreateInfo.pUserData = this; + + if (!m_internalData->debugMessenger.Create(*this, callbackCreateInfo)) + { + NazaraWarning("failed to install debug message callback"); + return; + } + } + else if (Vk::DebugReportCallbackEXT::IsSupported(*this)) + { + NazaraWarning(VK_EXT_DEBUG_UTILS_EXTENSION_NAME " is not supported, falling back on " VK_EXT_DEBUG_REPORT_EXTENSION_NAME); + + VkDebugReportCallbackCreateInfoEXT callbackCreateInfo = {}; + callbackCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT; + callbackCreateInfo.flags = VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_INFORMATION_BIT_EXT; + callbackCreateInfo.pfnCallback = &DebugReportCallback; + callbackCreateInfo.pUserData = this; + + if (!m_internalData->debugCallback.Create(*this, callbackCreateInfo)) + { + NazaraWarning("failed to install debug message callback"); + return; + } + } + else + { + NazaraWarning(VK_EXT_DEBUG_UTILS_EXTENSION_NAME " nor " VK_EXT_DEBUG_REPORT_EXTENSION_NAME " are not supported, cannot install debug message callback"); return; } - VkDebugUtilsMessengerCreateInfoEXT callbackCreateInfo = {}; - callbackCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; - callbackCreateInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT; - callbackCreateInfo.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; - callbackCreateInfo.pfnUserCallback = &DebugCallback; - callbackCreateInfo.pUserData = this; - - if (!m_internalData->debugMessenger.Create(*this, callbackCreateInfo)) - { - NazaraWarning("failed to install debug message callback"); - return; - } } void Instance::DestroyInstance()