VulkanInstance
This commit is contained in:
+43
@@ -0,0 +1,43 @@
|
|||||||
|
/*********************************************************************
|
||||||
|
* \file GraphicsInstance.hpp
|
||||||
|
*
|
||||||
|
* \author Romain BOULLARD
|
||||||
|
* \date September 2026
|
||||||
|
*********************************************************************/
|
||||||
|
#ifndef BIGFOOT_GRAPHICSINTERFACE_GRAPHICSINSTANCE_HPP
|
||||||
|
#define BIGFOOT_GRAPHICSINTERFACE_GRAPHICSINSTANCE_HPP
|
||||||
|
#include <Utils/Factory.hpp>
|
||||||
|
#include <Utils/Version.hpp>
|
||||||
|
|
||||||
|
#include <GraphicsInterface/GraphicsAPI_generated.hpp>
|
||||||
|
|
||||||
|
#include <EASTL/functional.h>
|
||||||
|
#include <EASTL/string_view.h>
|
||||||
|
#include <EASTL/unique_ptr.h>
|
||||||
|
|
||||||
|
namespace Bigfoot
|
||||||
|
{
|
||||||
|
class GraphicsInstance
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~GraphicsInstance() = default;
|
||||||
|
|
||||||
|
GraphicsInstance(const GraphicsInstance& p_instance) = delete;
|
||||||
|
GraphicsInstance(GraphicsInstance&& p_instance) = delete;
|
||||||
|
|
||||||
|
GraphicsInstance& operator=(const GraphicsInstance& p_instance) = delete;
|
||||||
|
GraphicsInstance& operator=(GraphicsInstance&& p_instance) = delete;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
GraphicsInstance() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
/****************************************************************************************/
|
||||||
|
|
||||||
|
using GraphicsInstanceFactory =
|
||||||
|
Factory<GraphicsInstance,
|
||||||
|
GraphicsAPI,
|
||||||
|
eastl::function<eastl::unique_ptr<GraphicsInstance>(eastl::string_view, Version)>>;
|
||||||
|
} // namespace Bigfoot
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -7,7 +7,8 @@ set(PublicDependencies
|
|||||||
set(PrivateDependencies)
|
set(PrivateDependencies)
|
||||||
set(BigfootPublicDependencies
|
set(BigfootPublicDependencies
|
||||||
GraphicsInterface)
|
GraphicsInterface)
|
||||||
set(BigfootPrivateDependencies)
|
set(BigfootPrivateDependencies
|
||||||
|
Engine)
|
||||||
|
|
||||||
bigfoot_create_package_lib(
|
bigfoot_create_package_lib(
|
||||||
"${PublicDependencies}"
|
"${PublicDependencies}"
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
/*********************************************************************
|
||||||
|
* \file VulkanInclude.hpp
|
||||||
|
*
|
||||||
|
* \author Romain BOULLARD
|
||||||
|
* \date September 2026
|
||||||
|
*********************************************************************/
|
||||||
|
#ifndef BIGFOOT_GRAPHICSVULKAN_VULKANINCLUDE_HPP
|
||||||
|
#define BIGFOOT_GRAPHICSVULKAN_VULKANINCLUDE_HPP
|
||||||
|
#define VULKAN_HPP_ASSERT(result)
|
||||||
|
#define VULKAN_HPP_ASSERT_ON_RESULT(result)
|
||||||
|
#include <vulkan/vulkan.hpp>
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/*********************************************************************
|
||||||
|
* \file VulkanInstance.hpp
|
||||||
|
*
|
||||||
|
* \author Romain BOULLARD
|
||||||
|
* \date September 2026
|
||||||
|
*********************************************************************/
|
||||||
|
#ifndef BIGFOOT_GRAPHICSVULKAN_VULKANINSTANCE_HPP
|
||||||
|
#define BIGFOOT_GRAPHICSVULKAN_VULKANINSTANCE_HPP
|
||||||
|
#include <GraphicsVulkan/VulkanInclude.hpp>
|
||||||
|
|
||||||
|
#include <GraphicsInterface/GraphicsInstance.hpp>
|
||||||
|
|
||||||
|
#include <Utils/TargetMacros.h>
|
||||||
|
#include <Utils/Version.hpp>
|
||||||
|
|
||||||
|
#include <EASTL/string_view.h>
|
||||||
|
|
||||||
|
namespace Bigfoot::Vulkan
|
||||||
|
{
|
||||||
|
class VulkanInstance final: public GraphicsInstance
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Constructor. Creates a vk::Instance
|
||||||
|
*
|
||||||
|
* \param p_applicationName The name of the application
|
||||||
|
* \param p_applicationVersion The version of the application
|
||||||
|
*/
|
||||||
|
VulkanInstance(eastl::string_view p_applicationName, Version p_applicationVersion);
|
||||||
|
|
||||||
|
~VulkanInstance() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the underlying Vulkan instance handle
|
||||||
|
*
|
||||||
|
* \return The vk::Instance handle
|
||||||
|
*/
|
||||||
|
[[nodiscard]]
|
||||||
|
vk::Instance GetHandle() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* The vulkan loader.
|
||||||
|
*/
|
||||||
|
vk::detail::DynamicLoader m_loader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The vulkan instance.
|
||||||
|
*/
|
||||||
|
vk::Instance m_instance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The debug messenger (used for validation callbacks).
|
||||||
|
*/
|
||||||
|
BIGFOOT_NOT_OPTIMIZED_ONLY(vk::DebugUtilsMessengerEXT m_debugMessenger);
|
||||||
|
};
|
||||||
|
} // namespace Bigfoot::Vulkan
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,160 @@
|
|||||||
|
/*********************************************************************
|
||||||
|
* \file VulkanInstance.cpp
|
||||||
|
*
|
||||||
|
* \author Romain BOULLARD
|
||||||
|
* \date September 2026
|
||||||
|
*********************************************************************/
|
||||||
|
#include <GraphicsVulkan/VulkanInstance.hpp>
|
||||||
|
|
||||||
|
#include <GraphicsVulkan/GraphicsVulkanAssertHandler.hpp>
|
||||||
|
#include <GraphicsVulkan/VulkanFormatters.hpp>
|
||||||
|
|
||||||
|
#include <Engine/EngineInfo_generated.hpp>
|
||||||
|
|
||||||
|
#include <EASTL/algorithm.h>
|
||||||
|
#include <EASTL/string.h>
|
||||||
|
#include <EASTL/vector.h>
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
|
||||||
|
|
||||||
|
namespace Bigfoot::Vulkan
|
||||||
|
{
|
||||||
|
[[nodiscard]]
|
||||||
|
std::uint32_t ToVulkanVersion(const Bigfoot::Version p_version)
|
||||||
|
{
|
||||||
|
return VK_MAKE_VERSION(p_version.GetMajor(), p_version.GetMinor(), p_version.GetPatch());
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************************/
|
||||||
|
|
||||||
|
#ifdef BIGFOOT_NOT_OPTIMIZED
|
||||||
|
vk::Bool32 VulkanDebugCallback(const vk::DebugUtilsMessageSeverityFlagBitsEXT p_severity,
|
||||||
|
[[maybe_unused]] vk::DebugUtilsMessageTypeFlagsEXT p_type,
|
||||||
|
const vk::DebugUtilsMessengerCallbackDataEXT* p_callbackData,
|
||||||
|
[[maybe_unused]] void* p_userData)
|
||||||
|
{
|
||||||
|
switch (p_severity)
|
||||||
|
{
|
||||||
|
case vk::DebugUtilsMessageSeverityFlagBitsEXT::eError:
|
||||||
|
BIGFOOT_LOG_ERROR(::Bigfoot::GRAPHICSVULKAN_LOGGER, "{}", p_callbackData->pMessage);
|
||||||
|
break;
|
||||||
|
case vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning:
|
||||||
|
BIGFOOT_LOG_WARN(::Bigfoot::GRAPHICSVULKAN_LOGGER, "{}", p_callbackData->pMessage);
|
||||||
|
break;
|
||||||
|
case vk::DebugUtilsMessageSeverityFlagBitsEXT::eInfo:
|
||||||
|
BIGFOOT_LOG_INFO(::Bigfoot::GRAPHICSVULKAN_LOGGER, "{}", p_callbackData->pMessage);
|
||||||
|
break;
|
||||||
|
case vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose:
|
||||||
|
default:
|
||||||
|
BIGFOOT_LOG_TRACE(::Bigfoot::GRAPHICSVULKAN_LOGGER, "{}", p_callbackData->pMessage);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return VK_FALSE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************************/
|
||||||
|
|
||||||
|
VulkanInstance::VulkanInstance(const eastl::string_view p_applicationName, const Version p_applicationVersion)
|
||||||
|
{
|
||||||
|
const PFN_vkGetInstanceProcAddr getInstanceProcAddr = m_loader.getProcAddress<PFN_vkGetInstanceProcAddr>(
|
||||||
|
"vkGetInstanceProcAddr");
|
||||||
|
CRITICAL_ASSERT(GraphicsVulkanAssertHandler, getInstanceProcAddr != nullptr, "vkGetInstanceProcAddr not found!");
|
||||||
|
|
||||||
|
VULKAN_HPP_DEFAULT_DISPATCHER.init(getInstanceProcAddr);
|
||||||
|
|
||||||
|
const eastl::string applicationName {p_applicationName};
|
||||||
|
const vk::ApplicationInfo applicationInfo {applicationName.c_str(),
|
||||||
|
ToVulkanVersion(p_applicationVersion),
|
||||||
|
BIGFOOT_NAME.data(),
|
||||||
|
ToVulkanVersion(BIGFOOT_VERSION),
|
||||||
|
VK_API_VERSION_1_3};
|
||||||
|
|
||||||
|
eastl::vector<const char*> enabledLayers;
|
||||||
|
eastl::vector<const char*> enabledExtensions {
|
||||||
|
VK_KHR_SURFACE_EXTENSION_NAME,
|
||||||
|
BIGFOOT_WINDOWS_OR_LINUX(VK_KHR_WIN32_SURFACE_EXTENSION_NAME, VK_KHR_XLIB_SURFACE_EXTENSION_NAME)};
|
||||||
|
|
||||||
|
#ifdef BIGFOOT_NOT_OPTIMIZED
|
||||||
|
const vk::ResultValue<std::vector<vk::LayerProperties>> availableLayers = vk::enumerateInstanceLayerProperties();
|
||||||
|
CRITICAL_ASSERT(GraphicsVulkanAssertHandler,
|
||||||
|
availableLayers.result == vk::Result::eSuccess,
|
||||||
|
"({}) Failed to enumerate Vulkan instance layers",
|
||||||
|
availableLayers.result);
|
||||||
|
|
||||||
|
const bool validationLayerAvailable = eastl::find_if(availableLayers.value.begin(),
|
||||||
|
availableLayers.value.end(),
|
||||||
|
[](const vk::LayerProperties& p_layer)
|
||||||
|
{
|
||||||
|
return eastl::string_view {p_layer.layerName.data()} ==
|
||||||
|
"VK_LAYER_KHRONOS_validation";
|
||||||
|
}) != availableLayers.value.end();
|
||||||
|
|
||||||
|
if (validationLayerAvailable)
|
||||||
|
{
|
||||||
|
enabledLayers.push_back("VK_LAYER_KHRONOS_validation");
|
||||||
|
enabledExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BIGFOOT_LOG_WARN(GRAPHICSVULKAN_LOGGER, "Vulkan validation layer requested but not available");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const vk::InstanceCreateInfo instanceCreateInfo {{}, &applicationInfo, enabledLayers, enabledExtensions};
|
||||||
|
|
||||||
|
const vk::ResultValue<vk::Instance> instance = vk::createInstance(instanceCreateInfo);
|
||||||
|
CRITICAL_ASSERT(GraphicsVulkanAssertHandler,
|
||||||
|
instance.result == vk::Result::eSuccess,
|
||||||
|
"({}) Failed to create Vulkan instance",
|
||||||
|
instance.result);
|
||||||
|
m_instance = instance.value;
|
||||||
|
|
||||||
|
VULKAN_HPP_DEFAULT_DISPATCHER.init(m_instance);
|
||||||
|
|
||||||
|
#ifdef BIGFOOT_NOT_OPTIMIZED
|
||||||
|
if (validationLayerAvailable)
|
||||||
|
{
|
||||||
|
vk::DebugUtilsMessengerCreateInfoEXT messengerCreateInfo {};
|
||||||
|
messengerCreateInfo.messageSeverity = vk::DebugUtilsMessageSeverityFlagsEXT {
|
||||||
|
vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose | vk::DebugUtilsMessageSeverityFlagBitsEXT::eInfo |
|
||||||
|
vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning | vk::DebugUtilsMessageSeverityFlagBitsEXT::eError};
|
||||||
|
messengerCreateInfo.messageType = vk::DebugUtilsMessageTypeFlagsEXT {
|
||||||
|
vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral | vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation |
|
||||||
|
vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance};
|
||||||
|
messengerCreateInfo.pfnUserCallback = &VulkanDebugCallback;
|
||||||
|
|
||||||
|
const vk::ResultValue<vk::DebugUtilsMessengerEXT> messenger = m_instance.createDebugUtilsMessengerEXT(
|
||||||
|
messengerCreateInfo);
|
||||||
|
CRITICAL_ASSERT(GraphicsVulkanAssertHandler,
|
||||||
|
messenger.result == vk::Result::eSuccess,
|
||||||
|
"({}) Failed to create Vulkan debug messenger",
|
||||||
|
messenger.result);
|
||||||
|
m_debugMessenger = messenger.value;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************************/
|
||||||
|
|
||||||
|
VulkanInstance::~VulkanInstance()
|
||||||
|
{
|
||||||
|
#ifdef BIGFOOT_NOT_OPTIMIZED
|
||||||
|
if (m_debugMessenger)
|
||||||
|
{
|
||||||
|
m_instance.destroyDebugUtilsMessengerEXT(m_debugMessenger);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
m_instance.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************************/
|
||||||
|
|
||||||
|
vk::Instance VulkanInstance::GetHandle() const
|
||||||
|
{
|
||||||
|
return m_instance;
|
||||||
|
}
|
||||||
|
} // namespace Bigfoot::Vulkan
|
||||||
@@ -23,6 +23,7 @@ namespace Bigfoot::Vulkan
|
|||||||
{
|
{
|
||||||
class VulkanFormattersFixture: public ::testing::Test
|
class VulkanFormattersFixture: public ::testing::Test
|
||||||
{
|
{
|
||||||
|
protected:
|
||||||
};
|
};
|
||||||
|
|
||||||
/****************************************************************************************/
|
/****************************************************************************************/
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
/*********************************************************************
|
||||||
|
* \file VulkanInstance.cpp
|
||||||
|
*
|
||||||
|
* \author Romain BOULLARD
|
||||||
|
* \date September 2026
|
||||||
|
*********************************************************************/
|
||||||
|
#include <GraphicsVulkan/VulkanInstance.hpp>
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
namespace Bigfoot::Vulkan
|
||||||
|
{
|
||||||
|
class VulkanInstanceFixture: public ::testing::Test
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
};
|
||||||
|
|
||||||
|
/****************************************************************************************/
|
||||||
|
|
||||||
|
TEST_F(VulkanInstanceFixture, Constructor_ShouldCreateAValidInstance)
|
||||||
|
{
|
||||||
|
const VulkanInstance instance {"VulkanInstanceTests", Version {1, 0, 0}};
|
||||||
|
|
||||||
|
EXPECT_TRUE(instance.GetHandle());
|
||||||
|
}
|
||||||
|
} // namespace Bigfoot::Vulkan
|
||||||
Reference in New Issue
Block a user