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(BigfootPublicDependencies
|
||||
GraphicsInterface)
|
||||
set(BigfootPrivateDependencies)
|
||||
set(BigfootPrivateDependencies
|
||||
Engine)
|
||||
|
||||
bigfoot_create_package_lib(
|
||||
"${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
|
||||
{
|
||||
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