From 625d18a6053e28762c77efd3dd0d79fc01b0b0ef Mon Sep 17 00:00:00 2001 From: vimene Date: Thu, 26 Jun 2025 01:12:08 +0200 Subject: added validation layers to vulkan --- src/engine.cpp | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 119 insertions(+), 9 deletions(-) (limited to 'src/engine.cpp') diff --git a/src/engine.cpp b/src/engine.cpp index d276d70..da28f75 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -292,6 +292,63 @@ static int main_term() { #define SCREEN_WIDTH 640 #define SCREEN_HEIGHT 480 +const std::vector validation_layers = { + "VK_LAYER_KHRONOS_validation" +}; + +#ifdef NDEBUG +const bool enable_validation_layers = false; +#else +const bool enable_validation_layers = true; +#endif + +static bool check_validation_layer_support() { + uint32_t layer_count; + vkEnumerateInstanceLayerProperties(&layer_count, nullptr); + + std::vector available_layers(layer_count); + vkEnumerateInstanceLayerProperties(&layer_count, available_layers.data()); + + for (const char* layer_name : validation_layers) { + bool layer_found = false; + + for (const auto& layer_properties : available_layers) { + if (strcmp(layer_name, layer_properties.layerName) == 0) { + layer_found = true; + break; + } + } + + if (!layer_found) { + return false; + } + } + + return true; +} + +static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback( + VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, + VkDebugUtilsMessageTypeFlagsEXT message_type, + const VkDebugUtilsMessengerCallbackDataEXT* callback_data, + void* user_data) { + std::cerr << "validation layer: " << callback_data->pMessage << std::endl; + return VK_FALSE; +} + +static void populate_msger_create_info(VkDebugUtilsMessengerCreateInfoEXT& msger_create_info) { + msger_create_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; + msger_create_info.messageSeverity = 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; + msger_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; + msger_create_info.pfnUserCallback = debug_callback; + msger_create_info.pUserData = nullptr; +} + static int main_graphical() { // init window glfwInit(); @@ -301,6 +358,11 @@ static int main_graphical() { // init Vulkan // init Vulkan - create instance + if (enable_validation_layers && !check_validation_layer_support()) { + std::cerr << "validation layers requested, but not available!" << std::endl; + std::exit(EXIT_FAILURE); + } + VkApplicationInfo app_info{}; app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; app_info.pApplicationName = "engine - test"; @@ -309,26 +371,52 @@ static int main_graphical() { app_info.engineVersion = VK_MAKE_VERSION(1, 0, 0); app_info.apiVersion = VK_API_VERSION_1_0; - uint32_t glfw_extension_count; - const char** glfw_extensions; - glfw_extensions = glfwGetRequiredInstanceExtensions(&glfw_extension_count); + std::vector extensions; + + { + uint32_t glfw_extension_count; + const char** glfw_extensions; + glfw_extensions = glfwGetRequiredInstanceExtensions(&glfw_extension_count); + extensions.insert(extensions.end(), glfw_extensions, glfw_extensions + glfw_extension_count); + } + + if (enable_validation_layers) { + extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + } uint32_t extension_count; vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr); - std::vector extensions(extension_count); - vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extensions.data()); + std::vector available_extensions(extension_count); + vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, available_extensions.data()); std::cout << "vulkan extensions:\n"; - for (const auto& extension : extensions) + for (const auto& extension : available_extensions) std::cout << " " << extension.extensionName << "\n"; + std::cout << "\n"; + + std::cout << "required extensions:\n"; + for (const auto& extension_name : extensions) + std::cout << " " << extension_name << "\n"; + VkInstanceCreateInfo create_info{}; create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; create_info.pApplicationInfo = &app_info; - create_info.enabledExtensionCount = glfw_extension_count; - create_info.ppEnabledExtensionNames = glfw_extensions; - create_info.enabledLayerCount = 0; + create_info.enabledExtensionCount = static_cast(extensions.size()); + create_info.ppEnabledExtensionNames = extensions.data(); + + VkDebugUtilsMessengerCreateInfoEXT inst_msger_create_info{}; + if (enable_validation_layers) { + create_info.enabledLayerCount = static_cast(validation_layers.size()); + create_info.ppEnabledLayerNames = validation_layers.data(); + + populate_msger_create_info(inst_msger_create_info); + create_info.pNext = (VkDebugUtilsMessengerCreateInfoEXT*) &inst_msger_create_info; + } else { + create_info.enabledLayerCount = 0; + create_info.pNext = nullptr; + } VkInstance instance; if (VkResult res = vkCreateInstance(&create_info, nullptr, &instance); res != VK_SUCCESS) { @@ -336,12 +424,34 @@ static int main_graphical() { std::exit(EXIT_FAILURE); } + VkDebugUtilsMessengerEXT debug_messenger; + if (enable_validation_layers) { + VkDebugUtilsMessengerCreateInfoEXT msger_create_info{}; + populate_msger_create_info(msger_create_info); + + auto create_debug_messenger = (PFN_vkCreateDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT"); + if (!create_debug_messenger) { + std::cerr << "failed to set up debug messenger!" << std::endl; + std::exit(EXIT_FAILURE); + } + create_debug_messenger(instance, &msger_create_info, nullptr, &debug_messenger); + } + // main loop while (!glfwWindowShouldClose(window)) { glfwPollEvents(); } // cleanup + if (enable_validation_layers) { + auto destroy_debug_messenger = (PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT"); + if (!destroy_debug_messenger) { + std::cerr << "failed to destroy debug messenger!" << std::endl; + std::exit(EXIT_FAILURE); + } + destroy_debug_messenger(instance, debug_messenger, nullptr); + } + vkDestroyInstance(instance, nullptr); glfwDestroyWindow(window); glfwTerminate(); -- cgit v1.2.3