Dodo 0.1
Template for CPP projects
Loading...
Searching...
No Matches
dodo::core::VulkanContext Class Reference

#include <VulkanContext.hpp>

Classes

struct  VulkanContextInfo
 
struct  VulkanDebug
 

Public Types

using DebugCallback = vk::PFN_DebugUtilsMessengerCallbackEXT
 

Public Member Functions

 ~VulkanContext ()=default
 
 VulkanContext (const VulkanContext &other)=delete
 
VulkanContextoperator= (const VulkanContext &other)=delete
 
 VulkanContext (VulkanContext &&other) noexcept
 
VulkanContextoperator= (VulkanContext &&other) noexcept
 

Static Public Member Functions

static VKAPI_ATTR vk::Bool32 VKAPI_CALL defaultDebugCallback (vk::DebugUtilsMessageSeverityFlagBitsEXT severity, vk::DebugUtilsMessageTypeFlagsEXT type, const vk::DebugUtilsMessengerCallbackDataEXT *pCallbackData, void *)
 

Private Member Functions

 VulkanContext ()=default
 

Static Private Member Functions

template<typename... Features>
static auto createContext (const VulkanContextInfo< Features... > &ctxInfo) -> std::expected< VulkanContext, std::string >
 
static auto checkRequiredLayers (const VulkanContext &vulkanContext, std::span< const char *const > validationLayers) -> std::expected< bool, std::string >
 
static auto checkRequiredExtensions (const VulkanContext &vulkanContext, std::span< const char *const > glfwExtensions) -> std::expected< bool, std::string >
 
static void setupDebugMessenger (VulkanContext &vulkanContext, DebugCallback debugCallback)
 
static auto pickPhysicalDevice (VulkanContext &vulkanContext) -> std::expected< bool, std::string >
 
static bool isDeviceSuitable (const vk::raii::PhysicalDevice &physicalDevice)
 
template<typename FirstFeature , typename... OtherFeatures>
static FirstFeature & getFirstFeature (vk::StructureChain< FirstFeature, OtherFeatures... > featureChain)
 

Private Attributes

vk::raii::Context _context
 
vk::raii::Instance _instance = nullptr
 
vk::raii::PhysicalDevice _physicalDevice = nullptr
 
vk::raii::DebugUtilsMessengerEXT _debugMessenger = nullptr
 

Friends

class DodoContext
 

Member Typedef Documentation

◆ DebugCallback

using dodo::core::VulkanContext::DebugCallback = vk::PFN_DebugUtilsMessengerCallbackEXT

Constructor & Destructor Documentation

◆ ~VulkanContext()

dodo::core::VulkanContext::~VulkanContext ( )
default

◆ VulkanContext() [1/3]

dodo::core::VulkanContext::VulkanContext ( const VulkanContext & other)
delete

◆ VulkanContext() [2/3]

dodo::core::VulkanContext::VulkanContext ( VulkanContext && other)
noexcept
10 :
11_context(std::exchange(other._context, vk::raii::Context())),
12_instance(std::exchange(other._instance, nullptr)),
13_physicalDevice(std::exchange(other._physicalDevice, nullptr))
14{
15}
vk::raii::PhysicalDevice _physicalDevice
Definition VulkanContext.hpp:26
vk::raii::Context _context
Definition VulkanContext.hpp:24
vk::raii::Instance _instance
Definition VulkanContext.hpp:25

◆ VulkanContext() [3/3]

dodo::core::VulkanContext::VulkanContext ( )
privatedefault

Member Function Documentation

◆ checkRequiredExtensions()

auto dodo::core::VulkanContext::checkRequiredExtensions ( const VulkanContext & vulkanContext,
std::span< const char *const > glfwExtensions ) -> std::expected<bool, std::string>
staticprivate
41 {
42 auto extensionProperties = vulkanContext._context.enumerateInstanceExtensionProperties();
43
44 std::cout << "available extensions:\n";
45 for (const auto &[extensionName, specVersion] : extensionProperties) {
46 std::cout << '\t' << extensionName << " " << specVersion << '\n';
47 }
48
49 for (auto glfwExtension : glfwExtensions)
50 {
51 if (std::ranges::none_of(extensionProperties,
52 [glfwExtension](auto const& extensionProperty)
53 { return strcmp(extensionProperty.extensionName, glfwExtension) == 0; }))
54 {
55 return std::unexpected("Required GLFW extension not supported: " + std::string(glfwExtension));
56 }
57 }
58 return true;
59}

