From c3409e800b80fa383eff37ef5382b6661dadb976 Mon Sep 17 00:00:00 2001 From: vimene Date: Sat, 20 Dec 2025 23:32:33 +0100 Subject: still more code refactoring --- src/engine.cpp | 182 +++++++++++++++++++++++++++------------------------------ 1 file changed, 85 insertions(+), 97 deletions(-) diff --git a/src/engine.cpp b/src/engine.cpp index aa9c644..0cf829a 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -303,7 +303,7 @@ static const std::vector validation_layers = { "VK_LAYER_KHRONOS_validation", }; -static const std::vector device_exts = { +static const std::vector physical_device_ext_names = { VK_KHR_SWAPCHAIN_EXTENSION_NAME, VK_KHR_SPIRV_1_4_EXTENSION_NAME, VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME, @@ -325,30 +325,24 @@ struct PhysicalDeviceEntry { }; static bool check_validation_layer_support() { - uint32_t layer_count; - if (VkResult res = vkEnumerateInstanceLayerProperties(&layer_count, nullptr); res != VK_SUCCESS) { - std::cerr << "failed to enumerate instance layer properties, error code: " << string_VkResult(res) << std::endl; - std::exit(EXIT_FAILURE); - } - std::vector available_layers(layer_count); - if (VkResult res = vkEnumerateInstanceLayerProperties(&layer_count, available_layers.data()); res != VK_SUCCESS) { - std::cerr << "failed to enumerate instance layer properties, error code: " << string_VkResult(res) << std::endl; - std::exit(EXIT_FAILURE); - } - - for (const char* layer_name : validation_layers) { - bool layer_found = false; - - for (const auto& layer_properties : available_layers) { - if (strcmp(layer_name, layer_properties.layerName) == 0) { - layer_found = true; - break; - } + auto avail_layers = [&]() { + uint32_t avail_layers_count; + if (VkResult res = vkEnumerateInstanceLayerProperties(&avail_layers_count, nullptr); res != VK_SUCCESS) { + std::cerr << "failed to enumerate instance layer properties, error code: " << string_VkResult(res) << std::endl; + std::exit(EXIT_FAILURE); + } + std::vector avail_layers(avail_layers_count); + if (VkResult res = vkEnumerateInstanceLayerProperties(&avail_layers_count, avail_layers.data()); res != VK_SUCCESS) { + std::cerr << "failed to enumerate instance layer properties, error code: " << string_VkResult(res) << std::endl; + std::exit(EXIT_FAILURE); } + return avail_layers; + }(); - if (!layer_found) { + for (const char* layer_name : validation_layers) { + if (std::ranges::find_if(avail_layers, [&](const auto& props) { return strcmp(layer_name, props.layerName) == 0; }) + == avail_layers.end()) return false; - } } return true; @@ -356,25 +350,19 @@ static bool check_validation_layer_support() { static std::string severity_to_str(VkDebugUtilsMessageSeverityFlagBitsEXT severity) { switch (severity) { - case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: - return "VERBOSE"; - case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: - return "INFO"; - case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: - return "WARNING"; - case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: - return "ERROR"; - default: - std::unreachable(); + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: return "VERBOSE"; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: return "INFO"; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: return "WARNING"; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: return "ERROR"; + default: std::unreachable(); } } -// TODO: remove [[maybe_unused]] static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback( VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, - [[maybe_unused]] VkDebugUtilsMessageTypeFlagsEXT message_type, + VkDebugUtilsMessageTypeFlagsEXT /* message_type */, const VkDebugUtilsMessengerCallbackDataEXT* callback_data, - [[maybe_unused]] void* user_data) { + void* /* user_data */) { std::cerr << "validation layer: [" << severity_to_str(message_severity) << "] " << callback_data->pMessage << std::endl; return VK_FALSE; } @@ -593,9 +581,6 @@ static int main_graphical() { for (uint32_t i = 0; i < avail_physical_devices.size(); i++) { const auto& avail_physical_device = avail_physical_devices[i]; - PhysicalDeviceEntry physical_device_entry; - physical_device_entry.physical_device = avail_physical_device; - auto physical_device_props = [&]() { VkPhysicalDeviceProperties2 physical_device_props{}; physical_device_props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; @@ -606,7 +591,7 @@ static int main_graphical() { std::cout << " " << (i + 1) << ". " << physical_device_props.properties.deviceName << ":" << std::endl; std::cout << " apiVersion: " << engine::myvk::api { physical_device_props.properties.apiVersion } << std::endl; - physical_device_entry.features = [&]() { + auto physical_device_features = [&]() { VkPhysicalDeviceFeatures2 physical_device_features{}; physical_device_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; vkGetPhysicalDeviceFeatures2(avail_physical_device, &physical_device_features); @@ -630,7 +615,7 @@ static int main_graphical() { }(); std::cout << " required physical device extensions:" << std::endl; - for (const auto& ext : device_exts) { + for (const auto& ext : physical_device_ext_names) { std::cout << " " << (std::ranges::find_if(physical_device_ext_props, [&](const auto& avail_ext) { return strcmp(avail_ext.extensionName, ext) == 0; }) == physical_device_ext_props.end() ? "!" : " "); @@ -667,47 +652,47 @@ static int main_graphical() { return std::optional {}; if (!graphics_queue_family_index || !present_queue_family_index) return std::optional {}; - if (std::ranges::find_if_not(device_exts, [&](const auto& device_ext) { + if (std::ranges::find_if_not(physical_device_ext_names, [&](const auto& device_ext) { return std::ranges::find_if(physical_device_ext_props, [&](const auto& ext_prop) { return strcmp(ext_prop.extensionName, device_ext) == 0; }) != physical_device_ext_props.end(); - }) != device_exts.end()) + }) != physical_device_ext_names.end()) return std::optional {}; unsigned score = 0; if (*graphics_queue_family_index == *present_queue_family_index) score += 5; - switch (physical_device_props.properties.deviceType) { - case VK_PHYSICAL_DEVICE_TYPE_OTHER: - score += 0; - break; - case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: - score += 2; - break; - case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: - score += 10; - break; - case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: - score += 5; - break; - case VK_PHYSICAL_DEVICE_TYPE_CPU: - score += 1; - break; - default: - // TODO: make it better, because if in the future vulkan add more device types, - // it can crash - std::unreachable(); - } + + score += [&](VkPhysicalDeviceType device_type) { + switch (device_type) { + case VK_PHYSICAL_DEVICE_TYPE_OTHER: return 0; + case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: return 2; + case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: return 10; + case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: return 5; + case VK_PHYSICAL_DEVICE_TYPE_CPU: return 1; + default: + { + std::cerr << "device type not supported: " << string_VkPhysicalDeviceType(device_type) << std::endl; + std::exit(EXIT_FAILURE); + } + } + }(physical_device_props.properties.deviceType); + return std::optional { score }; }(); std::cout << " is suitable: " << std::boolalpha << static_cast(score) << std::noboolalpha << std::endl; - if (score) { - physical_device_entry.graphics_queue_family_index = *graphics_queue_family_index; - physical_device_entry.present_queue_family_index = *present_queue_family_index; - physical_device_entry.name = physical_device_props.properties.deviceName; - physical_devices.insert({ *score, physical_device_entry }); - } + if (score) + physical_devices.insert({ *score, + { + .idx = i, + .physical_device = avail_physical_device, + .name = physical_device_props.properties.deviceName, + .graphics_queue_family_index = *graphics_queue_family_index, + .present_queue_family_index = *present_queue_family_index, + .features = physical_device_features, + } + }); } std::cout << std::endl; @@ -787,8 +772,8 @@ static int main_graphical() { .pQueueCreateInfos = device_queue_cis.data(), .enabledLayerCount = {}, .ppEnabledLayerNames = {}, - .enabledExtensionCount = static_cast(device_exts.size()), - .ppEnabledExtensionNames = device_exts.data(), + .enabledExtensionCount = static_cast(physical_device_ext_names.size()), + .ppEnabledExtensionNames = physical_device_ext_names.data(), .pEnabledFeatures = {}, }; @@ -836,16 +821,19 @@ static int main_graphical() { }(); auto surface_format = [&]() { - uint32_t surface_formats_count; - if (VkResult res = vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &surface_formats_count, nullptr); res != VK_SUCCESS) { - std::cerr << "failed to get physical device surface formats, error code: " << string_VkResult(res) << std::endl; - std::exit(EXIT_FAILURE); - } - std::vector surface_formats(surface_formats_count); - if (VkResult res = vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &surface_formats_count, surface_formats.data()); res != VK_SUCCESS) { - std::cerr << "failed to get physical device surface formats, error code: " << string_VkResult(res) << std::endl; - std::exit(EXIT_FAILURE); - } + auto surface_formats = [&]() { + uint32_t surface_formats_count; + if (VkResult res = vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &surface_formats_count, nullptr); res != VK_SUCCESS) { + std::cerr << "failed to get physical device surface formats, error code: " << string_VkResult(res) << std::endl; + std::exit(EXIT_FAILURE); + } + std::vector surface_formats(surface_formats_count); + if (VkResult res = vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &surface_formats_count, surface_formats.data()); res != VK_SUCCESS) { + std::cerr << "failed to get physical device surface formats, error code: " << string_VkResult(res) << std::endl; + std::exit(EXIT_FAILURE); + } + return surface_formats; + }(); for (const auto& surface_format : surface_formats) { if (surface_format.format == VK_FORMAT_B8G8R8A8_SRGB @@ -968,19 +956,19 @@ static int main_graphical() { auto [pl_layout, graphics_pl] = [&]() { // reading shader file auto shader_module = [&]() { - // shader code has to be 32-bits aligned, which is the case with the default allocator - std::vector shader_code; - { + auto shader_code = [&]() { const char* shader_file_name = SHADERSDIR "/shader.spv"; std::ifstream shader_file(shader_file_name, std::ios::ate | std::ios::binary); if (!shader_file.is_open()) { - std::cerr << "file `" << shader_file_name << "'not found" << std::endl; // TODO: improve + std::cerr << "file `" << shader_file_name << "' not found" << std::endl; // TODO: improve std::exit(EXIT_SUCCESS); } - shader_code.resize(shader_file.tellg()); + // shader code has to be 32-bits aligned, which is the case with the default allocator + std::vector shader_code(shader_file.tellg()); shader_file.seekg(0, std::ios::beg); shader_file.read(shader_code.data(), static_cast(shader_code.size())); - } + return shader_code; + }(); VkShaderModuleCreateInfo shader_module_ci { .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, @@ -998,7 +986,7 @@ static int main_graphical() { }(); auto [pl_layout, graphics_pl] = [&]() { - std::array pl_shader_stage_create_infos { + std::array pl_shader_stage_cis { VkPipelineShaderStageCreateInfo { .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, .pNext = nullptr, @@ -1146,8 +1134,8 @@ static int main_graphical() { .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .pNext = &pl_render_ci, .flags = {}, - .stageCount = 2, - .pStages = pl_shader_stage_create_infos.data(), + .stageCount = static_cast(pl_shader_stage_cis.size()), + .pStages = pl_shader_stage_cis.data(), .pVertexInputState = &pl_vert_in_state_ci, .pInputAssemblyState = &pl_in_asm_state_ci, .pTessellationState = {}, @@ -1250,6 +1238,11 @@ static int main_graphical() { while (!glfwWindowShouldClose(window)) { glfwPollEvents(); + if (VkResult res = vkWaitForFences(device, 1, &fence_draw, VK_TRUE, std::numeric_limits::max()); res != VK_SUCCESS) { + std::cerr << "failed to wait for draw fence, error code: " << string_VkResult(res) << std::endl; + std::exit(EXIT_FAILURE); + } + if (VkResult res = vkQueueWaitIdle(present_queue); res != VK_SUCCESS) { std::cerr << "failed to wait idle for graphics queue, error code: " << string_VkResult(res) << std::endl; std::exit(EXIT_FAILURE); @@ -1373,11 +1366,6 @@ static int main_graphical() { } } - if (VkResult res = vkWaitForFences(device, 1, &fence_draw, VK_TRUE, std::numeric_limits::max()); res != VK_SUCCESS) { - std::cerr << "failed to wait for draw fence, error code: " << string_VkResult(res) << std::endl; - std::exit(EXIT_FAILURE); - } - { VkPresentInfoKHR present_info { .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, @@ -1408,8 +1396,8 @@ static int main_graphical() { vkDestroyCommandPool(device, cmd_pool, nullptr); vkDestroyPipeline(device, graphics_pl, nullptr); vkDestroyPipelineLayout(device, pl_layout, nullptr); - for (const auto img_view : swapchain_img_views) - vkDestroyImageView(device, img_view, nullptr); + for (auto it_img_view = swapchain_img_views.rbegin(); it_img_view != swapchain_img_views.rend(); ++it_img_view) + vkDestroyImageView(device, *it_img_view, nullptr); vkDestroySwapchainKHR(device, swapchain, nullptr); vkDestroySurfaceKHR(instance, surface, nullptr); vkDestroyDevice(device, nullptr); -- cgit v1.2.3