i ❤️ segfaulting
This commit is contained in:
parent
0f4d0d72d9
commit
bca2a4e999
|
@ -42,6 +42,7 @@ executable(
|
|||
'src/camera/camera.cpp',
|
||||
'src/init/vulkan_instance.cpp',
|
||||
'src/init/debug_messenger.cpp',
|
||||
'src/init/device_manager.cpp',
|
||||
'src/window/window_manager.cpp',
|
||||
],
|
||||
include_directories: include_directories('include', is_system: true),
|
||||
|
|
209
src/init/device_manager.cpp
Normal file
209
src/init/device_manager.cpp
Normal file
|
@ -0,0 +1,209 @@
|
|||
#include <fmt/format.h>
|
||||
#include <set>
|
||||
#include <tuple>
|
||||
|
||||
#include "device_manager.hpp"
|
||||
|
||||
#include "../structs/swap_chain_support_details.hpp"
|
||||
|
||||
fn DeviceManager::pickPhysicalDevice(
|
||||
const vk::Instance& instance,
|
||||
const vk::SurfaceKHR& surface,
|
||||
const std::vector<const char*>& requiredExtensions
|
||||
) -> std::tuple<vk::PhysicalDevice, vk::SampleCountFlagBits, f32, bool> {
|
||||
// Get all available physical devices
|
||||
std::vector<vk::PhysicalDevice> devices = instance.enumeratePhysicalDevices();
|
||||
|
||||
if (devices.empty())
|
||||
throw std::runtime_error("Failed to find GPUs with Vulkan support!");
|
||||
|
||||
#ifndef NDEBUG
|
||||
fmt::println("Available devices:");
|
||||
#endif
|
||||
|
||||
vk::PhysicalDevice physicalDevice;
|
||||
vk::SampleCountFlagBits msaaSamples = vk::SampleCountFlagBits::e1;
|
||||
f32 maxLineWidth = 1.0F;
|
||||
bool wideLineSupport = false;
|
||||
|
||||
// For each device,
|
||||
for (const vk::PhysicalDevice& device : devices) {
|
||||
#ifndef NDEBUG
|
||||
vk::PhysicalDeviceProperties properties = device.getProperties();
|
||||
fmt::println("\t{}", properties.deviceName.data());
|
||||
#endif
|
||||
|
||||
// Set the first suitable device as the physical device
|
||||
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
|
||||
fmt::println("Maximum supported line width: {}", maxLineWidth);
|
||||
fmt::println("Wide lines supported: {}", wideLineSupport ? "yes" : "no");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If no suitable device was found, throw an error
|
||||
if (!physicalDevice)
|
||||
throw std::runtime_error("Failed to find a suitable GPU!");
|
||||
|
||||
return std::make_tuple(physicalDevice, msaaSamples, maxLineWidth, wideLineSupport);
|
||||
}
|
||||
|
||||
fn DeviceManager::createLogicalDevice(
|
||||
const vk::PhysicalDevice& physicalDevice,
|
||||
const vk::SurfaceKHR& surface,
|
||||
const std::vector<const char*>& requiredExtensions,
|
||||
const bool enableValidationLayers,
|
||||
const std::vector<const char*>& validationLayers
|
||||
) -> std::tuple<vk::UniqueDevice, vk::Queue, vk::Queue> {
|
||||
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() };
|
||||
|
||||
// Create queue create infos for each unique queue family
|
||||
std::vector<vk::DeviceQueueCreateInfo> queueCreateInfos;
|
||||
f32 queuePriority = 1.0F;
|
||||
|
||||
for (u32 queueFamily : uniqueQueueFamilies) {
|
||||
vk::DeviceQueueCreateInfo queueCreateInfo {
|
||||
.queueFamilyIndex = queueFamily,
|
||||
.queueCount = 1,
|
||||
.pQueuePriorities = &queuePriority,
|
||||
};
|
||||
queueCreateInfos.push_back(queueCreateInfo);
|
||||
}
|
||||
|
||||
// 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
|
||||
) -> vk::SampleCountFlagBits {
|
||||
vk::PhysicalDeviceProperties physicalDeviceProperties = physicalDevice.getProperties();
|
||||
|
||||
vk::SampleCountFlags counts = physicalDeviceProperties.limits.framebufferColorSampleCounts &
|
||||
physicalDeviceProperties.limits.framebufferDepthSampleCounts;
|
||||
|
||||
if (counts & vk::SampleCountFlagBits::e64)
|
||||
return vk::SampleCountFlagBits::e64;
|
||||
if (counts & vk::SampleCountFlagBits::e32)
|
||||
return vk::SampleCountFlagBits::e32;
|
||||
if (counts & vk::SampleCountFlagBits::e16)
|
||||
return vk::SampleCountFlagBits::e16;
|
||||
if (counts & vk::SampleCountFlagBits::e8)
|
||||
return vk::SampleCountFlagBits::e8;
|
||||
if (counts & vk::SampleCountFlagBits::e4)
|
||||
return vk::SampleCountFlagBits::e4;
|
||||
if (counts & vk::SampleCountFlagBits::e2)
|
||||
return vk::SampleCountFlagBits::e2;
|
||||
|
||||
return vk::SampleCountFlagBits::e1;
|
||||
}
|
||||
|
||||
fn DeviceManager::findQueueFamilies(const vk::PhysicalDevice& device, const vk::SurfaceKHR& surface)
|
||||
-> QueueFamilyIndices {
|
||||
QueueFamilyIndices indices;
|
||||
|
||||
// Get queue family properties
|
||||
std::vector<vk::QueueFamilyProperties> queueFamilies = device.getQueueFamilyProperties();
|
||||
|
||||
// Find queue family with graphics support
|
||||
for (size_t i = 0; i < queueFamilies.size(); i++) {
|
||||
if (queueFamilies[i].queueFlags & vk::QueueFlagBits::eGraphics)
|
||||
indices.graphics_family = static_cast<u32>(i);
|
||||
|
||||
// Check for presentation support
|
||||
if (device.getSurfaceSupportKHR(static_cast<u32>(i), surface))
|
||||
indices.present_family = static_cast<u32>(i);
|
||||
|
||||
if (indices.isComplete())
|
||||
break;
|
||||
}
|
||||
|
||||
return indices;
|
||||
}
|
||||
|
||||
fn DeviceManager::isDeviceSuitable(
|
||||
const vk::PhysicalDevice& device,
|
||||
const vk::SurfaceKHR& surface,
|
||||
const std::vector<const char*>& requiredExtensions
|
||||
) -> bool {
|
||||
// Check queue family support
|
||||
QueueFamilyIndices indices = findQueueFamilies(device, surface);
|
||||
|
||||
// Check extension support
|
||||
bool extensionsSupported = checkDeviceExtensionSupport(device, requiredExtensions);
|
||||
|
||||
// Check swap chain support
|
||||
bool swapChainAdequate = false;
|
||||
if (extensionsSupported) {
|
||||
SwapChainSupportDetails swapChainSupport;
|
||||
swapChainSupport.capabilities = device.getSurfaceCapabilitiesKHR(surface);
|
||||
swapChainSupport.formats = device.getSurfaceFormatsKHR(surface);
|
||||
swapChainSupport.present_modes = device.getSurfacePresentModesKHR(surface);
|
||||
swapChainAdequate = !swapChainSupport.formats.empty() && !swapChainSupport.present_modes.empty();
|
||||
}
|
||||
|
||||
// Check device features
|
||||
vk::PhysicalDeviceFeatures supportedFeatures = device.getFeatures();
|
||||
|
||||
return indices.isComplete() && extensionsSupported && swapChainAdequate &&
|
||||
supportedFeatures.samplerAnisotropy;
|
||||
}
|
||||
|
||||
fn DeviceManager::checkDeviceExtensionSupport(
|
||||
const vk::PhysicalDevice& device,
|
||||
const std::vector<const char*>& requiredExtensions
|
||||
) -> bool {
|
||||
// Get available extensions
|
||||
std::vector<vk::ExtensionProperties> availableExtensions = device.enumerateDeviceExtensionProperties();
|
||||
|
||||
// Convert available extensions to a set of strings for easier lookup
|
||||
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 availableExtensionNames.contains(required);
|
||||
});
|
||||
}
|
89
src/init/device_manager.hpp
Normal file
89
src/init/device_manager.hpp
Normal file
|
@ -0,0 +1,89 @@
|
|||
#pragma once
|
||||
|
||||
#define VULKAN_HPP_NO_CONSTRUCTORS
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
#include "../structs/queue_family_indices.hpp"
|
||||
#include "../util/types.hpp"
|
||||
|
||||
class DeviceManager {
|
||||
public:
|
||||
DeviceManager() = default;
|
||||
|
||||
/**
|
||||
* @brief Picks a suitable physical device (GPU) for the application.
|
||||
*
|
||||
* @param instance Vulkan instance to use for device selection
|
||||
* @param surface Surface to check for compatibility
|
||||
* @param requiredExtensions List of required device extensions
|
||||
* @return std::tuple<vk::PhysicalDevice, vk::SampleCountFlagBits, f32, bool> Physical device, MSAA samples,
|
||||
* max line width, wide line support
|
||||
*/
|
||||
static fn pickPhysicalDevice(
|
||||
const vk::Instance& instance,
|
||||
const vk::SurfaceKHR& surface,
|
||||
const std::vector<const char*>& requiredExtensions
|
||||
) -> std::tuple<vk::PhysicalDevice, vk::SampleCountFlagBits, f32, bool>;
|
||||
|
||||
/**
|
||||
* @brief Creates a logical device with the specified features.
|
||||
*
|
||||
* @param physicalDevice Physical device to create logical device from
|
||||
* @param surface Surface to create device with
|
||||
* @param requiredExtensions Device extensions to enable
|
||||
* @param enableValidationLayers Whether to enable validation layers
|
||||
* @param validationLayers Validation layers to enable if enabled
|
||||
* @return std::tuple<vk::UniqueDevice, vk::Queue, vk::Queue> Logical device and queues
|
||||
*/
|
||||
static fn createLogicalDevice(
|
||||
const vk::PhysicalDevice& physicalDevice,
|
||||
const vk::SurfaceKHR& surface,
|
||||
const std::vector<const char*>& requiredExtensions,
|
||||
bool enableValidationLayers,
|
||||
const std::vector<const char*>& validationLayers
|
||||
) -> std::tuple<vk::UniqueDevice, vk::Queue, vk::Queue>;
|
||||
|
||||
/**
|
||||
* @brief Gets the maximum supported MSAA sample count.
|
||||
*
|
||||
* @param physicalDevice Physical device to check
|
||||
* @return vk::SampleCountFlagBits Maximum supported sample count
|
||||
*/
|
||||
static fn getMaxUsableSampleCount(const vk::PhysicalDevice& physicalDevice) -> vk::SampleCountFlagBits;
|
||||
|
||||
/**
|
||||
* @brief Finds queue families that support required operations.
|
||||
*
|
||||
* @param device Physical device to check
|
||||
* @param surface Surface to check presentation support
|
||||
* @return QueueFamilyIndices Indices of suitable queue families
|
||||
*/
|
||||
static fn findQueueFamilies(const vk::PhysicalDevice& device, const vk::SurfaceKHR& surface)
|
||||
-> QueueFamilyIndices;
|
||||
|
||||
/**
|
||||
* @brief Checks if a physical device is suitable for the application.
|
||||
*
|
||||
* @param device Physical device to check
|
||||
* @param surface Surface to check compatibility with
|
||||
* @param requiredExtensions Required device extensions
|
||||
* @return bool True if device is suitable
|
||||
*/
|
||||
static fn isDeviceSuitable(
|
||||
const vk::PhysicalDevice& device,
|
||||
const vk::SurfaceKHR& surface,
|
||||
const std::vector<const char*>& requiredExtensions
|
||||
) -> bool;
|
||||
|
||||
/**
|
||||
* @brief Checks if a physical device supports 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(
|
||||
const vk::PhysicalDevice& device,
|
||||
const std::vector<const char*>& requiredExtensions
|
||||
) -> bool;
|
||||
};
|
197
src/main.cpp
197
src/main.cpp
|
@ -3,6 +3,7 @@
|
|||
#include <fmt/format.h> // For string formatting
|
||||
#include <shaderc/shaderc.hpp> // For shader compilation
|
||||
#include <unordered_set> // For unordered_set container
|
||||
#include <vector>
|
||||
|
||||
// GLM (OpenGL Mathematics) configuration
|
||||
#define GLM_FORCE_DEPTH_ZERO_TO_ONE // Use Vulkan's depth range (0 to 1) instead of OpenGL's (-1 to 1)
|
||||
|
@ -22,6 +23,7 @@
|
|||
// Include custom utility headers
|
||||
#include "camera/camera.hpp" // Camera class
|
||||
#include "init/debug_messenger.hpp"
|
||||
#include "init/device_manager.hpp"
|
||||
#include "init/vulkan_instance.hpp"
|
||||
#include "structs/camera_info.hpp"
|
||||
#include "structs/light_info.hpp"
|
||||
|
@ -381,7 +383,8 @@ class VulkanApp {
|
|||
.Instance = mInstance.get(),
|
||||
.PhysicalDevice = mPhysicalDevice,
|
||||
.Device = mDevice.get(),
|
||||
.QueueFamily = findQueueFamilies(mPhysicalDevice).graphics_family.value(),
|
||||
.QueueFamily =
|
||||
DeviceManager::findQueueFamilies(mPhysicalDevice, mSurface.get()).graphics_family.value(),
|
||||
.Queue = mGraphicsQueue,
|
||||
.DescriptorPool = mImGuiDescriptorPool.get(),
|
||||
.RenderPass = mRenderPass.get(),
|
||||
|
@ -653,45 +656,10 @@ class VulkanApp {
|
|||
* the application's requirements.
|
||||
*/
|
||||
fn pickPhysicalDevice() -> void {
|
||||
// Get all physical devices
|
||||
std::vector<vk::PhysicalDevice> devices = mInstance->enumeratePhysicalDevices();
|
||||
|
||||
// Make sure there are supported devices
|
||||
if (devices.empty())
|
||||
throw std::runtime_error("Failed to find GPUs with Vulkan support!");
|
||||
|
||||
#ifndef NDEBUG
|
||||
fmt::println("Available devices:");
|
||||
#endif
|
||||
|
||||
// For each device,
|
||||
for (const vk::PhysicalDevice& device : devices) {
|
||||
#ifndef NDEBUG
|
||||
vk::PhysicalDeviceProperties properties = device.getProperties();
|
||||
fmt::println("\t{}", properties.deviceName.data());
|
||||
#endif
|
||||
|
||||
// Set the first suitable device as the physical device
|
||||
if (isDeviceSuitable(device)) {
|
||||
mPhysicalDevice = device;
|
||||
mMsaaSamples = getMaxUsableSampleCount();
|
||||
|
||||
// Get the device properties for line width limits
|
||||
vk::PhysicalDeviceProperties deviceProperties = device.getProperties();
|
||||
mMaxLineWidth = deviceProperties.limits.lineWidthRange[1];
|
||||
mWideLineSupport = deviceProperties.limits.lineWidthRange[1] > 1.0F;
|
||||
|
||||
#ifndef NDEBUG
|
||||
fmt::println("Maximum supported line width: {}", mMaxLineWidth);
|
||||
fmt::println("Wide lines supported: {}", mWideLineSupport ? "yes" : "no");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If no suitable device was found, throw an error
|
||||
if (!mPhysicalDevice)
|
||||
throw std::runtime_error("Failed to find a suitable GPU!");
|
||||
std::tie(mPhysicalDevice, mMsaaSamples, mMaxLineWidth, mWideLineSupport) =
|
||||
DeviceManager::pickPhysicalDevice(
|
||||
mInstance.get(), mSurface.get(), std::vector(deviceExtensions.begin(), deviceExtensions.end())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -701,50 +669,13 @@ class VulkanApp {
|
|||
* features and retrieving handles to the graphics and presentation queues.
|
||||
*/
|
||||
fn createLogicalDevice() -> void {
|
||||
// Get the queue families
|
||||
QueueFamilyIndices qfIndices = findQueueFamilies(mPhysicalDevice);
|
||||
|
||||
std::vector<vk::DeviceQueueCreateInfo> queueCreateInfos;
|
||||
|
||||
std::set<u32> uniqueQueueFamilies = {
|
||||
qfIndices.graphics_family.value(),
|
||||
qfIndices.present_family.value(),
|
||||
};
|
||||
|
||||
// Set the queue priority
|
||||
f32 queuePriority = 1.0F;
|
||||
|
||||
// For each unique queue family, create a queue create info
|
||||
queueCreateInfos.reserve(uniqueQueueFamilies.size());
|
||||
|
||||
for (u32 queueFamily : uniqueQueueFamilies)
|
||||
queueCreateInfos.push_back({
|
||||
.queueFamilyIndex = queueFamily,
|
||||
.queueCount = 1,
|
||||
.pQueuePriorities = &queuePriority,
|
||||
});
|
||||
|
||||
// Enable required features
|
||||
vk::PhysicalDeviceFeatures deviceFeatures {
|
||||
.fillModeNonSolid = vk::True, // Required for wireframe rendering
|
||||
.wideLines = vk::True, // Required for line width > 1.0
|
||||
.samplerAnisotropy = vk::True,
|
||||
};
|
||||
|
||||
// Create the logical device
|
||||
vk::DeviceCreateInfo createInfo {
|
||||
.queueCreateInfoCount = static_cast<u32>(queueCreateInfos.size()),
|
||||
.pQueueCreateInfos = queueCreateInfos.data(),
|
||||
.enabledExtensionCount = static_cast<u32>(deviceExtensions.size()),
|
||||
.ppEnabledExtensionNames = deviceExtensions.data(),
|
||||
.pEnabledFeatures = &deviceFeatures,
|
||||
};
|
||||
|
||||
mDevice = mPhysicalDevice.createDeviceUnique(createInfo);
|
||||
|
||||
// Get the graphics and present queues
|
||||
mGraphicsQueue = mDevice->getQueue(qfIndices.graphics_family.value(), 0);
|
||||
mPresentQueue = mDevice->getQueue(qfIndices.present_family.value(), 0);
|
||||
std::tie(mDevice, mGraphicsQueue, mPresentQueue) = DeviceManager::createLogicalDevice(
|
||||
mPhysicalDevice,
|
||||
mSurface.get(),
|
||||
std::vector(deviceExtensions.begin(), deviceExtensions.end()),
|
||||
enableValidationLayers,
|
||||
std::vector(validationLayers.begin(), validationLayers.end())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -766,7 +697,7 @@ class VulkanApp {
|
|||
imageCount > swapChainSupport.capabilities.maxImageCount)
|
||||
imageCount = swapChainSupport.capabilities.maxImageCount;
|
||||
|
||||
QueueFamilyIndices qfIndices = findQueueFamilies(mPhysicalDevice);
|
||||
QueueFamilyIndices qfIndices = DeviceManager::findQueueFamilies(mPhysicalDevice, mSurface.get());
|
||||
std::array<u32, 2> queueFamilyIndices = {
|
||||
qfIndices.graphics_family.value(),
|
||||
qfIndices.present_family.value(),
|
||||
|
@ -1272,7 +1203,7 @@ class VulkanApp {
|
|||
* the buffers from which command buffer memory is allocated.
|
||||
*/
|
||||
fn createCommandPool() -> void {
|
||||
QueueFamilyIndices queueFamilyIndices = findQueueFamilies(mPhysicalDevice);
|
||||
QueueFamilyIndices queueFamilyIndices = DeviceManager::findQueueFamilies(mPhysicalDevice, mSurface.get());
|
||||
|
||||
vk::CommandPoolCreateInfo poolInfo { .flags = vk::CommandPoolCreateFlagBits::eResetCommandBuffer,
|
||||
.queueFamilyIndex = queueFamilyIndices.graphics_family.value() };
|
||||
|
@ -2690,100 +2621,6 @@ class VulkanApp {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks if a physical device is suitable for the application.
|
||||
*
|
||||
* @param device The physical device to check.
|
||||
* @return True if the device is suitable, false otherwise.
|
||||
*
|
||||
* This function checks if a physical device meets all the requirements
|
||||
* of the application, including queue families, extensions, and features.
|
||||
*/
|
||||
fn isDeviceSuitable(const vk::PhysicalDevice& device) -> bool {
|
||||
// Get the queue families that support the required operations
|
||||
QueueFamilyIndices qfIndices = findQueueFamilies(device);
|
||||
|
||||
// Check if the device supports the required extensions
|
||||
bool extensionsSupported = checkDeviceExtensionSupport(device);
|
||||
|
||||
bool swapChainAdequate = false;
|
||||
|
||||
if (extensionsSupported) {
|
||||
SwapChainSupportDetails swapChainSupport = querySwapChainSupport(device);
|
||||
// Check if the swap chain is adequate (make sure it has
|
||||
// at least one supported format and presentation mode)
|
||||
swapChainAdequate = !swapChainSupport.formats.empty() && !swapChainSupport.present_modes.empty();
|
||||
}
|
||||
|
||||
// Check if the device supports the required features
|
||||
vk::PhysicalDeviceFeatures supportedFeatures = device.getFeatures();
|
||||
|
||||
// If the device supports everything required, return true
|
||||
return qfIndices.isComplete() && extensionsSupported && swapChainAdequate &&
|
||||
supportedFeatures.samplerAnisotropy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks if a device supports all required extensions.
|
||||
*
|
||||
* @param device The physical device to check.
|
||||
* @return True if all required extensions are supported, false otherwise.
|
||||
*
|
||||
* This function verifies that a physical device supports all the
|
||||
* extensions required by the application.
|
||||
*/
|
||||
static fn checkDeviceExtensionSupport(const vk::PhysicalDevice& device) -> bool {
|
||||
// Get the available extensions
|
||||
std::vector<vk::ExtensionProperties> availableExtensions = device.enumerateDeviceExtensionProperties();
|
||||
|
||||
// Create a set of required extension names
|
||||
std::set<string> requiredExtensions(deviceExtensions.begin(), deviceExtensions.end());
|
||||
|
||||
// Remove each required extension from the set of available extensions
|
||||
for (const vk::ExtensionProperties& extension : availableExtensions)
|
||||
requiredExtensions.erase(extension.extensionName);
|
||||
|
||||
// If the set is empty, all required extensions are supported
|
||||
return requiredExtensions.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Finds queue families that support required operations.
|
||||
*
|
||||
* @param device The physical device to check.
|
||||
* @return A QueueFamilyIndices struct with the found queue family indices.
|
||||
*
|
||||
* This function finds queue families that support graphics operations
|
||||
* and presentation to the window surface.
|
||||
*/
|
||||
fn findQueueFamilies(const vk::PhysicalDevice& device) -> QueueFamilyIndices {
|
||||
// Create a struct to store the queue family indices
|
||||
QueueFamilyIndices qfIndices;
|
||||
|
||||
// Get the queue family properties
|
||||
std::vector<vk::QueueFamilyProperties> queueFamilies = device.getQueueFamilyProperties();
|
||||
|
||||
// For every queue family,
|
||||
for (u32 i = 0; i < queueFamilies.size(); i++) {
|
||||
// Check if the queue family supports the required operations
|
||||
if (queueFamilies[i].queueFlags & vk::QueueFlagBits::eGraphics)
|
||||
qfIndices.graphics_family = i;
|
||||
|
||||
// Check if the queue family supports presentation
|
||||
vk::Bool32 queuePresentSupport = device.getSurfaceSupportKHR(i, mSurface.get());
|
||||
|
||||
// If the queue family supports presentation, set the present family index
|
||||
if (queuePresentSupport)
|
||||
qfIndices.present_family = i;
|
||||
|
||||
// If the queue family supports both operations, we're done
|
||||
if (qfIndices.isComplete())
|
||||
break;
|
||||
}
|
||||
|
||||
return qfIndices;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks if all requested validation layers are available.
|
||||
*
|
||||
|
|
|
@ -24,7 +24,10 @@ namespace constants {
|
|||
|
||||
// Validation layers
|
||||
#ifndef NDEBUG
|
||||
constexpr bool enableValidationLayers = true;
|
||||
constexpr std::array<const char*, 1> validationLayers = { "VK_LAYER_KHRONOS_validation" };
|
||||
#else
|
||||
constexpr bool enableValidationLayers = false;
|
||||
#endif
|
||||
|
||||
// Device extensions
|
||||
|
|
Loading…
Reference in a new issue