◆ checkRequiredLayers()

auto dodo::core::VulkanContext::checkRequiredLayers ( const VulkanContext & vulkanContext,
std::span< const char *const > validationLayers ) -> std::expected<bool, std::string>
staticprivate
27 {
28 if (!validationLayers.empty()) {
29 auto layerProperties = vulkanContext._context.enumerateInstanceLayerProperties();
30 if (std::ranges::any_of(validationLayers, [&layerProperties](auto const &requiredLayer) {
31 return std::ranges::none_of(layerProperties, [requiredLayer](auto const &layerProperty) {
32 return strcmp(layerProperty.layerName, requiredLayer) == 0;
33 });
34 })) {
35 return std::unexpected("One or more required layers are not supported!");
36 }
37 }
38 return true;
39}
const std::vector< char const * > validationLayers
Definition main.cpp:28

References validationLayers.

◆ createContext()

template<typename... Features>
auto dodo::core::VulkanContext::createContext ( const VulkanContextInfo< Features... > & ctxInfo) -> std::expected<VulkanContext, std::string>
staticprivate
83 {
84 VulkanContext vulkanContext;
85 VulkanDebug debugInfo = ctxInfo.debugInfo;
86 if (debugInfo.debugEnabled) {
87 if (auto result = checkRequiredLayers(vulkanContext, debugInfo.validationLayers); !result)
88 return std::unexpected(result.error());
89 // setupDebugMessenger(vulkanContext, debugInfo.debugCallback);
90 }
91
92 uint32_t glfwExtensionCount = 0;
93 const auto glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
94 if (auto result = checkRequiredExtensions(vulkanContext, std::span(glfwExtensions, glfwExtensionCount)); !result)
95 return std::unexpected(result.error());
96
97 const vk::InstanceCreateInfo createInfo{
98 .pApplicationInfo = &ctxInfo.vkInfo,
99 .enabledLayerCount = static_cast<uint32_t>(debugInfo.validationLayers.size()),
100 .ppEnabledLayerNames = debugInfo.validationLayers.data(),
101 .enabledExtensionCount = glfwExtensionCount,
102 .ppEnabledExtensionNames = glfwExtensions,
103 };
104
105 vulkanContext._instance = vk::raii::Instance(vulkanContext._context, createInfo);
106 return vulkanContext;
107}
static auto checkRequiredExtensions(const VulkanContext &vulkanContext, std::span< const char *const > glfwExtensions) -> std::expected< bool, std::string >
Definition VulkanContext.cpp:41
static auto checkRequiredLayers(const VulkanContext &vulkanContext, std::span< const char *const > validationLayers) -> std::expected< bool, std::string >
Definition VulkanContext.cpp:27
GLFWAPI const char ** glfwGetRequiredInstanceExtensions(uint32_t *count)
Returns the Vulkan instance extensions required by GLFW.

References _context, _instance, dodo::core::VulkanContext::VulkanDebug::debugEnabled, glfwGetRequiredInstanceExtensions(), and dodo::core::VulkanContext::VulkanDebug::validationLayers.

Referenced by dodo::core::DodoContext::createDodoContext().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ defaultDebugCallback()

VKAPI_ATTR vk::Bool32 VKAPI_CALL dodo::core::VulkanContext::defaultDebugCallback ( vk::DebugUtilsMessageSeverityFlagBitsEXT severity,
vk::DebugUtilsMessageTypeFlagsEXT type,
const vk::DebugUtilsMessengerCallbackDataEXT * pCallbackData,
void *  )
static
77{
78 if (severity >= vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning)
79 std::cerr << "validation layer: type " << to_string(type) << " msg: " << pCallbackData->pMessage << std::endl;
80 return vk::False;
81}

◆ getFirstFeature()

template<typename FirstFeature , typename... OtherFeatures>
FirstFeature & dodo::core::VulkanContext::getFirstFeature ( vk::StructureChain< FirstFeature, OtherFeatures... > featureChain)
staticprivate
119 {
120 return featureChain.template get<FirstFeature>();
121}

◆ isDeviceSuitable()

