Abstracts away vulkan Instance
This commit is contained in:
@@ -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 {};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -19,7 +19,6 @@ namespace fgl::engine
|
||||
m_name( window_name )
|
||||
{
|
||||
initWindow();
|
||||
Device::init( *this );
|
||||
}
|
||||
|
||||
Window::~Window()
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#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 );
|
||||
|
||||
|
||||
263
src/engine/rendering/Instance.cpp
Normal file
263
src/engine/rendering/Instance.cpp
Normal file
@@ -0,0 +1,263 @@
|
||||
//
|
||||
// Created by kj16609 on 6/20/24.
|
||||
//
|
||||
|
||||
#include "Instance.hpp"
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
#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
|
||||
51
src/engine/rendering/Instance.hpp
Normal file
51
src/engine/rendering/Instance.hpp
Normal file
@@ -0,0 +1,51 @@
|
||||
//
|
||||
// Created by kj16609 on 6/20/24.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vulkan/vulkan_raii.hpp>
|
||||
|
||||
#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
|
||||
Reference in New Issue
Block a user