// ============================================= // Aster: context.cpp // Copyright (c) 2020-2024 Anish Bhobe // ============================================= #include "context.h" #include #include constexpr eastl::array VALIDATION_LAYERS = { "VK_LAYER_KHRONOS_validation", }; VKAPI_ATTR b32 VKAPI_CALL DebugCallback(const VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, const VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT *callbackData, [[maybe_unused]] void *userData) { using Severity = vk::DebugUtilsMessageSeverityFlagsEXT; using SeverityBits = vk::DebugUtilsMessageSeverityFlagBitsEXT; using MessageType = vk::DebugUtilsMessageTypeFlagsEXT; using MessageTypeBits = vk::DebugUtilsMessageTypeFlagBitsEXT; const auto severity = Severity(messageSeverity); if (MessageType(messageType) & MessageTypeBits::eValidation) { if (severity & SeverityBits::eError) ERROR("{}", callbackData->pMessage); if (severity & SeverityBits::eWarning) WARN("{}", callbackData->pMessage); if (severity & SeverityBits::eInfo) INFO("{}", callbackData->pMessage); if (severity & SeverityBits::eVerbose) VERBOSE("{}", callbackData->pMessage); } return false; } Context::Context(const cstr appName, const Version version, bool enableValidation) { INFO_IF(enableValidation, "Validation Layers enabled"); if (!glfwInit()) { const char *error = nullptr; const auto code = glfwGetError(&error); ERROR("GLFW Init failed. Cause: ({}) {}", code, error) THEN_ABORT(code); } // TODO Get/Check API Version // Creating Instance const vk::ApplicationInfo appInfo = { .pApplicationName = appName, .applicationVersion = version.GetVkVersion(), .pEngineName = PROJECT_NAME, .engineVersion = version.GetVkVersion(), .apiVersion = ASTER_API_VERSION, }; const vk::DebugUtilsMessengerCreateInfoEXT debugUtilsMessengerCreateInfo = { .messageSeverity = vk::DebugUtilsMessageSeverityFlagBitsEXT::eError | vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning | vk::DebugUtilsMessageSeverityFlagBitsEXT::eInfo, .messageType = vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral | vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance | vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation, .pfnUserCallback = DebugCallback, .pUserData = nullptr, }; u32 glfwExtensionCount = 0; cstr *glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); eastl::fixed_vector instanceExtensions(glfwExtensions, glfwExtensions + glfwExtensionCount); if (enableValidation) { instanceExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); } const vk::DynamicLoader dl; // ReSharper disable once CppInconsistentNaming const auto vkGetInstanceProcAddr = dl.getProcAddress("vkGetInstanceProcAddr"); VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr); const auto instanceCreateInfo = vk::InstanceCreateInfo{ .pNext = enableValidation ? &debugUtilsMessengerCreateInfo : nullptr, .pApplicationInfo = &appInfo, .enabledLayerCount = enableValidation ? Cast(VALIDATION_LAYERS.size()) : 0, .ppEnabledLayerNames = enableValidation ? VALIDATION_LAYERS.data() : nullptr, .enabledExtensionCount = Cast(instanceExtensions.size()), .ppEnabledExtensionNames = instanceExtensions.data(), }; // May throw. Irrecoverable. vk::Result result = createInstance(&instanceCreateInfo, nullptr, &m_Instance); ERROR_IF(result, "Instance creation failed. Cause: {}", result) THEN_ABORT(result) ELSE_DEBUG("Instance Created."); VULKAN_HPP_DEFAULT_DISPATCHER.init(m_Instance); // Debug Messenger if (enableValidation) { result = m_Instance.createDebugUtilsMessengerEXT(&debugUtilsMessengerCreateInfo, nullptr, &m_DebugMessenger); ERROR_IF(result, "Debug Messenger creation failed. Cause: {}", result) // Non-critical. Continue. ELSE_DEBUG("Debug Messenger Created."); } } Context::~Context() { if (m_DebugMessenger) { m_Instance.destroy(m_DebugMessenger, nullptr); DEBUG("Debug Messenger destroyed"); } m_Instance.destroy(nullptr); DEBUG("Instance destroyed"); glfwTerminate(); }