instance creator

This commit is contained in:
ouczbs 2024-02-29 18:57:36 +08:00
parent 9192d2bfe7
commit 9d4a55ddbc
6 changed files with 260 additions and 57 deletions

View File

@ -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<VkPhysicalDevice> available_devices;
mInstance->EnumerateAvailablePhysicalDevices(available_devices);

View File

@ -2,6 +2,7 @@
#include <string>
#include <vector>
#include "wrapper/instance.h"
#include "wrapper/instance_creator.h"
#include "wrapper/device.h"
namespace vulkanapi {
class Backend{

View File

@ -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<uint32_t>(layers.size()), // uint32_t enabledLayerCount
@ -62,7 +40,7 @@ namespace vulkanapi {
}
//调用vulkan接口加载实例函数指针
LoadInstanceLevelFunctions(mPtr, extensions);
InstanceCreator::LoadInstanceLevelFunctions(mPtr, extensions);
}
bool Instance::EnumerateAvailablePhysicalDevices(std::vector<VkPhysicalDevice>& available_devices)
{

View File

@ -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<std::string> _desiredExtensions;
std::vector<std::string> _desiredLayers;
public:
InstanceCreator();
~InstanceCreator();
void AddExtension(std::string extensionName);
void AddLayer(std::string layerName);
};
friend class InstanceCreator;
protected:
VkInstance mPtr;
public:

View File

@ -0,0 +1,199 @@
#pragma once
#include "instance.h"
#include "instance_creator.h"
#include <string>
#include <iostream>
#include <vector>
#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<char const*> InstanceCreator::EnabledExtensionNames()
{
std::vector<VkExtensionProperties> available_extensions;
std::vector<char const*> _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<char const*> InstanceCreator::EnabledLayerNames()
{
std::vector<VkLayerProperties> available_layers;
std::vector<char const*> _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<VkExtensionProperties>& 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<VkLayerProperties>& 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<VkExtensionProperties> 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<VkLayerProperties> 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<char const*> 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;
}
};

View File

@ -0,0 +1,47 @@
#pragma once
#include <string>
#include <vector>
#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<std::string> desiredExtensions;
std::vector<std::string> desiredLayers;
public:
InstanceCreator();
void AddExtension(std::string extensionName);
void AddLayer(std::string layerName);
std::vector<char const*> EnabledExtensionNames();
std::vector<char const*> EnabledLayerNames();
public:
#ifdef _USE_GRAPHIC_DEBUG
VkDebugUtilsMessageSeverityFlagsEXT messageSeverity;
VkDebugUtilsMessageTypeFlagsEXT messageType;
PFN_vkDebugUtilsMessengerCallbackEXT debugCallback;
#endif
private:
static bool CheckAvailableInstanceExtensions(std::vector<VkExtensionProperties>& available_extensions);
static bool CheckAvailableInstanceLayers(std::vector<VkLayerProperties>& available_layers);
static bool IsExtensionSupported(std::vector<VkExtensionProperties> const& available_extensions,
char const* const extension);
static bool IsLayerSupported(std::vector<VkLayerProperties> 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<char const*> const& enabled_extensions);
};
};