Move to vulkan raii.

Vulkan RAII is new, but it helps manage a multi-device environment
without the additional context-tracking.
This commit is contained in:
Anish Bhobe 2024-06-12 16:21:44 +02:00
parent e9da60c056
commit cd8ab16ad2
7 changed files with 73 additions and 86 deletions

View File

@ -1,18 +1,15 @@
#include <iostream>
#include "constants.h"
#include "glfw_context.h"
#include "window.h"
#include <iostream>
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 });
delete window;
delete context;
delete glfw;
while (window.poll()) {
}
return 0;
}

View File

@ -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)

View File

@ -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<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr");
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr);
tie(result, instance) = vk::createInstance({
try {
instance = vk::raii::Instance{ raii_context, {
.pNext = enable_validation_layers ? &debug_messenger_create_info : nullptr,
.pApplicationInfo = &app_info,
.enabledLayerCount = enable_validation_layers ? cast<u32>(validation_layers.size()) : 0,
.ppEnabledLayerNames = enable_validation_layers ? validation_layers.data() : nullptr,
.enabledExtensionCount = cast<u32>(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);
} };
} 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;

View File

@ -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);

View File

@ -15,8 +15,8 @@
#include <string>
#define VULKAN_HPP_ASSERT(expr) DEBUG_IF(!(expr), "Vulkan assert failed")
#include <vulkan/vulkan.hpp>
#include <vk_mem_alloc.h>
#include <vulkan/vulkan_raii.hpp>
#define CODE_LOC " @ " __FILE__ ":" VULKAN_HPP_STRINGIFY(__LINE__)
[[nodiscard]] inline bool failed(const vk::Result _result) {

View File

@ -4,16 +4,13 @@
// =============================================
#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");
@ -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<i32>(extent.width), cast<i32>(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<i32>(w_ - extent.width) / 2, cast<i32>(h_ - extent.height) / 2);
}
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
VkSurfaceKHR surface_;
auto result = cast<vk::Result>(glfwCreateWindowSurface(cast<VkInstance>(_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<vk::Result>(glfwCreateWindowSurface(cast<VkInstance>(*_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;

View File

@ -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<i32>(extent.width), cast<i32>(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 };