From 979334a2f9a99fbe1222a49ee1c2302214bc2dfc Mon Sep 17 00:00:00 2001 From: vimene Date: Mon, 15 Dec 2025 04:26:01 +0100 Subject: added logical devices and queues --- src/engine.cpp | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 119 insertions(+), 14 deletions(-) diff --git a/src/engine.cpp b/src/engine.cpp index 0e29d60..f548e75 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -294,7 +294,7 @@ static int main_term() { #define SCREEN_HEIGHT 480 static const std::vector validation_layers = { - "VK_LAYER_KHRONOS_validation" + "VK_LAYER_KHRONOS_validation", }; static const std::vector device_exts = { @@ -335,13 +335,47 @@ static bool check_validation_layer_support() { return true; } +static std::string severity_to_str(VkDebugUtilsMessageSeverityFlagBitsEXT severity) { + std::string s; + bool first = true; + if (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) { + if (!first) + s += ", "; + else + first = false; + s += "VERBOSE"; + } + if (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) { + if (!first) + s += ", "; + else + first = false; + s += "INFO"; + } + if (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) { + if (!first) + s += ", "; + else + first = false; + s += "WARNING"; + } + if (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) { + if (!first) + s += ", "; + else + first = false; + s += "ERROR"; + } + return s; +} + // TODO: remove [[maybe_unused]] static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback( - [[maybe_unused]] VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, + VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, [[maybe_unused]] VkDebugUtilsMessageTypeFlagsEXT message_type, const VkDebugUtilsMessengerCallbackDataEXT* callback_data, [[maybe_unused]] void* user_data) { - std::cerr << "validation layer: " << callback_data->pMessage << std::endl; + std::cerr << "validation layer: [" << severity_to_str(message_severity) << "] " << callback_data->pMessage << std::endl; return VK_FALSE; } @@ -358,6 +392,13 @@ static void populate_msger_create_info(VkDebugUtilsMessengerCreateInfoEXT& msger msger_create_info.pUserData = nullptr; } +static uint32_t find_queue_family_index(const std::vector& queue_family_properties) { + auto it = std::ranges::find_if(queue_family_properties, [](const auto& prop) { + return (prop.queueFamilyProperties.queueFlags & VK_QUEUE_GRAPHICS_BIT) != static_cast(0); + }); + return static_cast(std::distance(queue_family_properties.begin(), it)); +} + static int main_graphical() { // init window glfwInit(); @@ -366,6 +407,12 @@ static int main_graphical() { GLFWwindow* window = glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Engine", nullptr, nullptr); // init Vulkan + std::cout << "Vulkan loader version: " + << VK_API_VERSION_MAJOR(VK_HEADER_VERSION_COMPLETE) + << "." << VK_API_VERSION_MINOR(VK_HEADER_VERSION_COMPLETE) + << "." << VK_API_VERSION_PATCH(VK_HEADER_VERSION_COMPLETE) + << std::endl; + // init Vulkan - create instance if (enable_validation_layers && !check_validation_layer_support()) { std::cerr << "validation layers requested, but not available!" << std::endl; @@ -399,14 +446,18 @@ static int main_graphical() { vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, available_extensions.data()); std::cout << "vulkan extensions:\n"; - for (const auto& extension : available_extensions) - std::cout << " " << extension.extensionName << "\n"; + for (const auto& extension : available_extensions) { + std::cout + << (std::ranges::find_if(extensions, [avail_ext_name=extension.extensionName](const auto& ext_name) { return strcmp(ext_name, avail_ext_name) == 0; }) + != extensions.end() ? "*" : " "); + std::cout << " " << extension.extensionName << "\n"; + } std::cout << "\n"; std::cout << "required extensions:\n"; for (const auto& extension_name : extensions) - std::cout << " " << extension_name << "\n"; + std::cout << " " << extension_name << "\n"; VkInstanceCreateInfo create_info{}; create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; @@ -468,17 +519,19 @@ static int main_graphical() { features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; vkGetPhysicalDeviceFeatures2(physical_device, &features); - uint32_t queue_family_properties_count; - vkGetPhysicalDeviceQueueFamilyProperties2(physical_device, &queue_family_properties_count, nullptr); - std::vector queue_family_properties(queue_family_properties_count); - vkGetPhysicalDeviceQueueFamilyProperties2(physical_device, &queue_family_properties_count, queue_family_properties.data()); - // TODO: found a better name, too confusing with device_exts uint32_t ext_props_count; vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &ext_props_count, nullptr); std::vector ext_props(ext_props_count); vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &ext_props_count, ext_props.data()); + uint32_t queue_family_properties_count; + vkGetPhysicalDeviceQueueFamilyProperties2(physical_device, &queue_family_properties_count, nullptr); + std::vector queue_family_properties(queue_family_properties_count); + for (auto& elt : queue_family_properties) + elt.sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2; + vkGetPhysicalDeviceQueueFamilyProperties2(physical_device, &queue_family_properties_count, queue_family_properties.data()); + std::cout << "structure type: " << string_VkStructureType(properties.sType) << std::endl; std::cout << "pNext: " << properties.pNext << std::endl; std::cout << "apiVersion: (variant " << VK_API_VERSION_VARIANT(properties.properties.apiVersion) << ") " @@ -572,9 +625,7 @@ static int main_graphical() { if (VK_API_VERSION_VARIANT(properties.properties.apiVersion) != 0 || properties.properties.apiVersion < VK_API_VERSION_1_4) return false; - if (std::ranges::find_if(queue_family_properties, [](const auto& prop) { - return (prop.queueFamilyProperties.queueFlags & VK_QUEUE_GRAPHICS_BIT) != static_cast(0); - }) == queue_family_properties.end()) + if (find_queue_family_index(queue_family_properties) == queue_family_properties.size()) return false; if (std::ranges::find_if_not(device_exts, [&ext_props](const auto& device_ext) { return std::ranges::find_if(ext_props, @@ -598,12 +649,66 @@ static int main_graphical() { std::exit(EXIT_FAILURE); } + // TODO: shouldn't fetch twice (already fetched while selecting physical device) + uint32_t queue_family_index = [device]() { + uint32_t queue_family_properties_count; + vkGetPhysicalDeviceQueueFamilyProperties2(device, &queue_family_properties_count, nullptr); + std::vector queue_family_properties(queue_family_properties_count); + for (auto& elt : queue_family_properties) + elt.sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2; + vkGetPhysicalDeviceQueueFamilyProperties2(device, &queue_family_properties_count, queue_family_properties.data()); + + // don't need to check if it's found, we already checked that in device seleciton + return find_queue_family_index(queue_family_properties); + }(); + + float queue_priority = .5f; + VkDeviceQueueCreateInfo deviceQueueCreateInfo{}; + deviceQueueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + deviceQueueCreateInfo.queueFamilyIndex = queue_family_index; + deviceQueueCreateInfo.queueCount = 1; + deviceQueueCreateInfo.pQueuePriorities = &queue_priority; + + VkDeviceCreateInfo device_create_info{}; + device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + device_create_info.queueCreateInfoCount = 1; + device_create_info.pQueueCreateInfos = &deviceQueueCreateInfo; + device_create_info.enabledExtensionCount = static_cast(device_exts.size()); + device_create_info.ppEnabledExtensionNames = device_exts.data(); + + // set everything to false + VkPhysicalDeviceFeatures2 device_features{}; + device_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; + device_create_info.pNext = &device_features; + + VkPhysicalDeviceVulkan13Features device_vk13_features{}; + device_vk13_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES; + device_vk13_features.dynamicRendering = VK_TRUE; + device_features.pNext = &device_vk13_features; + + VkPhysicalDeviceExtendedDynamicStateFeaturesEXT device_eds_features{}; + device_eds_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT; + device_eds_features.extendedDynamicState = VK_TRUE; + device_vk13_features.pNext = &device_eds_features; + + // TODO: rename to just "device", and rename "device" to "physical_device" + VkDevice logical_device; + if (VkResult res = vkCreateDevice(device, &device_create_info, nullptr, &logical_device); res != VK_SUCCESS) { + std::cerr << "failed to create device: " << string_VkResult(res) << std::endl; + std::exit(EXIT_FAILURE); + } + + VkQueue graphics_queue; + vkGetDeviceQueue(logical_device, queue_family_index, 0, &graphics_queue); + // main loop while (!glfwWindowShouldClose(window)) { glfwPollEvents(); } // cleanup + vkDestroyDevice(logical_device, nullptr); + if (enable_validation_layers) { auto destroy_debug_messenger = (PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT"); if (!destroy_debug_messenger) { -- cgit v1.2.3