From dc18a4b2737595016400a6ca6024e7b914738b14 Mon Sep 17 00:00:00 2001 From: kj16609 Date: Thu, 20 Jun 2024 06:51:25 -0400 Subject: [PATCH] Abstracts away vulkan Instance --- src/engine/EngineContext.hpp | 9 + src/engine/FGL_DEFINES.hpp | 9 + src/engine/Window.cpp | 1 - src/engine/rendering/Device.cpp | 223 ++----------------------- src/engine/rendering/Device.hpp | 11 +- src/engine/rendering/Instance.cpp | 263 ++++++++++++++++++++++++++++++ src/engine/rendering/Instance.hpp | 51 ++++++ 7 files changed, 348 insertions(+), 219 deletions(-) create mode 100644 src/engine/rendering/Instance.cpp create mode 100644 src/engine/rendering/Instance.hpp diff --git a/src/engine/EngineContext.hpp b/src/engine/EngineContext.hpp index 347f2cb..ee207a5 100644 --- a/src/engine/EngineContext.hpp +++ b/src/engine/EngineContext.hpp @@ -20,7 +20,16 @@ namespace fgl::engine static constexpr int DEFAULT_WIDTH { 1920 }; static constexpr int DEFAULT_HEIGHT { 1080 }; + vk::raii::Context ctx {}; + + // Window must be prepared *BEFORE* instance is ready in order to make + // glfwGetRequiredInstanceExtensions valid Window m_window { DEFAULT_WIDTH, DEFAULT_HEIGHT, "titor Engine" }; + + Instance m_instance { ctx }; + + Device device { m_window, m_instance }; + Renderer m_renderer { m_window }; //GameObject::Map game_objects {}; diff --git a/src/engine/FGL_DEFINES.hpp b/src/engine/FGL_DEFINES.hpp index bffbe30..844d2c3 100644 --- a/src/engine/FGL_DEFINES.hpp +++ b/src/engine/FGL_DEFINES.hpp @@ -4,6 +4,14 @@ #pragma once +#define FGL_DELETE_DEFAULT_CTOR( ClassName ) ClassName() = delete; +#define FGL_DELETE_COPY_ASSIGN( ClassName ) ClassName& operator=( const ClassName& ) = delete; +#define FGL_DELETE_COPY_CTOR( ClassName ) ClassName( const ClassName& ) = delete; +#define FGL_DELETE_MOVE_ASSIGN( ClassName ) ClassName& operator=( ClassName&& ) = delete; +#define FGL_DELETE_MOVE_CTOR( ClassName ) ClassName( ClassName&& ) = delete; +#define FGL_DELETE_COPY( ClassName ) FGL_DELETE_COPY_CTOR( ClassName ) FGL_DELETE_COPY_ASSIGN( ClassName ) +#define FGL_DELETE_MOVE( ClassName ) FGL_DELETE_MOVE_CTOR( ClassName ) FGL_DELETE_MOVE_ASSIGN( ClassName ) + #ifndef FGL_FORCE_NOTHING #ifdef __GNUC__ @@ -29,6 +37,7 @@ #endif #else + #define FGL_FLATTEN #define FGL_FLATTEN_HOT #define FGL_FORCE_INLINE diff --git a/src/engine/Window.cpp b/src/engine/Window.cpp index abd5541..259bf53 100644 --- a/src/engine/Window.cpp +++ b/src/engine/Window.cpp @@ -19,7 +19,6 @@ namespace fgl::engine m_name( window_name ) { initWindow(); - Device::init( *this ); } Window::~Window() diff --git a/src/engine/rendering/Device.cpp b/src/engine/rendering/Device.cpp index 1b89999..856a2f1 100644 --- a/src/engine/rendering/Device.cpp +++ b/src/engine/rendering/Device.cpp @@ -10,90 +10,10 @@ #include "engine/logging/logging.hpp" -PFN_vkCreateDebugUtilsMessengerEXT pfnVkCreateDebugUtilsMessengerEXT { nullptr }; -PFN_vkDestroyDebugUtilsMessengerEXT pfnVkDestroyDebugUtilsMessengerEXT { nullptr }; -PFN_vkSetDebugUtilsObjectNameEXT pfnVkSetDebugUtilsObjectNameEXT { nullptr }; - -// local callback functions -static VKAPI_ATTR vk::Bool32 VKAPI_CALL debugCallback( - [[maybe_unused]] VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, - [[maybe_unused]] VkDebugUtilsMessageTypeFlagsEXT messageType, - const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, - [[maybe_unused]] void* pUserData ) -{ - using Bits = VkDebugUtilsMessageSeverityFlagBitsEXT; - using namespace fgl::engine; - - if ( pCallbackData->flags & Bits::VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT ) - { - log::info( pCallbackData->pMessage ); - } - else if ( pCallbackData->flags & Bits::VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT ) - { - log::warn( pCallbackData->pMessage ); - } - else if ( pCallbackData->flags & Bits::VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT ) - { - log::error( pCallbackData->pMessage ); - std::abort(); - } - else - { - //log::critical( "Unknown severity message: {}", pCallbackData->pMessage ); - //std::abort(); - } - - return VK_FALSE; -} - -VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugUtilsMessengerEXT( - VkInstance instance, - const VkDebugUtilsMessengerCreateInfoEXT* create_info, - const VkAllocationCallbacks* allocator, - VkDebugUtilsMessengerEXT* messenger ) -{ - return pfnVkCreateDebugUtilsMessengerEXT( instance, create_info, allocator, messenger ); -} - -VKAPI_ATTR void VKAPI_CALL vkDestroyDebugUtilsMessengerEXT( - VkInstance instance, VkDebugUtilsMessengerEXT messenger, VkAllocationCallbacks const * pAllocator ) -{ - return pfnVkDestroyDebugUtilsMessengerEXT( instance, messenger, pAllocator ); -} - -VKAPI_ATTR VkResult VKAPI_CALL - vkSetDebugUtilsObjectNameEXT( VkDevice device, const VkDebugUtilsObjectNameInfoEXT* nameInfo ) -{ - return pfnVkSetDebugUtilsObjectNameEXT( device, nameInfo ); -} - namespace fgl::engine { - vk::Result CreateDebugUtilsMessengerEXT( - vk::Instance instance, - const vk::DebugUtilsMessengerCreateInfoEXT& pCreateInfo, - [[maybe_unused]] const vk::AllocationCallbacks* pAllocator, - vk::DebugUtilsMessengerEXT* pDebugMessenger ) - { - return instance.createDebugUtilsMessengerEXT( &pCreateInfo, pAllocator, pDebugMessenger ); - } - void DestroyDebugUtilsMessengerEXT( - vk::Instance instance, - vk::DebugUtilsMessengerEXT debugMessenger, - [[maybe_unused]] const vk::AllocationCallbacks* pAllocator ) - { - instance.destroyDebugUtilsMessengerEXT( debugMessenger ); - } - - inline static std::unique_ptr< Device > global_device { nullptr }; - - Device& Device::init( Window& window ) - { - global_device = std::make_unique< Device >( window ); - DescriptorPool::init( *global_device ); - return *global_device; - } + Device* global_device { nullptr }; Device& Device::getInstance() { @@ -102,15 +22,19 @@ namespace fgl::engine } // class member functions - Device::Device( Window& window ) + Device::Device( Window& window, Instance& instance ) : m_instance( instance ) { - createInstance(); - setupDebugMessenger(); + assert( !global_device ); + createSurface( window ); pickPhysicalDevice(); createLogicalDevice(); createVMAAllocator(); createCommandPool(); + + global_device = this; + + DescriptorPool::init( *global_device ); } Device::~Device() @@ -118,61 +42,15 @@ namespace fgl::engine vkDestroyCommandPool( m_device, m_commandPool, nullptr ); vkDestroyDevice( m_device, nullptr ); - if ( enableValidationLayers ) - { - DestroyDebugUtilsMessengerEXT( m_instance, m_debugMessenger, nullptr ); - } - vkDestroySurfaceKHR( m_instance, m_surface_khr, nullptr ); vkDestroyInstance( m_instance, nullptr ); } - void Device::createInstance() - { - if ( enableValidationLayers && !checkValidationLayerSupport() ) - { - throw std::runtime_error( "validation layers requested, but not available!" ); - } - - vk::ApplicationInfo appInfo {}; - appInfo.pApplicationName = "Mecha Game"; - appInfo.applicationVersion = VK_MAKE_VERSION( 1, 0, 0 ); - appInfo.pEngineName = "titor"; - appInfo.engineVersion = VK_MAKE_VERSION( 1, 0, 0 ); - appInfo.apiVersion = VK_API_VERSION_1_3; - - vk::InstanceCreateInfo createInfo {}; - createInfo.pApplicationInfo = &appInfo; - - auto extensions { getRequiredInstanceExtensions() }; - assert( extensions.size() >= 1 ); - createInfo.enabledExtensionCount = static_cast< uint32_t >( extensions.size() ); - createInfo.ppEnabledExtensionNames = extensions.data(); - - hasGlfwRequiredInstanceExtensions(); - - vk::DebugUtilsMessengerCreateInfoEXT debugCreateInfo {}; - if ( enableValidationLayers ) - { - createInfo.enabledLayerCount = static_cast< uint32_t >( validationLayers.size() ); - createInfo.ppEnabledLayerNames = validationLayers.data(); - - populateDebugMessengerCreateInfo( debugCreateInfo ); - createInfo.pNext = &debugCreateInfo; - } - else - { - createInfo.enabledLayerCount = 0; - createInfo.pNext = nullptr; - } - - if ( vk::createInstance( &createInfo, nullptr, &m_instance ) != vk::Result::eSuccess ) - throw std::runtime_error( "Failed to create Vulkan instance" ); - } - void Device::pickPhysicalDevice() { - std::vector< vk::PhysicalDevice > devices { m_instance.enumeratePhysicalDevices() }; + std::vector< vk::PhysicalDevice > devices { + static_cast< vk::Instance >( m_instance ).enumeratePhysicalDevices() + }; bool found { false }; @@ -317,57 +195,6 @@ namespace fgl::engine return indices.isComplete() && extensionsSupported && swapChainAdequate && supportedFeatures.samplerAnisotropy; } - void Device::populateDebugMessengerCreateInfo( vk::DebugUtilsMessengerCreateInfoEXT& createInfo ) - { - createInfo.messageSeverity = - vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning | vk::DebugUtilsMessageSeverityFlagBitsEXT::eError; - createInfo.messageType = vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral - | vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation - | vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance; - createInfo.pfnUserCallback = debugCallback; - createInfo.pUserData = nullptr; // Optional - } - - void Device::setupDebugMessenger() - { - std::cout << "Setting up debug messenger: " << std::endl; - - if ( !enableValidationLayers ) - { - std::cout << "-- Validation disabled" << std::endl; - return; - } - - pfnVkCreateDebugUtilsMessengerEXT = reinterpret_cast< - PFN_vkCreateDebugUtilsMessengerEXT >( m_instance.getProcAddr( "vkCreateDebugUtilsMessengerEXT" ) ); - pfnVkDestroyDebugUtilsMessengerEXT = reinterpret_cast< - PFN_vkDestroyDebugUtilsMessengerEXT >( m_instance.getProcAddr( "vkDestroyDebugUtilsMessengerEXT" ) ); - pfnVkSetDebugUtilsObjectNameEXT = - reinterpret_cast< PFN_vkSetDebugUtilsObjectNameEXT >( m_instance - .getProcAddr( "vkSetDebugUtilsObjectNameEXT" ) ); - - if ( !pfnVkCreateDebugUtilsMessengerEXT || !pfnVkDestroyDebugUtilsMessengerEXT ) - { - throw std::runtime_error( "failed to load debug messenger functions!" ); - } - - if ( !pfnVkSetDebugUtilsObjectNameEXT ) - { - throw std::runtime_error( "failed to load debug object name function!" ); - } - - vk::DebugUtilsMessengerCreateInfoEXT createInfo {}; - populateDebugMessengerCreateInfo( createInfo ); - - if ( CreateDebugUtilsMessengerEXT( m_instance, createInfo, nullptr, &m_debugMessenger ) - != vk::Result::eSuccess ) - { - throw std::runtime_error( "failed to set up debug messenger!" ); - } - - std::cout << "-- Debug callback setup" << std::endl; - } - bool Device::checkValidationLayerSupport() { std::vector< vk::LayerProperties > availableLayers { vk::enumerateInstanceLayerProperties() }; @@ -415,34 +242,6 @@ namespace fgl::engine return extensions; } - void Device::hasGlfwRequiredInstanceExtensions() - { - std::vector< vk::ExtensionProperties > instance_extensions { vk::enumerateInstanceExtensionProperties() }; - - std::cout << "available instance instance_extensions:" << std::endl; - std::unordered_set< std::string > available; - for ( const auto& extension : instance_extensions ) - { - std::cout << "\t" << extension.extensionName << std::endl; - available.insert( extension.extensionName ); - } - - std::cout << "required instance instance_extensions:" << std::endl; - auto requiredExtensions { getRequiredInstanceExtensions() }; - for ( const char* required : requiredExtensions ) - { - if ( std::find_if( - instance_extensions.begin(), - instance_extensions.end(), - [ required ]( const vk::ExtensionProperties& prop ) - { return std::strcmp( prop.extensionName, required ); } ) - == instance_extensions.end() ) - throw std::runtime_error( "Missing required glfw extension" ); - else - std::cout << required << std::endl; - } - } - bool Device::checkDeviceExtensionSupport( vk::PhysicalDevice device ) { const std::vector< vk::ExtensionProperties > availableExtensions { diff --git a/src/engine/rendering/Device.hpp b/src/engine/rendering/Device.hpp index 0d4558e..113ab87 100644 --- a/src/engine/rendering/Device.hpp +++ b/src/engine/rendering/Device.hpp @@ -6,6 +6,7 @@ #include #include +#include "Instance.hpp" #include "engine/Window.hpp" #include "engine/concepts/is_suballocation.hpp" #include "vma/vma_impl.hpp" @@ -32,8 +33,8 @@ namespace fgl::engine class Device { - vk::Instance m_instance { VK_NULL_HANDLE }; - vk::DebugUtilsMessengerEXT m_debugMessenger { VK_NULL_HANDLE }; + Instance& m_instance; + vk::PhysicalDevice m_physical_device { VK_NULL_HANDLE }; vk::CommandPool m_commandPool { VK_NULL_HANDLE }; @@ -59,7 +60,8 @@ namespace fgl::engine vk::PhysicalDeviceProperties m_properties {}; - static Device& init( Window& window ); + Device( Window& window, Instance& ); + static Device& getInstance(); template < typename Dst, typename Src > @@ -83,7 +85,6 @@ namespace fgl::engine private: - void createInstance(); void setupDebugMessenger(); void createSurface( Window& window ); void pickPhysicalDevice(); @@ -96,8 +97,6 @@ namespace fgl::engine std::vector< const char* > getRequiredInstanceExtensions(); bool checkValidationLayerSupport(); QueueFamilyIndices findQueueFamilies( vk::PhysicalDevice device ); - void populateDebugMessengerCreateInfo( vk::DebugUtilsMessengerCreateInfoEXT& createInfo ); - void hasGlfwRequiredInstanceExtensions(); bool checkDeviceExtensionSupport( vk::PhysicalDevice device ); SwapChainSupportDetails querySwapChainSupport( vk::PhysicalDevice device ); diff --git a/src/engine/rendering/Instance.cpp b/src/engine/rendering/Instance.cpp new file mode 100644 index 0000000..f9cc8ed --- /dev/null +++ b/src/engine/rendering/Instance.cpp @@ -0,0 +1,263 @@ +// +// Created by kj16609 on 6/20/24. +// + +#include "Instance.hpp" + +#include + +#include + +#include "engine/logging/logging.hpp" + +PFN_vkCreateDebugUtilsMessengerEXT pfnVkCreateDebugUtilsMessengerEXT { nullptr }; +PFN_vkDestroyDebugUtilsMessengerEXT pfnVkDestroyDebugUtilsMessengerEXT { nullptr }; +PFN_vkSetDebugUtilsObjectNameEXT pfnVkSetDebugUtilsObjectNameEXT { nullptr }; + +// Callback function for vulkan messaging. +static VKAPI_ATTR vk::Bool32 VKAPI_CALL debugCallback( + [[maybe_unused]] VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + [[maybe_unused]] VkDebugUtilsMessageTypeFlagsEXT messageType, + const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, + [[maybe_unused]] void* pUserData ) +{ + using Bits = VkDebugUtilsMessageSeverityFlagBitsEXT; + using namespace fgl::engine; + + if ( pCallbackData->flags & Bits::VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT ) + { + log::info( pCallbackData->pMessage ); + } + else if ( pCallbackData->flags & Bits::VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT ) + { + log::warn( pCallbackData->pMessage ); + } + else if ( pCallbackData->flags & Bits::VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT ) + { + log::error( pCallbackData->pMessage ); + std::abort(); + } + else + { + //log::critical( "Unknown severity message: {}", pCallbackData->pMessage ); + //std::abort(); + } + + return VK_FALSE; +} + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugUtilsMessengerEXT( + VkInstance instance, + const VkDebugUtilsMessengerCreateInfoEXT* create_info, + const VkAllocationCallbacks* allocator, + VkDebugUtilsMessengerEXT* messenger ) +{ + assert( pfnVkCreateDebugUtilsMessengerEXT ); + return pfnVkCreateDebugUtilsMessengerEXT( instance, create_info, allocator, messenger ); +} + +VKAPI_ATTR void VKAPI_CALL vkDestroyDebugUtilsMessengerEXT( + VkInstance instance, VkDebugUtilsMessengerEXT messenger, VkAllocationCallbacks const * pAllocator ) +{ + assert( pfnVkDestroyDebugUtilsMessengerEXT ); + return pfnVkDestroyDebugUtilsMessengerEXT( instance, messenger, pAllocator ); +} + +VKAPI_ATTR VkResult VKAPI_CALL + vkSetDebugUtilsObjectNameEXT( VkDevice device, const VkDebugUtilsObjectNameInfoEXT* nameInfo ) +{ + assert( pfnVkSetDebugUtilsObjectNameEXT ); + return pfnVkSetDebugUtilsObjectNameEXT( device, nameInfo ); +} + +namespace fgl::engine +{ + vk::Result CreateDebugUtilsMessengerEXT( + vk::Instance instance, + const vk::DebugUtilsMessengerCreateInfoEXT& pCreateInfo, + [[maybe_unused]] const vk::AllocationCallbacks* pAllocator, + vk::DebugUtilsMessengerEXT* pDebugMessenger ) + { + return instance.createDebugUtilsMessengerEXT( &pCreateInfo, pAllocator, pDebugMessenger ); + } + + void DestroyDebugUtilsMessengerEXT( + vk::Instance instance, + vk::DebugUtilsMessengerEXT debugMessenger, + [[maybe_unused]] const vk::AllocationCallbacks* pAllocator ) + { + instance.destroyDebugUtilsMessengerEXT( debugMessenger ); + } + + vk::ApplicationInfo Instance::appInfo() + { + vk::ApplicationInfo info {}; + info.pApplicationName = "Mecha Game"; + info.applicationVersion = VK_MAKE_VERSION( 1, 0, 0 ); + + info.pEngineName = "titor"; + info.engineVersion = VK_MAKE_VERSION( 1, 0, 0 ); + + info.apiVersion = VK_API_VERSION_1_3; + + return info; + } + + vk::InstanceCreateInfo Instance:: + createInfo( vk::ApplicationInfo* app_info, vk::DebugUtilsMessengerCreateInfoEXT* msger_info ) + { + vk::InstanceCreateInfo info {}; + info.pApplicationInfo = app_info; + + assert( m_required_extensions.size() >= 1 ); + info.enabledExtensionCount = static_cast< uint32_t >( m_required_extensions.size() ); + info.ppEnabledExtensionNames = m_required_extensions.data(); + + verifyGlfwExtensions(); + + const static std::vector< const char* > validationLayers { "VK_LAYER_KHRONOS_validation" }; + + if ( ENABLE_VALIDATION_LAYERS ) + { + info.enabledLayerCount = static_cast< uint32_t >( validationLayers.size() ); + info.ppEnabledLayerNames = validationLayers.data(); + + info.pNext = msger_info; + } + else + { + info.enabledLayerCount = 0; + info.pNext = nullptr; + } + + return info; + } + + std::vector< const char* > Instance::getRequiredInstanceExtensions() + { + uint32_t glfwExtensionCount = 0; + const char** glfwExtensions { glfwGetRequiredInstanceExtensions( &glfwExtensionCount ) }; + + if ( glfwExtensions == nullptr ) throw std::runtime_error( "Failed to get required extensions from glfw" ); + + std::vector< const char* > extensions( glfwExtensions, glfwExtensions + glfwExtensionCount ); + + // "VK_KHR_surface" is guaranteed to be in this list + assert( extensions.size() >= 1 ); + + if ( ENABLE_VALIDATION_LAYERS ) + { + extensions.push_back( VK_EXT_DEBUG_UTILS_EXTENSION_NAME ); + } + + return extensions; + } + + vk::DebugUtilsMessengerCreateInfoEXT Instance::createDebugMessengerInfo() + { + vk::DebugUtilsMessengerCreateInfoEXT create_info {}; + create_info.messageSeverity = + vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning | vk::DebugUtilsMessageSeverityFlagBitsEXT::eError; + create_info.messageType = vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral + | vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation + | vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance; + create_info.pfnUserCallback = debugCallback; + create_info.pUserData = nullptr; // Optional + + return create_info; + } + + void Instance::verifyGlfwExtensions() + { + std::vector< vk::ExtensionProperties > instance_extensions { vk::enumerateInstanceExtensionProperties() }; + + std::cout << "available instance instance_extensions:" << std::endl; + std::unordered_set< std::string > available {}; + //Get list of all available instance extensions + for ( const auto& extension : instance_extensions ) + { + std::cout << "\t" << extension.extensionName << std::endl; + available.insert( extension.extensionName ); + } + + std::cout << "required instance instance_extensions:" << std::endl; + //Get the list of the required extensions + + auto requiredExtensions { getRequiredInstanceExtensions() }; + for ( const char* required : requiredExtensions ) + { + if ( std::find_if( + instance_extensions.begin(), + instance_extensions.end(), + [ required ]( const vk::ExtensionProperties& prop ) + { return std::strcmp( prop.extensionName, required ); } ) + == instance_extensions.end() ) + { + log::critical( "Failed to find required extention: {}", std::string_view( required ) ); + throw std::runtime_error( "Failed to find required extention: " ); + } + else + std::cout << required << std::endl; + } + } + + void Instance::setupDebugMessenger() + { + if ( !ENABLE_VALIDATION_LAYERS ) + { + log::info( "Validation disabled. Skipping debug messenger" ); + return; + } + + log::info( "Setting up debug messenger" ); + + pfnVkCreateDebugUtilsMessengerEXT = reinterpret_cast< + PFN_vkCreateDebugUtilsMessengerEXT >( m_instance.getProcAddr( "vkCreateDebugUtilsMessengerEXT" ) ); + pfnVkDestroyDebugUtilsMessengerEXT = reinterpret_cast< + PFN_vkDestroyDebugUtilsMessengerEXT >( m_instance.getProcAddr( "vkDestroyDebugUtilsMessengerEXT" ) ); + pfnVkSetDebugUtilsObjectNameEXT = + reinterpret_cast< PFN_vkSetDebugUtilsObjectNameEXT >( m_instance + .getProcAddr( "vkSetDebugUtilsObjectNameEXT" ) ); + + if ( !pfnVkCreateDebugUtilsMessengerEXT || !pfnVkDestroyDebugUtilsMessengerEXT ) + { + log::critical( + "Failed to load create/destroy messenger functions pfnVkCreateDebugUtilsMessengerEXT/pfnVkDestroyDebugUtilsMessengerEXT" ); + throw std::runtime_error( "failed to load debug messenger functions!" ); + } + + if ( !pfnVkSetDebugUtilsObjectNameEXT ) + { + log::critical( "Failed to load debug object naming function: pfnVkSetDebugUtilsObjectNameEXT" ); + throw std::runtime_error( "failed to load debug object name function!" ); + } + + if ( CreateDebugUtilsMessengerEXT( m_instance, m_debug_info, nullptr, &m_debug_messenger ) + != vk::Result::eSuccess ) + { + throw std::runtime_error( "failed to set up debug messenger!" ); + } + + log::info( "Debug callback setup" ); + } + + Instance::Instance( vk::raii::Context& ctx ) : + m_app_info( appInfo() ), + m_debug_info( createDebugMessengerInfo() ), + m_required_extensions( getRequiredInstanceExtensions() ), + m_instance_info( createInfo( &m_app_info, &m_debug_info ) ), + m_instance( ctx, m_instance_info ) + { + //Post setup. + setupDebugMessenger(); + } + + Instance::~Instance() + { + if ( ENABLE_VALIDATION_LAYERS ) + { + DestroyDebugUtilsMessengerEXT( m_instance, m_debug_messenger, nullptr ); + } + } + +} // namespace fgl::engine diff --git a/src/engine/rendering/Instance.hpp b/src/engine/rendering/Instance.hpp new file mode 100644 index 0000000..c50c5f7 --- /dev/null +++ b/src/engine/rendering/Instance.hpp @@ -0,0 +1,51 @@ +// +// Created by kj16609 on 6/20/24. +// + +#pragma once + +#include + +#include "engine/FGL_DEFINES.hpp" + +namespace fgl::engine +{ + class Instance + { + static constexpr bool ENABLE_VALIDATION_LAYERS { true }; + + vk::ApplicationInfo m_app_info; + vk::DebugUtilsMessengerCreateInfoEXT m_debug_info; + std::vector< const char* > m_required_extensions; + vk::InstanceCreateInfo m_instance_info; + + vk::raii::Instance m_instance; + + vk::DebugUtilsMessengerEXT m_debug_messenger { VK_NULL_HANDLE }; + + vk::ApplicationInfo appInfo(); + vk::DebugUtilsMessengerCreateInfoEXT createDebugMessengerInfo(); + vk::InstanceCreateInfo + createInfo( vk::ApplicationInfo* info, vk::DebugUtilsMessengerCreateInfoEXT* msger_info ); + + std::vector< const char* > getRequiredInstanceExtensions(); + + void verifyGlfwExtensions(); + + void setupDebugMessenger(); + + public: + + FGL_DELETE_DEFAULT_CTOR( Instance ) + FGL_DELETE_COPY( Instance ) + FGL_DELETE_MOVE( Instance ) + + Instance( vk::raii::Context& ctx ); + + ~Instance(); + + inline operator vk::Instance() { return m_instance; } + + inline operator VkInstance() { return *m_instance; } + }; +} // namespace fgl::engine \ No newline at end of file