bool dodo::core::VulkanContext::isDeviceSuitable ( const vk::raii::PhysicalDevice & physicalDevice)
staticprivate
111 {
112 const auto deviceProperties = physicalDevice.getProperties();
113 const auto deviceFeatures = physicalDevice.getFeatures();
114
115 return deviceProperties.deviceType == vk::PhysicalDeviceType::eDiscreteGpu && deviceFeatures.geometryShader;
116}

◆ operator=() [1/2]

VulkanContext & dodo::core::VulkanContext::operator= ( const VulkanContext & other)
delete

◆ operator=() [2/2]

VulkanContext & dodo::core::VulkanContext::operator= ( VulkanContext && other)
noexcept
17 {
18 if (this != &other) {
19 _context = std::exchange(other._context, vk::raii::Context());
20 _instance = std::exchange(other._instance, nullptr);
21 _physicalDevice = std::exchange(other._physicalDevice, nullptr);
22 }
23 return *this;
24}

◆ pickPhysicalDevice()

auto dodo::core::VulkanContext::pickPhysicalDevice ( VulkanContext & vulkanContext) -> std::expected<bool, std::string>
staticprivate
83 {
84 // auto devices = vulkanContext._instance.enumeratePhysicalDevices();
85 // const auto devIter = std::ranges::find_if(devices,
86 // [&](auto const & device) {
87 // auto queueFamilies = device.getQueueFamilyProperties();
88 // bool isSuitable = device.getProperties().apiVersion >= VK_API_VERSION_1_3;
89 // const auto qfpIter = std::ranges::find_if(queueFamilies,
90 // []( vk::QueueFamilyProperties const & qfp )
91 // {
92 // return (qfp.queueFlags & vk::QueueFlagBits::eGraphics) != static_cast<vk::QueueFlags>(0);
93 // } );
94 // isSuitable = isSuitable && ( qfpIter != queueFamilies.end() );
95 // auto extensions = device.enumerateDeviceExtensionProperties( );
96 // bool found = true;
97 // for (auto const & extension : deviceExtensions) {
98 // auto extensionIter = std::ranges::find_if(extensions, [extension](auto const & ext) {return strcmp(ext.extensionName, extension) == 0;});
99 // found = found && extensionIter != extensions.end();
100 // }
101 // isSuitable = isSuitable && found;
102 // if (isSuitable)
103 // vulkanContext._physicalDevice = device;
104 // return isSuitable;
105 // });
106 // if (devIter == devices.end())
107 // return std::unexpected("Failed to find a suitable GPU");
108 return true;
109}

◆ setupDebugMessenger()

void dodo::core::VulkanContext::setupDebugMessenger ( VulkanContext & vulkanContext,
DebugCallback debugCallback )
staticprivate
61 {
62 constexpr vk::DebugUtilsMessageSeverityFlagsEXT SEVERITY_FLAGS(vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose |
63 vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning |
64 vk::DebugUtilsMessageSeverityFlagBitsEXT::eError);
65 constexpr vk::DebugUtilsMessageTypeFlagsEXT MESSAGE_TYPE_FLAGS(
66 vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral | vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance | vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation);
67 const vk::DebugUtilsMessengerCreateInfoEXT debugUtilsMessengerCreateInfoEXT{.messageSeverity = SEVERITY_FLAGS,
68 .messageType = MESSAGE_TYPE_FLAGS,
69 .pfnUserCallback = debugCallback};
70 vulkanContext._debugMessenger = vulkanContext._instance.createDebugUtilsMessengerEXT(debugUtilsMessengerCreateInfoEXT);
71}

References _debugMessenger, and _instance.

Friends And Related Symbol Documentation

◆ DodoContext

friend class DodoContext
friend

Member Data Documentation

◆ _context

vk::raii::Context dodo::core::VulkanContext::_context
private

Referenced by createContext().

◆ _debugMessenger

vk::raii::DebugUtilsMessengerEXT dodo::core::VulkanContext::_debugMessenger = nullptr
private

Referenced by setupDebugMessenger().

◆ _instance

vk::raii::Instance dodo::core::VulkanContext::_instance = nullptr
private

◆ _physicalDevice

vk::raii::PhysicalDevice dodo::core::VulkanContext::_physicalDevice = nullptr
private

The documentation for this class was generated from the following files: