Browse Source

Add vulkan error callbacks

Kajetan Johannes Hammerle 3 months ago
parent
commit
372d921704
1 changed files with 89 additions and 2 deletions
  1. 89 2
      src/VulkanWrapper.c

+ 89 - 2
src/VulkanWrapper.c

@@ -8,6 +8,8 @@
 
 typedef struct {
     VkInstance instance;
+    VkDebugUtilsMessengerEXT debugMessenger;
+    VkDebugReportCallbackEXT debugReportCallback;
     u32 graphicsFamily;
     VkPhysicalDevice physicalDevice;
     VkDevice device;
@@ -50,6 +52,12 @@ static const char* getVulkanErrorString(VkResult r) {
         }                                                                      \
     } while(false)
 
+static PFN_vkVoidFunction getVulkanFunction(const char* name) {
+    return vkGetInstanceProcAddr(vk.instance, name);
+}
+
+#define GET_VULKAN_FUNCTION(name) ((PFN_##name)getVulkanFunction(#name))
+
 static bool initInstance() {
     VkApplicationInfo i = {.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
                            .pApplicationName = "Vulkan",
@@ -71,6 +79,84 @@ static bool initInstance() {
     return false;
 }
 
+static VKAPI_ATTR VkBool32 onVulkanDebugMessenger VKAPI_CALL(
+    VkDebugUtilsMessageSeverityFlagBitsEXT, VkDebugUtilsMessageTypeFlagsEXT,
+    const VkDebugUtilsMessengerCallbackDataEXT* data, void*) {
+    LOG_WARNING("Vulkan validation layer message: %s", data->pMessage);
+    return false;
+}
+
+static bool initDebugMessenger() {
+    VkDebugUtilsMessengerCreateInfoEXT info = {
+        .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
+        .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
+                           VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
+        .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,
+        .pfnUserCallback = onVulkanDebugMessenger};
+    auto f = GET_VULKAN_FUNCTION(vkCreateDebugUtilsMessengerEXT);
+    if(f == nullptr) {
+        LOG_WARNING("Could not find debug util messenger function");
+        return false;
+    }
+    VK_ASSERT(f(vk.instance, &info, nullptr, &vk.debugMessenger));
+    return false;
+}
+
+static VKAPI_ATTR VkBool32 onVulkanDebugReport
+VKAPI_CALL(VkDebugReportFlagsEXT, VkDebugReportObjectTypeEXT, uint64_t, size_t,
+           int32_t, const char* pLayerPrefix, const char* pMessage, void*) {
+    LOG_WARNING("Vulkan debug message '%s': %s", pLayerPrefix, pMessage);
+    return false;
+}
+
+static bool initDebugReportCallback() {
+    VkDebugReportCallbackCreateInfoEXT info = {
+        .sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT,
+        .flags = VK_DEBUG_REPORT_WARNING_BIT_EXT |
+                 VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT |
+                 VK_DEBUG_REPORT_ERROR_BIT_EXT,
+        .pfnCallback = onVulkanDebugReport};
+    auto f = GET_VULKAN_FUNCTION(vkCreateDebugReportCallbackEXT);
+    if(f == nullptr) {
+        LOG_WARNING("Could not find debug report function");
+        return false;
+    }
+    VK_ASSERT(f(vk.instance, &info, nullptr, &vk.debugReportCallback));
+    return false;
+}
+
+static bool initDebugging() {
+    return initDebugMessenger() || initDebugReportCallback();
+}
+
+static void destroyDebugMessenger() {
+    auto f = GET_VULKAN_FUNCTION(vkDestroyDebugUtilsMessengerEXT);
+    if(f == nullptr) {
+        LOG_WARNING("Could not find debug util messenger destroy function");
+        return;
+    }
+    f(vk.instance, vk.debugMessenger, nullptr);
+}
+
+static void destroyDebugReportCallback() {
+    auto f = GET_VULKAN_FUNCTION(vkDestroyDebugReportCallbackEXT);
+    if(f == nullptr) {
+        LOG_WARNING("Could not find debug report destroy function");
+        return;
+    }
+    f(vk.instance, vk.debugReportCallback, nullptr);
+}
+
+static void destroyDebugging() {
+    if(vk.instance == VK_NULL_HANDLE) {
+        return;
+    }
+    destroyDebugMessenger();
+    destroyDebugReportCallback();
+}
+
 static bool choosePhysicalDevice(VkPhysicalDevice* devices, u32 amount) {
     VK_ASSERT(vkEnumeratePhysicalDevices(vk.instance, &amount, devices));
     int bestPoints = 0;
@@ -288,8 +374,8 @@ static bool createSwapchainImages(SwapchainImages* i) {
 bool initVulkan() {
     vk.width = 400;
     vk.height = 300;
-    if(initInstance() || initPhysicalDevice() || initDevice() ||
-       initSurface() || initSwapchain()) {
+    if(initInstance() || initDebugging() || initPhysicalDevice() ||
+       initDevice() || initSurface() || initSwapchain()) {
         return true;
     }
     SwapchainImages images;
@@ -308,5 +394,6 @@ void destroyVulkan(void) {
         vkDestroySurfaceKHR(vk.instance, vk.surface, nullptr);
     }
     vkDestroyDevice(vk.device, nullptr);
+    destroyDebugging();
     vkDestroyInstance(vk.instance, nullptr);
 }