This commit is contained in:
Mars 2024-11-18 19:34:19 -05:00
parent 32a3d21488
commit e72e9bd51f
6 changed files with 306 additions and 151 deletions

View file

@ -14,6 +14,7 @@ common_cpp_args = [
'-Wno-c++98-compat-pedantic', '-Wno-c++98-compat-pedantic',
'-Wno-pre-c++20-compat-pedantic', '-Wno-pre-c++20-compat-pedantic',
'-Wno-padded', '-Wno-padded',
'-Wno-switch-default',
'-mavx2', '-mavx2',
] ]

View file

@ -1,32 +1,97 @@
#include <fmt/color.h>
#include <fmt/format.h> #include <fmt/format.h>
#include "debug_messenger.hpp" #include "debug_messenger.hpp"
fn DebugMessenger::create(const vk::Instance& instance) -> vk::UniqueDebugUtilsMessengerEXT { fn DebugMessenger::create(const vk::Instance& instance, Config config)
-> std::expected<vk::UniqueDebugUtilsMessengerEXT, std::string> {
#ifdef NDEBUG #ifdef NDEBUG
return nullptr; return nullptr;
#else #else
vk::DebugUtilsMessengerCreateInfoEXT createInfo { try {
.messageSeverity = vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose | vk::DebugUtilsMessengerCreateInfoEXT createInfo {
vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning | .messageSeverity = config.severity_flags,
vk::DebugUtilsMessageSeverityFlagBitsEXT::eError, .messageType = config.type_flags,
.messageType = vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral | .pfnUserCallback = debugCallback,
vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation | .pUserData = &config,
vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance, };
.pfnUserCallback = debugCallback,
.pUserData = nullptr,
};
return instance.createDebugUtilsMessengerEXTUnique(createInfo); return instance.createDebugUtilsMessengerEXTUnique(createInfo);
} catch (const vk::SystemError& e) {
return std::unexpected(fmt::format("Failed to create debug messenger: {}", e.what()));
}
#endif #endif
} }
VKAPI_ATTR VkBool32 VKAPI_CALL DebugMessenger::debugCallback( VKAPI_ATTR VkBool32 VKAPI_CALL DebugMessenger::debugCallback(
VkDebugUtilsMessageSeverityFlagBitsEXT /*messageSeverity*/, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VkDebugUtilsMessageTypeFlagsEXT /*messageType*/, VkDebugUtilsMessageTypeFlagsEXT messageType,
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
void* /*pUserData*/ void* pUserData
) { ) {
fmt::println("validation layer: {}", pCallbackData->pMessage); const auto* config = static_cast<const Config*>(pUserData);
Message msg { .message = pCallbackData->pMessage,
.severity = static_cast<vk::DebugUtilsMessageSeverityFlagBitsEXT>(messageSeverity),
.type = static_cast<vk::DebugUtilsMessageTypeFlagsEXT>(messageType),
.function_name = pCallbackData->pMessageIdName
? std::optional<std::string_view>(pCallbackData->pMessageIdName)
: std::nullopt,
.id = pCallbackData->messageIdNumber };
const auto formattedMessage = formatMessage(msg);
if (config && config->use_stderr_for_errors &&
(messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)) {
fmt::println(stderr, "{}", formattedMessage);
} else {
fmt::println("{}", formattedMessage);
}
return VK_FALSE; return VK_FALSE;
} }
fn DebugMessenger::formatMessage(const Message& msg) -> std::string {
// Color based on severity
fmt::color textColor = fmt::color::white;
std::string_view severityText;
switch (msg.severity) {
case vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose:
textColor = fmt::color::light_blue;
severityText = "VERBOSE";
break;
case vk::DebugUtilsMessageSeverityFlagBitsEXT::eInfo:
textColor = fmt::color::white;
severityText = "INFO";
break;
case vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning:
textColor = fmt::color::yellow;
severityText = "WARNING";
break;
case vk::DebugUtilsMessageSeverityFlagBitsEXT::eError:
textColor = fmt::color::red;
severityText = "ERROR";
break;
}
// Build message type string
std::string typeStr;
if (msg.type & vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral)
typeStr += "GENERAL ";
if (msg.type & vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation)
typeStr += "VALIDATION ";
if (msg.type & vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance)
typeStr += "PERFORMANCE ";
// Format the message with color and structure
return fmt::format(
fmt::emphasis::bold | fg(textColor),
"[{}] {} {}{}: {}",
severityText,
typeStr,
msg.function_name.has_value() ? fmt::format("in {} ", *msg.function_name) : "",
msg.id,
msg.message
);
}

