From cd8ab16ad24b75b350facdb932377242c8aa53c2 Mon Sep 17 00:00:00 2001 From: Anish Bhobe Date: Wed, 12 Jun 2024 16:21:44 +0200 Subject: [PATCH] Move to vulkan raii. Vulkan RAII is new, but it helps manage a multi-device environment without the additional context-tracking. --- aster_core/aster.cpp | 19 ++++++--------- aster_core/config.h | 1 - aster_core/context.cpp | 50 ++++++++++++++++++-------------------- aster_core/context.h | 5 ++-- aster_core/global.h | 2 +- aster_core/window.cpp | 55 ++++++++++++++++++++---------------------- aster_core/window.h | 27 +++++++++------------ 7 files changed, 73 insertions(+), 86 deletions(-) diff --git a/aster_core/aster.cpp b/aster_core/aster.cpp index b82f0b6..f6c5b4d 100644 --- a/aster_core/aster.cpp +++ b/aster_core/aster.cpp @@ -1,18 +1,15 @@ -#include #include "constants.h" #include "glfw_context.h" #include "window.h" +#include -int main(int, char**) { +int main(int, char **) { + GlfwContext glfw = {}; + Context context = {"Aster", VERSION}; + Window window = {"Aster1", &context, { 640, 480 }}; - GlfwContext* glfw = new GlfwContext(); - Context* context = new Context("Aster", VERSION); - Window* window = new Window("Aster1", context, { 640, 480 }); + while (window.poll()) { + } - delete window; - delete context; - delete glfw; - - return 0; + return 0; } - diff --git a/aster_core/config.h b/aster_core/config.h index bb5f85b..4b14c88 100644 --- a/aster_core/config.h +++ b/aster_core/config.h @@ -11,7 +11,6 @@ #define GLFW_INCLUDE_VULKAN #define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1 #define VULKAN_HPP_NO_STRUCT_CONSTRUCTORS -#define VULKAN_HPP_NO_EXCEPTIONS #if defined(NDEBUG) #define USE_OPTICK (0) diff --git a/aster_core/context.cpp b/aster_core/context.cpp index 4bf07c9..6018bf7 100644 --- a/aster_core/context.cpp +++ b/aster_core/context.cpp @@ -5,7 +5,7 @@ #include "context.h" -VKAPI_ATTR b32 VKAPI_CALL Context::debug_callback(VkDebugUtilsMessageSeverityFlagBitsEXT _message_severity, VkDebugUtilsMessageTypeFlagsEXT _message_type, const VkDebugUtilsMessengerCallbackDataEXT *_callback_data, [[maybe_unused]] void *_user_data) { +VKAPI_ATTR b32 VKAPI_CALL Context::debug_callback(const VkDebugUtilsMessageSeverityFlagBitsEXT _message_severity, const VkDebugUtilsMessageTypeFlagsEXT _message_type, const VkDebugUtilsMessengerCallbackDataEXT *_callback_data, [[maybe_unused]] void *_user_data) { using Severity = vk::DebugUtilsMessageSeverityFlagsEXT; using SeverityBits = vk::DebugUtilsMessageSeverityFlagBitsEXT; using MessageType = vk::DebugUtilsMessageTypeFlagsEXT; @@ -29,8 +29,6 @@ VKAPI_ATTR b32 VKAPI_CALL Context::debug_callback(VkDebugUtilsMessageSeverityFla } void Context::init(const std::string_view &_app_name, const Version &_app_version) { - vk::Result result; - INFO_IF(enable_validation_layers, "Validation Layers enabled"); // Creating Instance @@ -67,33 +65,31 @@ void Context::init(const std::string_view &_app_name, const Version &_app_versio const auto vkGetInstanceProcAddr = dl.getProcAddress("vkGetInstanceProcAddr"); VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr); - tie(result, instance) = vk::createInstance({ - .pNext = enable_validation_layers ? &debug_messenger_create_info : nullptr, - .pApplicationInfo = &app_info, - .enabledLayerCount = enable_validation_layers ? cast(validation_layers.size()) : 0, - .ppEnabledLayerNames = enable_validation_layers ? validation_layers.data() : nullptr, - .enabledExtensionCount = cast(vulkan_extensions.size()), - .ppEnabledExtensionNames = vulkan_extensions.data(), - }); - ERROR_IF(failed(result), "Failed to create Vulkan instance with "s + to_string(result)) - THEN_CRASH(result) - ELSE_INFO("Instance Created."); - VULKAN_HPP_DEFAULT_DISPATCHER.init(instance); + try { + instance = vk::raii::Instance{ raii_context, { + .pNext = enable_validation_layers ? &debug_messenger_create_info : nullptr, + .pApplicationInfo = &app_info, + .enabledLayerCount = enable_validation_layers ? cast(validation_layers.size()) : 0, + .ppEnabledLayerNames = enable_validation_layers ? validation_layers.data() : nullptr, + .enabledExtensionCount = cast(vulkan_extensions.size()), + .ppEnabledExtensionNames = vulkan_extensions.data(), + } }; + } catch (const std::exception &err) { + ERROR("Failed to create Vulkan instance with "s + err.what()); + throw err; + } + INFO("Instance Created."); // Debug Messenger if (enable_validation_layers) { - tie(result, debug_messenger) = instance.createDebugUtilsMessengerEXT(debug_messenger_create_info); - ERROR_IF(failed(result), "Debug Messenger creation failed with "s + to_string(result)) - ELSE_INFO("Debug Messenger Created."); + try { + debug_messenger = vk::raii::DebugUtilsMessengerEXT{ instance, debug_messenger_create_info }; + } catch (const std::exception &err) { + ERROR("Debug Messenger creation failed with "s + err.what()); + throw err; + } + INFO("Debug Messenger Created."); } } -Context::~Context() { - if (instance) { - if (enable_validation_layers && debug_messenger) { - instance.destroyDebugUtilsMessengerEXT(debug_messenger); - } - instance.destroy(); - INFO("Context destroyed"); - } -} +Context::~Context() = default; diff --git a/aster_core/context.h b/aster_core/context.h index b6c6f60..ca71d8a 100644 --- a/aster_core/context.h +++ b/aster_core/context.h @@ -73,8 +73,9 @@ public: VK_KHR_MULTIVIEW_EXTENSION_NAME, }; - vk::Instance instance; - vk::DebugUtilsMessengerEXT debug_messenger; + vk::raii::Context raii_context; + vk::raii::Instance instance{ nullptr }; + vk::raii::DebugUtilsMessengerEXT debug_messenger{ nullptr }; private: void init(const std::string_view &_app_name, const Version &_app_version); diff --git a/aster_core/global.h b/aster_core/global.h index f1cf576..b6d7820 100644 --- a/aster_core/global.h +++ b/aster_core/global.h @@ -15,8 +15,8 @@ #include #define VULKAN_HPP_ASSERT(expr) DEBUG_IF(!(expr), "Vulkan assert failed") -#include #include +#include #define CODE_LOC " @ " __FILE__ ":" VULKAN_HPP_STRINGIFY(__LINE__) [[nodiscard]] inline bool failed(const vk::Result _result) { diff --git a/aster_core/window.cpp b/aster_core/window.cpp index 2be78ec..36a4a9b 100644 --- a/aster_core/window.cpp +++ b/aster_core/window.cpp @@ -4,18 +4,15 @@ // ============================================= #include "window.h" -#include "logger.h" #include "context.h" #include "glfw_context.h" +#include "logger.h" -Window::Window(const std::string_view& _title, Context* _context, vk::Extent2D _extent, b8 _full_screen) - : parent_context{ std::move(_context) } - , extent{ _extent } - , name{ _title } - , full_screen{ _full_screen } { - +Window::Window(const std::string_view &_title, Context *_context, const vk::Extent2D _extent, const bool _full_screen) : + extent{ _extent }, name{ _title } { + full_screen = _full_screen; monitor = glfwGetPrimaryMonitor(); - ERROR_IF(monitor == nullptr, "No monitor found"); + ERROR_IF(monitor == nullptr, "No monitor found"); i32 x_, y_, w_, h_; glfwGetMonitorWorkarea(monitor, &x_, &y_, &w_, &h_); @@ -23,8 +20,9 @@ Window::Window(const std::string_view& _title, Context* _context, vk::Extent2D _ glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); glfwWindowHint(GLFW_CENTER_CURSOR, GLFW_TRUE); - window = glfwCreateWindow(extent.width, extent.height, name.data(), full_screen ? monitor : nullptr, nullptr); - ERROR_IF(window == nullptr, "Window creation failed") ELSE_INFO(std::fmt("Window '%s' created with resolution '%dx%d'", name.data(), extent.width, extent.height)); + window = glfwCreateWindow(cast(extent.width), cast(extent.height), name.c_str(), (_full_screen ? monitor : nullptr), nullptr); + ERROR_IF(window == nullptr, "Window creation failed") + ELSE_INFO(std::fmt("Window '%s' created with resolution '%dx%d'", name.data(), extent.width, extent.height)); if (window == nullptr) { auto code = GlfwContext::post_error(); glfwTerminate(); @@ -32,27 +30,31 @@ Window::Window(const std::string_view& _title, Context* _context, vk::Extent2D _ } if (full_screen == false) { - glfwSetWindowPos(window, (w_ - extent.width) / 2, (h_ - extent.height) / 2); + glfwSetWindowPos(window, cast(w_ - extent.width) / 2, cast(h_ - extent.height) / 2); } glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); VkSurfaceKHR surface_; - auto result = cast(glfwCreateWindowSurface(cast(_context->instance), window, nullptr, &surface_)); - ERROR_IF(failed(result), "Failed to create Surface with "s + to_string(result)) THEN_CRASH(result) ELSE_INFO("Surface Created"); - surface = vk::SurfaceKHR(surface_); + auto result = cast(glfwCreateWindowSurface(cast(*_context->instance), window, nullptr, &surface_)); + if (failed(result)) { + ERROR("Failed to create Surface with "s + to_string(result)); + throw std::runtime_error("Failed to create Surface with "s + to_string(result)); + } + INFO("Surface Created"); + surface = vk::raii::SurfaceKHR{ _context->instance, surface_ }; } -Window::Window(Window&& _other) noexcept: parent_context{ std::move(_other.parent_context) } - , window{ std::exchange(_other.window, nullptr) } - , monitor{ _other.monitor } - , surface{ std::exchange(_other.surface, nullptr) } - , extent{ _other.extent } - , name{ std::move(_other.name) } - , full_screen{ _other.full_screen } {} +Window::Window(Window &&_other) noexcept : + window{ std::exchange(_other.window, nullptr) }, + monitor{ _other.monitor }, + surface{ std::exchange(_other.surface, nullptr) }, + extent{ _other.extent }, + name{ std::move(_other.name) }, + full_screen{ _other.full_screen } {} -Window& Window::operator=(Window&& _other) noexcept { - if (this == &_other) return *this; - parent_context = std::move(_other.parent_context); +Window &Window::operator=(Window &&_other) noexcept { + if (this == &_other) + return *this; window = _other.window; monitor = _other.monitor; surface = std::exchange(_other.surface, nullptr); @@ -63,11 +65,6 @@ Window& Window::operator=(Window&& _other) noexcept { } Window::~Window() { - if (parent_context && surface) { - parent_context->instance.destroy(surface); - INFO("Surface Destroyed"); - } - if (window != nullptr) { glfwDestroyWindow(window); window = nullptr; diff --git a/aster_core/window.h b/aster_core/window.h index e4929b7..de03c02 100644 --- a/aster_core/window.h +++ b/aster_core/window.h @@ -10,28 +10,27 @@ #include "context.h" struct Window final { + Window(const std::string_view &_title, Context *_context, vk::Extent2D _extent, b8 _full_screen = false); - Window(const std::string_view& _title, Context* _context, vk::Extent2D _extent, b8 _full_screen = false); - - Window(const Window& _other) = delete; - Window(Window&& _other) noexcept; - Window& operator=(const Window& _other) = delete; - Window& operator=(Window&& _other) noexcept; + Window(const Window &_other) = delete; + Window(Window &&_other) noexcept; + Window &operator=(const Window &_other) = delete; + Window &operator=(Window &&_other) noexcept; ~Window(); - bool should_close() const noexcept { + [[nodiscard]] bool should_close() const noexcept { return glfwWindowShouldClose(window); } - bool poll() const noexcept { + [[nodiscard]] bool poll() const noexcept { glfwPollEvents(); return !glfwWindowShouldClose(window); } - void set_window_size(const vk::Extent2D& _extent) noexcept { + void set_window_size(const vk::Extent2D &_extent) noexcept { extent = _extent; - glfwSetWindowSize(window, extent.width, extent.height); + glfwSetWindowSize(window, cast(extent.width), cast(extent.height)); } void set_window_size(const u32 _width, const u32 _height) noexcept { @@ -39,11 +38,9 @@ struct Window final { } // fields - Context* parent_context{}; - - GLFWwindow* window{ nullptr }; - GLFWmonitor* monitor{ nullptr }; - vk::SurfaceKHR surface; + GLFWwindow *window{ nullptr }; + GLFWmonitor *monitor{ nullptr }; + vk::raii::SurfaceKHR surface{ nullptr }; vk::Extent2D extent; std::string name; b8 full_screen{ false };