diff --git a/engine/src/engine/vulkanapi/backend.cpp b/engine/src/engine/vulkanapi/backend.cpp index a5213d7..fafe7b4 100644 --- a/engine/src/engine/vulkanapi/backend.cpp +++ b/engine/src/engine/vulkanapi/backend.cpp @@ -4,7 +4,7 @@ namespace vulkanapi { Backend::Backend(const char* appName, int deviceIndex) { - auto instanceCreator = Instance::InstanceCreator(); + auto instanceCreator = InstanceCreator(); mInstance = new Instance(instanceCreator); std::vector available_devices; mInstance->EnumerateAvailablePhysicalDevices(available_devices); diff --git a/engine/src/engine/vulkanapi/backend.h b/engine/src/engine/vulkanapi/backend.h index 40e93a7..1dd4087 100644 --- a/engine/src/engine/vulkanapi/backend.h +++ b/engine/src/engine/vulkanapi/backend.h @@ -2,6 +2,7 @@ #include #include #include "wrapper/instance.h" +#include "wrapper/instance_creator.h" #include "wrapper/device.h" namespace vulkanapi { class Backend{ diff --git a/engine/src/engine/vulkanapi/wrapper/instance.cpp b/engine/src/engine/vulkanapi/wrapper/instance.cpp index ea35b20..80b574a 100644 --- a/engine/src/engine/vulkanapi/wrapper/instance.cpp +++ b/engine/src/engine/vulkanapi/wrapper/instance.cpp @@ -1,39 +1,17 @@ #include "instance.h" -#include "instance_help.h" +#include "instance_creator.h" +#include "zlog.h" namespace vulkanapi { - Instance::InstanceCreator::InstanceCreator() - : appName("Vulkan Application") - , appVersion(VK_MAKE_VERSION(1, 0, 0)) - , engineName("No Engine") - , engineVersion(VK_MAKE_VERSION(1, 0, 0)) - , apiVersion(VK_API_VERSION_1_0) -#ifdef _USE_GRAPHIC_DEBUG - , messageSeverity(VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) - , messageType(VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) - // , debugCallback(Instance::DebugCallback) -#endif - { - } - Instance::InstanceCreator::~InstanceCreator() - { - } - void Instance::InstanceCreator::AddExtension(std::string extensionName) - { - } - void Instance::InstanceCreator::AddLayer(std::string layerName) - { - } - Instance::Instance(InstanceCreator& Creator) { //加载dll LIBRARY_TYPE vulkan_library; - ConnectWithVulkanLoaderLibrary(vulkan_library); + InstanceCreator::ConnectWithVulkanLoaderLibrary(vulkan_library); //加载vulkan接口 - LoadFunctionExportedFromVulkanLoaderLibrary(vulkan_library); + InstanceCreator::LoadFunctionExportedFromVulkanLoaderLibrary(vulkan_library); //调用vulkan接口,加载全局函数指针 - LoadGlobalLevelFunctions(); + InstanceCreator::LoadGlobalLevelFunctions(); VkApplicationInfo application_info = { VK_STRUCTURE_TYPE_APPLICATION_INFO, // VkStructureType sType nullptr, // const void * pNext @@ -43,12 +21,12 @@ namespace vulkanapi { Creator.engineVersion, // uint32_t engineVersion Creator.apiVersion // uint32_t apiVersion }; - auto extensions = _EnabledExtensionNames(Creator._desiredExtensions); - auto layers = _EnabledLayerNames(Creator._desiredLayers); - VkDebugUtilsMessengerCreateInfoEXT createInfo = _DebugUtilsLayerNext(); + auto extensions = Creator.EnabledExtensionNames(); + auto layers = Creator.EnabledLayerNames(); + //VkDebugUtilsMessengerCreateInfoEXT createInfo = _DebugUtilsLayerNext(); VkInstanceCreateInfo instance_create_info = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // VkStructureType sType - &createInfo, // const void * pNext + nullptr, // const void * pNext 0, // VkInstanceCreateFlags flags &application_info, // const VkApplicationInfo * pApplicationInfo static_cast(layers.size()), // uint32_t enabledLayerCount @@ -62,7 +40,7 @@ namespace vulkanapi { } //调用vulkan接口,加载实例函数指针 - LoadInstanceLevelFunctions(mPtr, extensions); + InstanceCreator::LoadInstanceLevelFunctions(mPtr, extensions); } bool Instance::EnumerateAvailablePhysicalDevices(std::vector& available_devices) { diff --git a/engine/src/engine/vulkanapi/wrapper/instance.h b/engine/src/engine/vulkanapi/wrapper/instance.h index e8853f4..87d13a7 100644 --- a/engine/src/engine/vulkanapi/wrapper/instance.h +++ b/engine/src/engine/vulkanapi/wrapper/instance.h @@ -4,31 +4,9 @@ #include "../vulkan.h" namespace vulkanapi { + class InstanceCreator; class Instance{ - public: - class InstanceCreator { - friend class Instance; - public: - std::string appName; - uint32_t appVersion; - std::string engineName; - uint32_t engineVersion; - uint32_t apiVersion; -#ifdef _USE_GRAPHIC_DEBUG - VkDebugUtilsMessageSeverityFlagsEXT messageSeverity; - VkDebugUtilsMessageTypeFlagsEXT messageType; - PFN_vkDebugUtilsMessengerCallbackEXT debugCallback; -#endif - private: - std::vector _desiredExtensions; - std::vector _desiredLayers; - - public: - InstanceCreator(); - ~InstanceCreator(); - void AddExtension(std::string extensionName); - void AddLayer(std::string layerName); - }; + friend class InstanceCreator; protected: VkInstance mPtr; public: diff --git a/engine/src/engine/vulkanapi/wrapper/instance_creator.cpp b/engine/src/engine/vulkanapi/wrapper/instance_creator.cpp new file mode 100644 index 0000000..fd4bba6 --- /dev/null +++ b/engine/src/engine/vulkanapi/wrapper/instance_creator.cpp @@ -0,0 +1,199 @@ +#pragma once +#include "instance.h" +#include "instance_creator.h" +#include +#include +#include +#include "zlog.h" +namespace vulkanapi { + InstanceCreator::InstanceCreator() + : appName("Vulkan Application") + , appVersion(VK_MAKE_VERSION(1, 0, 0)) + , engineName("No Engine") + , engineVersion(VK_MAKE_VERSION(1, 0, 0)) + , apiVersion(VK_API_VERSION_1_0) +#ifdef _USE_GRAPHIC_DEBUG + , messageSeverity(VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) + , messageType(VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) + // , debugCallback(Instance::DebugCallback) +#endif + { + + } + void InstanceCreator::AddExtension(std::string extensionName) + { + desiredExtensions.push_back(extensionName); + } + void InstanceCreator::AddLayer(std::string layerName) + { + desiredLayers.push_back(layerName); + } + std::vector InstanceCreator::EnabledExtensionNames() + { + std::vector available_extensions; + std::vector _extension; + if (!CheckAvailableInstanceExtensions(available_extensions)) { + return _extension; + } + for (int i = 0, l = desiredExtensions.size(); i < l; i++) { + if (IsExtensionSupported(available_extensions, desiredExtensions[i].c_str())) { + _extension.push_back(desiredExtensions[i].c_str()); + } + else { + zlog::error("cann't support extension: {}", desiredExtensions[i].c_str()); + } + } + return _extension; + } + + std::vector InstanceCreator::EnabledLayerNames() + { + std::vector available_layers; + std::vector _layers; + if (!CheckAvailableInstanceLayers(available_layers)) { + return _layers; + } + for (int i = 0, l = desiredLayers.size(); i < l; i++) { + if (IsLayerSupported(available_layers, desiredLayers[i].c_str())) { + _layers.push_back(desiredLayers[i].c_str()); + } + else { + zlog::error("Could not load instance-level Vulkan function named: {}", desiredLayers[i].c_str()); + } + } + return _layers; + } + + + bool InstanceCreator::CheckAvailableInstanceExtensions(std::vector& available_extensions) + { + uint32_t extensions_count = 0; + VkResult result = VK_SUCCESS; + + result = vkEnumerateInstanceExtensionProperties(nullptr, &extensions_count, nullptr); + if ((result != VK_SUCCESS) || + (extensions_count == 0)) { + zlog::error("Could not get the number of instance extensions."); + return false; + } + + available_extensions.resize(extensions_count); + result = vkEnumerateInstanceExtensionProperties(nullptr, &extensions_count, available_extensions.data()); + if ((result != VK_SUCCESS) || + (extensions_count == 0)) { + zlog::error("Could not enumerate instance extensions."); + return false; + } + return true; + } + + bool InstanceCreator::CheckAvailableInstanceLayers(std::vector& available_layers) + { + uint32_t extensions_count = 0; + VkResult result = VK_SUCCESS; + + result = vkEnumerateInstanceLayerProperties(&extensions_count, nullptr); + if ((result != VK_SUCCESS) || + (extensions_count == 0)) { + zlog::error("Could not get the number of instance layers."); + return false; + } + + available_layers.resize(extensions_count); + result = vkEnumerateInstanceLayerProperties(&extensions_count, available_layers.data()); + if ((result != VK_SUCCESS) || + (extensions_count == 0)) { + zlog::error("Could not enumerate instance layers."); + return false; + } + + return true; + } + + bool InstanceCreator::IsExtensionSupported(std::vector const& available_extensions, char const* const extension) + { + for (auto& available_extension : available_extensions) { + if (strstr(available_extension.extensionName, extension)) { + return true; + } + } + return false; + } + + bool InstanceCreator::IsLayerSupported(std::vector const& available_layers, char const* const layer) + { + for (auto& available_layer : available_layers) { + if (strstr(available_layer.layerName, layer)) { + return true; + } + } + return false; + } + + bool InstanceCreator::ConnectWithVulkanLoaderLibrary(LIBRARY_TYPE& vulkan_library) + { +#if defined _WIN32 + vulkan_library = LoadLibrary("vulkan-1.dll"); +#elif defined __linux + vulkan_library = dlopen("libvulkan.so.1", RTLD_NOW); +#endif + if (vulkan_library == nullptr) { + zlog::error("Could not connect with a Vulkan Runtime library."); + return false; + } + return true; + } + bool InstanceCreator::LoadFunctionExportedFromVulkanLoaderLibrary(LIBRARY_TYPE const& vulkan_library) + { +#if defined _WIN32 +#define LoadFunction GetProcAddress +#elif defined __linux +#define LoadFunction dlsym +#endif + +#define EXPORTED_VULKAN_FUNCTION( name ) \ + name = (PFN_##name)LoadFunction( vulkan_library, #name ); \ + if( name == nullptr ) { \ + zlog::error( "Could not load exported Vulkan function named:"#name);\ + return false; \ + } +#include "../vulkan_function_list.inl" + return true; + } + bool InstanceCreator::LoadGlobalLevelFunctions() { +#define GLOBAL_LEVEL_VULKAN_FUNCTION( name ) \ + name = (PFN_##name)vkGetInstanceProcAddr( nullptr, #name ); \ + if( name == nullptr ) { \ + zlog::error( "Could not load global level Vulkan function named:"#name);\ + return false; \ + } +#include "../vulkan_function_list.inl" + return true; + } + + bool InstanceCreator::LoadInstanceLevelFunctions(VkInstance instance, std::vector const& enabled_extensions) + { + // Load core Vulkan API instance-level functions +#define INSTANCE_LEVEL_VULKAN_FUNCTION( name ) \ + name = (PFN_##name)vkGetInstanceProcAddr( instance, #name ); \ + if( name == nullptr ) { \ + zlog::error( "Could not load instance-level Vulkan function named:"#name);\ + return false; \ + } + + // Load instance-level functions from enabled extensions +#define INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION( name, extension ) \ + for( auto & enabled_extension : enabled_extensions ) { \ + if( std::string( enabled_extension ) == std::string( extension ) ) { \ + name = (PFN_##name)vkGetInstanceProcAddr( instance, #name ); \ + if( name == nullptr ) { \ + zlog::error( "Could not load instance-level Vulkan function named:"#name);\ + return false; \ + } \ + } \ + } +#include "../vulkan_function_list.inl" + return true; + } + +}; \ No newline at end of file diff --git a/engine/src/engine/vulkanapi/wrapper/instance_creator.h b/engine/src/engine/vulkanapi/wrapper/instance_creator.h new file mode 100644 index 0000000..799363a --- /dev/null +++ b/engine/src/engine/vulkanapi/wrapper/instance_creator.h @@ -0,0 +1,47 @@ +#pragma once +#include +#include +#include "../vulkan.h" + +namespace vulkanapi { + class Instance; + class InstanceCreator { + friend class Instance; + public: + std::string appName; + uint32_t appVersion; + std::string engineName; + uint32_t engineVersion; + uint32_t apiVersion; + + std::vector desiredExtensions; + std::vector desiredLayers; + public: + InstanceCreator(); + void AddExtension(std::string extensionName); + void AddLayer(std::string layerName); + + std::vector EnabledExtensionNames(); + std::vector EnabledLayerNames(); + public: +#ifdef _USE_GRAPHIC_DEBUG + VkDebugUtilsMessageSeverityFlagsEXT messageSeverity; + VkDebugUtilsMessageTypeFlagsEXT messageType; + PFN_vkDebugUtilsMessengerCallbackEXT debugCallback; +#endif + + private: + static bool CheckAvailableInstanceExtensions(std::vector& available_extensions); + static bool CheckAvailableInstanceLayers(std::vector& available_layers); + static bool IsExtensionSupported(std::vector const& available_extensions, + char const* const extension); + static bool IsLayerSupported(std::vector const& available_layers, + char const* const layer); + private: + static bool ConnectWithVulkanLoaderLibrary(LIBRARY_TYPE& vulkan_library); + static bool LoadFunctionExportedFromVulkanLoaderLibrary(LIBRARY_TYPE const& vulkan_library); + static bool LoadGlobalLevelFunctions(); + static bool LoadInstanceLevelFunctions(VkInstance instance, + std::vector const& enabled_extensions); + }; +}; \ No newline at end of file