View file

@ -2,12 +2,35 @@
#define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1 // Use dynamic dispatch for Vulkan functions #define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1 // Use dynamic dispatch for Vulkan functions
#define VULKAN_HPP_NO_CONSTRUCTORS #define VULKAN_HPP_NO_CONSTRUCTORS
#include <expected>
#include <string>
#include <string_view>
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
#include "../util/types.hpp" #include "../util/types.hpp"
class DebugMessenger { class DebugMessenger {
public: public:
/**
* @brief Configuration for debug messenger
*/
struct Config {
vk::DebugUtilsMessageSeverityFlagsEXT severity_flags;
vk::DebugUtilsMessageTypeFlagsEXT type_flags;
bool use_stderr_for_errors;
};
/**
* @brief Debug message information
*/
struct Message {
std::string_view message;
vk::DebugUtilsMessageSeverityFlagBitsEXT severity;
vk::DebugUtilsMessageTypeFlagsEXT type;
std::optional<std::string_view> function_name;
i32 id;
};
DebugMessenger() = default; DebugMessenger() = default;
DebugMessenger(const DebugMessenger&) = default; DebugMessenger(const DebugMessenger&) = default;
DebugMessenger(DebugMessenger&&) = delete; DebugMessenger(DebugMessenger&&) = delete;
@ -15,7 +38,22 @@ class DebugMessenger {
fn operator=(DebugMessenger&&)->DebugMessenger& = delete; fn operator=(DebugMessenger&&)->DebugMessenger& = delete;
~DebugMessenger() = default; ~DebugMessenger() = default;
static fn create(const vk::Instance& instance) -> vk::UniqueDebugUtilsMessengerEXT; /**
* @brief Creates a debug messenger with the specified configuration
* @param instance Vulkan instance
* @param config Debug messenger configuration
* @return Expected containing the debug messenger or an error message
*/
static fn create(
const vk::Instance& instance,
Config config = { .severity_flags = vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose |
vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning |
vk::DebugUtilsMessageSeverityFlagBitsEXT::eError,
.type_flags = vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral |
vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation |
vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance,
.use_stderr_for_errors = true }
) -> std::expected<vk::UniqueDebugUtilsMessengerEXT, std::string>;
private: private:
static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback( static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(
@ -24,4 +62,11 @@ class DebugMessenger {
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
void* pUserData void* pUserData
); );
/**
* @brief Formats a debug message for output
* @param msg Message information
* @return Formatted message string
*/
static fn formatMessage(const Message& msg) -> std::string;
}; };

View file

@ -1,118 +1,118 @@
#include <expected>
#include <fmt/format.h> #include <fmt/format.h>
#include <set> #include <set>
#include <tuple> #include <span>
#include "device_manager.hpp" #include "device_manager.hpp"
#include "../structs/swap_chain_support_details.hpp" #include "../structs/swap_chain_support_details.hpp"
struct PhysicalDeviceInfo {
vk::PhysicalDevice physical_device;
vk::SampleCountFlagBits msaa_samples;
f32 max_line_width;
bool wide_line_support;
};
struct LogicalDeviceInfo {
vk::UniqueDevice device;
vk::Queue graphics_queue;
vk::Queue present_queue;
};
fn DeviceManager::pickPhysicalDevice( fn DeviceManager::pickPhysicalDevice(
const vk::Instance& instance, const vk::Instance& instance,
const vk::SurfaceKHR& surface, const vk::SurfaceKHR& surface,
const std::vector<const char*>& requiredExtensions std::span<const char* const> requiredExtensions
) -> std::tuple<vk::PhysicalDevice, vk::SampleCountFlagBits, f32, bool> { ) -> std::expected<PhysicalDeviceInfo, std::string> {
// Get all available physical devices // Get all available physical devices
std::vector<vk::PhysicalDevice> devices = instance.enumeratePhysicalDevices(); auto devices = instance.enumeratePhysicalDevices();
if (devices.empty()) if (devices.empty())
throw std::runtime_error("Failed to find GPUs with Vulkan support!"); return std::unexpected("Failed to find GPUs with Vulkan support!");
#ifndef NDEBUG #ifndef NDEBUG
fmt::println("Available devices:"); fmt::println("Available devices:");
#endif #endif
vk::PhysicalDevice physicalDevice; // Find the first suitable device using ranges
vk::SampleCountFlagBits msaaSamples = vk::SampleCountFlagBits::e1; auto suitableDevice = std::ranges::find_if(devices, [&](const auto& device) {
f32 maxLineWidth = 1.0F; return isDeviceSuitable(device, surface, requiredExtensions);
bool wideLineSupport = false; });
// For each device, if (suitableDevice == devices.end())
for (const vk::PhysicalDevice& device : devices) { return std::unexpected("Failed to find a suitable GPU!");
#ifndef NDEBUG
vk::PhysicalDeviceProperties properties = device.getProperties();
fmt::println("\t{}", properties.deviceName.data());
#endif
// Set the first suitable device as the physical device vk::PhysicalDeviceProperties deviceProperties = suitableDevice->getProperties();
if (isDeviceSuitable(device, surface, requiredExtensions)) {
physicalDevice = device;
msaaSamples = getMaxUsableSampleCount(physicalDevice);
// Get the device properties for line width limits
vk::PhysicalDeviceProperties deviceProperties = device.getProperties();
maxLineWidth = deviceProperties.limits.lineWidthRange[1];
wideLineSupport = deviceProperties.limits.lineWidthRange[1] > 1.0F;
#ifndef NDEBUG #ifndef NDEBUG
fmt::println("Maximum supported line width: {}", maxLineWidth); fmt::println("\t{}", deviceProperties.deviceName.data());
fmt::println("Wide lines supported: {}", wideLineSupport ? "yes" : "no"); fmt::println("Maximum supported line width: {}", deviceProperties.limits.lineWidthRange[1]);
fmt::println("Wide lines supported: {}", deviceProperties.limits.lineWidthRange[1] > 1.0F ? "yes" : "no");
#endif #endif
break;
}
}
// If no suitable device was found, throw an error return PhysicalDeviceInfo {
if (!physicalDevice) .physical_device = *suitableDevice,
throw std::runtime_error("Failed to find a suitable GPU!"); .msaa_samples = getMaxUsableSampleCount(*suitableDevice),
.max_line_width = deviceProperties.limits.lineWidthRange[1],
return std::make_tuple(physicalDevice, msaaSamples, maxLineWidth, wideLineSupport); .wide_line_support = deviceProperties.limits.lineWidthRange[1] > 1.0F,
};
} }
fn DeviceManager::createLogicalDevice( fn DeviceManager::createLogicalDevice(
const vk::PhysicalDevice& physicalDevice, const vk::PhysicalDevice& physicalDevice,
const vk::SurfaceKHR& surface, const vk::SurfaceKHR& surface,
const std::vector<const char*>& requiredExtensions, std::span<const char* const> requiredExtensions,
const bool enableValidationLayers, bool enableValidationLayers,
const std::vector<const char*>& validationLayers std::span<const char* const> validationLayers
) -> std::tuple<vk::UniqueDevice, vk::Queue, vk::Queue> { ) -> std::expected<LogicalDeviceInfo, std::string> {
QueueFamilyIndices indices = findQueueFamilies(physicalDevice, surface); try {
QueueFamilyIndices indices = findQueueFamilies(physicalDevice, surface);
// Create a set of unique queue families needed std::set<u32> uniqueQueueFamilies = { indices.graphics_family.value(), indices.present_family.value() };
std::set<u32> uniqueQueueFamilies = { indices.graphics_family.value(), indices.present_family.value() };
// Create queue create infos for each unique queue family std::vector<vk::DeviceQueueCreateInfo> queueCreateInfos;
std::vector<vk::DeviceQueueCreateInfo> queueCreateInfos; f32 queuePriority = 1.0F;
f32 queuePriority = 1.0F;
for (u32 queueFamily : uniqueQueueFamilies) { // Use ranges to transform unique queue families into create infos
vk::DeviceQueueCreateInfo queueCreateInfo { std::ranges::transform(uniqueQueueFamilies, std::back_inserter(queueCreateInfos), [&](u32 queueFamily) {
.queueFamilyIndex = queueFamily, return vk::DeviceQueueCreateInfo {
.queueCount = 1, .queueFamilyIndex = queueFamily,
.pQueuePriorities = &queuePriority, .queueCount = 1,
.pQueuePriorities = &queuePriority,
};
});
vk::PhysicalDeviceFeatures deviceFeatures {
.wideLines = vk::True,
.samplerAnisotropy = vk::True,
}; };
queueCreateInfos.push_back(queueCreateInfo);
vk::DeviceCreateInfo createInfo {
.queueCreateInfoCount = static_cast<u32>(queueCreateInfos.size()),
.pQueueCreateInfos = queueCreateInfos.data(),
.enabledExtensionCount = static_cast<u32>(requiredExtensions.size()),
.ppEnabledExtensionNames = requiredExtensions.data(),
.pEnabledFeatures = &deviceFeatures,
};
if (enableValidationLayers) {
createInfo.enabledLayerCount = static_cast<u32>(validationLayers.size());
createInfo.ppEnabledLayerNames = validationLayers.data();
}
auto device = physicalDevice.createDeviceUnique(createInfo);
auto graphicsQueue = device->getQueue(indices.graphics_family.value(), 0);
auto presentQueue = device->getQueue(indices.present_family.value(), 0);
return LogicalDeviceInfo {
.device = std::move(device),
.graphics_queue = graphicsQueue,
.present_queue = presentQueue,
};
} catch (const vk::SystemError& e) {
return std::unexpected(fmt::format("Failed to create logical device: {}", e.what()));
} }
// Specify device features
vk::PhysicalDeviceFeatures deviceFeatures {
.fillModeNonSolid = true,
.wideLines = true,
.samplerAnisotropy = true,
};
// Create the logical device
vk::DeviceCreateInfo createInfo {
.queueCreateInfoCount = static_cast<u32>(queueCreateInfos.size()),
.pQueueCreateInfos = queueCreateInfos.data(),
.enabledExtensionCount = static_cast<u32>(requiredExtensions.size()),
.ppEnabledExtensionNames = requiredExtensions.data(),
.pEnabledFeatures = &deviceFeatures,
};
// Only enable validation layers if requested
if (enableValidationLayers) {
createInfo.enabledLayerCount = static_cast<u32>(validationLayers.size());
createInfo.ppEnabledLayerNames = validationLayers.data();
}
// Create the logical device
vk::UniqueDevice device = physicalDevice.createDeviceUnique(createInfo);
// Get queue handles
vk::Queue graphicsQueue = device->getQueue(indices.graphics_family.value(), 0);
vk::Queue presentQueue = device->getQueue(indices.present_family.value(), 0);
return std::make_tuple(std::move(device), graphicsQueue, presentQueue);
} }
fn DeviceManager::getMaxUsableSampleCount(const vk::PhysicalDevice& physicalDevice fn DeviceManager::getMaxUsableSampleCount(const vk::PhysicalDevice& physicalDevice
@ -162,9 +162,9 @@ fn DeviceManager::findQueueFamilies(const vk::PhysicalDevice& device, const vk::
} }
fn DeviceManager::isDeviceSuitable( fn DeviceManager::isDeviceSuitable(
const vk::PhysicalDevice& device, const vk::PhysicalDevice& device,
const vk::SurfaceKHR& surface, const vk::SurfaceKHR& surface,
const std::vector<const char*>& requiredExtensions std::span<const char* const> requiredExtensions
) -> bool { ) -> bool {
// Check queue family support // Check queue family support
QueueFamilyIndices indices = findQueueFamilies(device, surface); QueueFamilyIndices indices = findQueueFamilies(device, surface);
@ -190,20 +190,15 @@ fn DeviceManager::isDeviceSuitable(
} }
fn DeviceManager::checkDeviceExtensionSupport( fn DeviceManager::checkDeviceExtensionSupport(
const vk::PhysicalDevice& device, const vk::PhysicalDevice& device,
const std::vector<const char*>& requiredExtensions std::span<const char* const> requiredExtensions
) -> bool { ) -> bool {
// Get available extensions
std::vector<vk::ExtensionProperties> availableExtensions = device.enumerateDeviceExtensionProperties(); std::vector<vk::ExtensionProperties> availableExtensions = device.enumerateDeviceExtensionProperties();
// Convert available extensions to a set of strings for easier lookup // Use ranges to check if all required extensions are available
std::set<std::string> availableExtensionNames;
for (const auto& extension : availableExtensions) {
availableExtensionNames.insert(extension.extensionName);
}
// Check if all required extensions are available
return std::ranges::all_of(requiredExtensions, [&](const char* required) { return std::ranges::all_of(requiredExtensions, [&](const char* required) {
return availableExtensionNames.contains(required); return std::ranges::any_of(availableExtensions, [&](const vk::ExtensionProperties& available) {
return strcmp(required, available.extensionName) == 0;
});
}); });
} }

View file

@ -2,6 +2,8 @@
#define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1 #define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1
#define VULKAN_HPP_NO_CONSTRUCTORS #define VULKAN_HPP_NO_CONSTRUCTORS
#include <expected>
#include <span>
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
#include "../structs/queue_family_indices.hpp" #include "../structs/queue_family_indices.hpp"
@ -11,20 +13,38 @@ class DeviceManager {
public: public:
DeviceManager() = default; DeviceManager() = default;
/**
* @brief Result type for physical device selection
*/
struct PhysicalDeviceInfo {
vk::PhysicalDevice physical_device;
vk::SampleCountFlagBits msaa_samples;
f32 max_line_width;
bool wide_line_support;
};
/**
* @brief Result type for logical device creation
*/
struct LogicalDeviceInfo {
vk::UniqueDevice device;
vk::Queue graphics_queue;
vk::Queue present_queue;
};
/** /**
* @brief Picks a suitable physical device (GPU) for the application. * @brief Picks a suitable physical device (GPU) for the application.
* *
* @param instance Vulkan instance to use for device selection * @param instance Vulkan instance to use for device selection
* @param surface Surface to check for compatibility * @param surface Surface to check for compatibility
* @param requiredExtensions List of required device extensions * @param requiredExtensions List of required device extensions
* @return std::tuple<vk::PhysicalDevice, vk::SampleCountFlagBits, f32, bool> Physical device, MSAA samples, * @return std::expected<PhysicalDeviceInfo, std::string> Physical device info or error message
* max line width, wide line support
*/ */
static fn pickPhysicalDevice( static fn pickPhysicalDevice(
const vk::Instance& instance, const vk::Instance& instance,
const vk::SurfaceKHR& surface, const vk::SurfaceKHR& surface,
const std::vector<const char*>& requiredExtensions std::span<const char* const> requiredExtensions
) -> std::tuple<vk::PhysicalDevice, vk::SampleCountFlagBits, f32, bool>; ) -> std::expected<PhysicalDeviceInfo, std::string>;
/** /**
* @brief Creates a logical device with the specified features. * @brief Creates a logical device with the specified features.
@ -34,15 +54,15 @@ class DeviceManager {
* @param requiredExtensions Device extensions to enable * @param requiredExtensions Device extensions to enable
* @param enableValidationLayers Whether to enable validation layers * @param enableValidationLayers Whether to enable validation layers
* @param validationLayers Validation layers to enable if enabled * @param validationLayers Validation layers to enable if enabled
* @return std::tuple<vk::UniqueDevice, vk::Queue, vk::Queue> Logical device and queues * @return std::expected<LogicalDeviceInfo, std::string> Logical device info or error message
*/ */
static fn createLogicalDevice( static fn createLogicalDevice(
const vk::PhysicalDevice& physicalDevice, const vk::PhysicalDevice& physicalDevice,
const vk::SurfaceKHR& surface, const vk::SurfaceKHR& surface,
const std::vector<const char*>& requiredExtensions, std::span<const char* const> requiredExtensions,
bool enableValidationLayers, bool enableValidationLayers,
const std::vector<const char*>& validationLayers std::span<const char* const> validationLayers
) -> std::tuple<vk::UniqueDevice, vk::Queue, vk::Queue>; ) -> std::expected<LogicalDeviceInfo, std::string>;
/** /**
* @brief Gets the maximum supported MSAA sample count. * @brief Gets the maximum supported MSAA sample count.
@ -71,20 +91,16 @@ class DeviceManager {
* @return bool True if device is suitable * @return bool True if device is suitable
*/ */
static fn isDeviceSuitable( static fn isDeviceSuitable(
const vk::PhysicalDevice& device, const vk::PhysicalDevice& device,
const vk::SurfaceKHR& surface, const vk::SurfaceKHR& surface,
const std::vector<const char*>& requiredExtensions std::span<const char* const> requiredExtensions
) -> bool; ) -> bool;
/** /**
* @brief Checks if a physical device supports required extensions. * @brief Checks if the device supports the required extensions.
*
* @param device Physical device to check
* @param requiredExtensions Required device extensions
* @return bool True if device supports all required extensions
*/ */
static fn checkDeviceExtensionSupport( static fn checkDeviceExtensionSupport(
const vk::PhysicalDevice& device, const vk::PhysicalDevice& device,
const std::vector<const char*>& requiredExtensions std::span<const char* const> requiredExtensions
) -> bool; ) -> bool;
}; };

View file

@ -161,10 +161,12 @@ class VulkanApp {
Camera mCamera; ///< Camera object Camera mCamera; ///< Camera object
// Light settings // Light settings
LightInfo mLightSettings { .position = glm::vec3(2.0F, 2.0F, 2.0F), LightInfo mLightSettings {
.color = glm::vec3(1.0F, 1.0F, 1.0F), .position = glm::vec3(2.0F, 2.0F, 2.0F),
.ambient_strength = 0.1F, .color = glm::vec3(1.0F, 1.0F, 1.0F),
.specular_strength = 0.5F }; .ambient_strength = 0.1F,
.specular_strength = 0.5F,
};
// Mouse input tracking // Mouse input tracking
bool mFirstMouse = true; ///< Flag for first mouse movement bool mFirstMouse = true; ///< Flag for first mouse movement
@ -641,7 +643,21 @@ class VulkanApp {
return; return;
#endif #endif
mDebugMessenger = DebugMessenger::create(mInstance.get()); DebugMessenger::Config config {
.severity_flags = vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose |
vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning |
vk::DebugUtilsMessageSeverityFlagBitsEXT::eError,
.type_flags = vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral |
vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation |
vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance,
.use_stderr_for_errors = true,
};
auto result = DebugMessenger::create(mInstance.get(), config);
if (!result) {
throw std::runtime_error(result.error());
}
mDebugMessenger = std::move(*result);
} }
/** /**
@ -658,10 +674,18 @@ class VulkanApp {
* the application's requirements. * the application's requirements.
*/ */
fn pickPhysicalDevice() -> void { fn pickPhysicalDevice() -> void {
std::tie(mPhysicalDevice, mMsaaSamples, mMaxLineWidth, mWideLineSupport) = auto result =
DeviceManager::pickPhysicalDevice( DeviceManager::pickPhysicalDevice(mInstance.get(), mSurface.get(), std::span(deviceExtensions));
mInstance.get(), mSurface.get(), std::vector(deviceExtensions.begin(), deviceExtensions.end())
); if (!result) {
throw std::runtime_error(result.error());
}
const auto& info = *result;
mPhysicalDevice = info.physical_device;
mMsaaSamples = info.msaa_samples;
mMaxLineWidth = info.max_line_width;
mWideLineSupport = info.wide_line_support;
} }
/** /**
@ -671,13 +695,22 @@ class VulkanApp {
* features and retrieving handles to the graphics and presentation queues. * features and retrieving handles to the graphics and presentation queues.
*/ */
fn createLogicalDevice() -> void { fn createLogicalDevice() -> void {
std::tie(mDevice, mGraphicsQueue, mPresentQueue) = DeviceManager::createLogicalDevice( auto result = DeviceManager::createLogicalDevice(
mPhysicalDevice, mPhysicalDevice,
mSurface.get(), mSurface.get(),
std::vector(deviceExtensions.begin(), deviceExtensions.end()), std::span(deviceExtensions),
enableValidationLayers, enableValidationLayers,
std::vector(validationLayers.begin(), validationLayers.end()) std::span(validationLayers)
); );
if (!result) {
throw std::runtime_error(result.error());
}
auto info = std::move(*result);
mDevice = std::move(info.device);
mGraphicsQueue = info.graphics_queue;
mPresentQueue = info.present_queue;
} }
/** /**