#include #include #include #include "window.hpp" #define NELEMS(x) (sizeof(x) / sizeof((x)[0])) GLFWwindow *window = nullptr; VkInstance vkInstance = nullptr; VkPhysicalDevice vkPhysicalDevice = nullptr; VkSurfaceKHR vkSurfaceKHR = nullptr; VkDebugReportCallbackEXT vkDebugReport = nullptr; const bool ENABLE_VALIDATION_LAYERS = true; const bool VULKAN_DEBUG_REPORT = true; VkBool32 UserDebugCallback( VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, void *pUserData) { printf("Validation Layer: %s\n", pCallbackData->pMessage); return VK_FALSE; } static VKAPI_ATTR VkBool32 VKAPI_CALL DebugReport(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, unsigned long object, size_t location, int messageCode, const char *pLayerPrefix, const char *pMessage, void *pUserData) { (void)flags; (void)object; (void)location; (void)messageCode; (void)pUserData; (void)pLayerPrefix; // Unused arguments fprintf(stderr, "[vulkan] Debug report from ObjectType: %i\nMessage: %s\n\n", objectType, pMessage); return VK_FALSE; } void InitVulkan() { if (ENABLE_VALIDATION_LAYERS) { unsigned int layerCount; vkEnumerateInstanceLayerProperties(&layerCount, nullptr); std::vector availableLayers(layerCount); vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data()); printf("Available Layers:\n"); for (const auto &layerProperties : availableLayers) { printf("\t%s\n", layerProperties.layerName); } } VkApplicationInfo appInfo{}; appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; appInfo.apiVersion = VK_API_VERSION_1_3; appInfo.pApplicationName = "pikul"; appInfo.pEngineName = "pikul"; appInfo.applicationVersion = 1; appInfo.engineVersion = 1; VkInstanceCreateInfo createInfo{}; createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; createInfo.pApplicationInfo = &appInfo; createInfo.enabledLayerCount = 0; std::vector enabledLayerNames(1); enabledLayerNames[0] = "VK_LAYER_KHRONOS_validation"; printf("Requested Layers:\n"); for (const char *s : enabledLayerNames) { printf("\t%s\n", s); } VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo{}; debugCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; if (ENABLE_VALIDATION_LAYERS) { createInfo.enabledLayerCount = enabledLayerNames.size(); createInfo.ppEnabledLayerNames = enabledLayerNames.data(); debugCreateInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; debugCreateInfo.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; debugCreateInfo.pfnUserCallback = UserDebugCallback; debugCreateInfo.pUserData = nullptr; debugCreateInfo.pNext = nullptr; createInfo.pNext = &debugCreateInfo; } std::vector allGlfwExtensions; { unsigned int extensionCount = 0; const char **glfwExtensions = glfwGetRequiredInstanceExtensions(&extensionCount); allGlfwExtensions.reserve(extensionCount + 2); copy(&glfwExtensions[0], &glfwExtensions[extensionCount], back_inserter(allGlfwExtensions)); if (ENABLE_VALIDATION_LAYERS) { allGlfwExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); allGlfwExtensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); } createInfo.ppEnabledExtensionNames = allGlfwExtensions.data(); createInfo.enabledExtensionCount = allGlfwExtensions.size(); } printf("Required Extensions:\n"); for (const auto &ext : allGlfwExtensions) { printf("\t%s\n", ext); } if (ENABLE_VALIDATION_LAYERS) { unsigned int extensionCount = 0; vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr); std::vector extensions(extensionCount); vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data()); printf("Available Extensions:\n"); for (const auto &extension : extensions) { printf("\t%s\n", extension.extensionName); } } auto result = vkCreateInstance(&createInfo, nullptr, &vkInstance); if (result != VK_SUCCESS) { printf("Failed to create VkInstance! : %d\n", result); throw result; } if (VULKAN_DEBUG_REPORT) { PFN_vkCreateDebugReportCallbackEXT func = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(vkInstance, "vkCreateDebugReportCallbackEXT"); assert(func != nullptr && "vkCreateDebugReportCallbackEXT ProcAddr was nullptr"); VkDebugReportCallbackCreateInfoEXT debugReportCallbackCreateInfo{}; debugReportCallbackCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; debugReportCallbackCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT; debugReportCallbackCreateInfo.pfnCallback = DebugReport; debugReportCallbackCreateInfo.pUserData = nullptr; VkResult result = func(vkInstance, &debugReportCallbackCreateInfo, nullptr, &vkDebugReport); if (result != VK_SUCCESS) { fprintf(stderr, "%s\n", "Failed to create debug report!"); } } } void CreateWindow(PKEWindowProperties *wp) { if (vkInstance != nullptr) return; glfwInit(); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); window = glfwCreateWindow(wp->width, wp->height, "Pikul", nullptr, nullptr); InitVulkan(); } void DestroyWindow() { if (VULKAN_DEBUG_REPORT) { auto vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(vkInstance, "vkDestroyDebugReportCallbackEXT"); vkDestroyDebugReportCallbackEXT(vkInstance, vkDebugReport, nullptr); } if (vkInstance != nullptr) return; PFN_vkDestroyInstance(vkInstance); glfwDestroyWindow(window); glfwTerminate(); }