From 9a9fa710ff79188f9a7796a0e1b1729ce7b14d71 Mon Sep 17 00:00:00 2001 From: Jiga228 Date: Wed, 24 Sep 2025 21:48:34 +0700 Subject: [PATCH] Add create swapchain --- Core/Core/RenderEngine.cpp | 152 ++++++++++++++++++++++++++++++++++--- Core/Core/RenderEngine.h | 22 +++++- 2 files changed, 162 insertions(+), 12 deletions(-) diff --git a/Core/Core/RenderEngine.cpp b/Core/Core/RenderEngine.cpp index ba4ec23..e9bea64 100644 --- a/Core/Core/RenderEngine.cpp +++ b/Core/Core/RenderEngine.cpp @@ -1,5 +1,6 @@ #include "RenderEngine.h" +#include #include #include #include @@ -10,6 +11,10 @@ #include "GLFW/glfw3.h" +const std::vector RenderEngine::deviceExtensions = { + VK_KHR_SWAPCHAIN_EXTENSION_NAME +}; + #ifdef _DEBUG static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback( VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, @@ -31,6 +36,25 @@ VkResult RenderEngine::enable_layer_validation(VkDebugUtilsMessengerCreateInfoEX } #endif +RenderEngine::SwapchainSupportDetails RenderEngine::query_swapchain_details() +{ + SwapchainSupportDetails details; + + vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device_, surface_, &details.capabilities); + + uint32_t surface_format_cnt = 0; + VK_CHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device_, surface_, &surface_format_cnt, nullptr)); + details.formats.resize(surface_format_cnt); + VK_CHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device_, surface_, &surface_format_cnt, details.formats.data())); + + uint32_t present_modes_cnt = 0; + VK_CHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device_, surface_, &present_modes_cnt, nullptr)); + details.present_modes.resize(surface_format_cnt); + VK_CHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device_, surface_, &present_modes_cnt, details.present_modes.data())); + + return details; +} + std::vector RenderEngine::get_required_extensions() { uint32_t extensions_count = 0; @@ -58,9 +82,31 @@ bool RenderEngine::is_device_suitable(VkPhysicalDevice device, VkSurfaceKHR surf QueueFamilyIndices indices = find_queue_family_indices(device, surface); - return device_properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU - && device_features.geometryShader - && indices.is_complete(); + return indices.is_complete() && check_device_extensions_support(device); +} + +bool RenderEngine::check_device_extensions_support(VkPhysicalDevice device) +{ + uint32_t extension_count; + VK_CHECK(vkEnumerateDeviceExtensionProperties(device, nullptr, &extension_count, nullptr)); + std::vector available_extensions(extension_count); + VK_CHECK(vkEnumerateDeviceExtensionProperties(device, nullptr, &extension_count, available_extensions.data())); + + for (const auto& extension : deviceExtensions) + { + bool isFind = false; + for (const auto& i : available_extensions) + { + if (std::strcmp(i.extensionName, extension) == 0) + { + isFind = true; + break; + } + } + if (!isFind) + return false; + } + return true; } RenderEngine::QueueFamilyIndices RenderEngine::find_queue_family_indices(VkPhysicalDevice physical_device, VkSurfaceKHR surface) @@ -88,6 +134,43 @@ RenderEngine::QueueFamilyIndices RenderEngine::find_queue_family_indices(VkPhysi return queue_family_indices; } +VkSurfaceFormatKHR RenderEngine::choose_surface_format(const std::vector& surface_formats) +{ + for (const auto& i : surface_formats) + { + if (i.format == VK_FORMAT_B8G8R8A8_SRGB && i.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) + return i; + } + return surface_formats[0]; +} + +VkPresentModeKHR RenderEngine::choose_present_mode(const std::vector& present_modes, VkPresentModeKHR desired_present_mode) +{ + for (const auto& i : present_modes) + { + if (i == desired_present_mode) + return i; + } + return VK_PRESENT_MODE_FIFO_KHR; +} + +VkExtent2D RenderEngine::choose_extent(const VkSurfaceCapabilitiesKHR& capabilities, GLFWwindow* window) +{ + if (capabilities.currentExtent.width != std::numeric_limits::max()) + return capabilities.currentExtent; + else + { + int width, height; + glfwGetFramebufferSize(window, &width, &height); + VkExtent2D actualExtent = { + static_cast(width), + static_cast(height) + }; + actualExtent.width = std::max(capabilities.minImageExtent.width, std::min(capabilities.maxImageExtent.width, actualExtent.width)); + return actualExtent; + } +} + void RenderEngine::create_instance() { std::vector extensions = get_required_extensions(); @@ -107,7 +190,7 @@ void RenderEngine::create_instance() instance_create_info.enabledExtensionCount = static_cast(extensions.size()); instance_create_info.ppEnabledExtensionNames = extensions.data(); #ifdef _DEBUG - std::vector layers_validation = { + const std::vector layers_validation = { "VK_LAYER_KHRONOS_validation" }; instance_create_info.enabledLayerCount = static_cast(layers_validation.size()); @@ -168,17 +251,17 @@ void RenderEngine::create_logical_device() device_queue_create_info.queueCount = 1; queue_create_infos.push_back(device_queue_create_info); } - + VkDeviceCreateInfo device_create_info{}; device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; device_create_info.queueCreateInfoCount = static_cast(unique_queue_families.size()); device_create_info.pQueueCreateInfos = queue_create_infos.data(); device_create_info.pEnabledFeatures = &device_features; - device_create_info.enabledExtensionCount = 0; - device_create_info.ppEnabledExtensionNames = nullptr; + device_create_info.enabledExtensionCount = static_cast(deviceExtensions.size()); + device_create_info.ppEnabledExtensionNames = deviceExtensions.data(); #ifdef _DEBUG - std::vector layers_validation = { + const std::vector layers_validation = { "VK_LAYER_KHRONOS_validation" }; device_create_info.enabledLayerCount = static_cast(layers_validation.size()); @@ -193,12 +276,59 @@ void RenderEngine::create_logical_device() vkGetDeviceQueue(device_, indices.present_family.value(), 0, &present_queue_); } +void RenderEngine::create_swapchain(VkPresentModeKHR desired_present_mode) +{ + SwapchainSupportDetails swapchain_support = query_swapchain_details(); + VkSurfaceFormatKHR surface_format = choose_surface_format(swapchain_support.formats); + VkPresentModeKHR present_mode = choose_present_mode(swapchain_support.present_modes, desired_present_mode); + VkExtent2D extent = choose_extent(swapchain_support.capabilities, window_); + + uint32_t image_count = swapchain_support.capabilities.minImageCount + 1; + if (swapchain_support.capabilities.maxImageCount > 0 && image_count > swapchain_support.capabilities.maxImageCount) + image_count = swapchain_support.capabilities.maxImageCount; + + VkSwapchainCreateInfoKHR swapchain_create_info{}; + swapchain_create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; + swapchain_create_info.surface = surface_; + swapchain_create_info.minImageCount = image_count; + swapchain_create_info.imageFormat = surface_format.format; + swapchain_create_info.imageColorSpace = surface_format.colorSpace; + swapchain_create_info.imageExtent = extent; + swapchain_create_info.imageArrayLayers = 1; + swapchain_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + swapchain_create_info.preTransform = swapchain_support.capabilities.currentTransform; + swapchain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + swapchain_create_info.presentMode = present_mode; + swapchain_create_info.clipped = VK_TRUE; + swapchain_create_info.oldSwapchain = VK_NULL_HANDLE; + + QueueFamilyIndices family_indices = find_queue_family_indices(physical_device_, surface_); + uint32_t queue_family_indices[] = {family_indices.graphycs_family.value(), family_indices.present_family.value()}; + if (family_indices.graphycs_family != family_indices.present_family) + { + swapchain_create_info.imageSharingMode = VK_SHARING_MODE_CONCURRENT; + swapchain_create_info.queueFamilyIndexCount = 2; + swapchain_create_info.pQueueFamilyIndices = queue_family_indices; + } + else + { + swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + swapchain_create_info.queueFamilyIndexCount = 0; + swapchain_create_info.pQueueFamilyIndices = nullptr; + } + + VK_CHECK(vkCreateSwapchainKHR(device_, &swapchain_create_info, nullptr, &swapchain_)); + + swapchain_images_.resize(image_count); + vkGetSwapchainImagesKHR(device_, swapchain_, &image_count, swapchain_images_.data()); +} + void RenderEngine::create_surface() { VK_CHECK(glfwCreateWindowSurface(instance_, window_, nullptr, &surface_)); } -RenderEngine::RenderEngine(CoreInstance& core, GLFWwindow* window): +RenderEngine::RenderEngine(CoreInstance& core, GLFWwindow* window, VkPresentModeKHR desired_present_mode): core_(core), window_(window) #ifdef _DEBUG @@ -209,10 +339,14 @@ window_(window) create_surface(); pick_physical_device(); create_logical_device(); + create_swapchain(desired_present_mode); } RenderEngine::~RenderEngine() { + if (swapchain_ != VK_NULL_HANDLE) + vkDestroySwapchainKHR(device_, swapchain_, nullptr); + if (device_ != VK_NULL_HANDLE) vkDestroyDevice(device_, nullptr); diff --git a/Core/Core/RenderEngine.h b/Core/Core/RenderEngine.h index 51fc3c1..5ef70bc 100644 --- a/Core/Core/RenderEngine.h +++ b/Core/Core/RenderEngine.h @@ -25,6 +25,14 @@ class RenderEngine std::optional present_family; bool is_complete(); }; + struct SwapchainSupportDetails + { + VkSurfaceCapabilitiesKHR capabilities; + std::vector formats; + std::vector present_modes; + }; + + static const std::vector deviceExtensions; CoreInstance& core_; GLFWwindow* window_; @@ -34,23 +42,31 @@ class RenderEngine VkDevice device_ = VK_NULL_HANDLE; VkQueue graphics_queue_ = VK_NULL_HANDLE; VkQueue present_queue_ = VK_NULL_HANDLE; + VkSwapchainKHR swapchain_ = VK_NULL_HANDLE; + std::vector swapchain_images_; #ifdef _DEBUG VkResult enable_layer_validation(VkDebugUtilsMessengerCreateInfoEXT* create_info); VkDebugUtilsMessengerEXT debug_messenger_; #endif - + SwapchainSupportDetails query_swapchain_details(); + static std::vector get_required_extensions(); static bool is_device_suitable(VkPhysicalDevice device, VkSurfaceKHR surface); + static bool check_device_extensions_support(VkPhysicalDevice device); static QueueFamilyIndices find_queue_family_indices(VkPhysicalDevice physical_device, VkSurfaceKHR surface); - + static VkSurfaceFormatKHR choose_surface_format(const std::vector& surface_formats); + static VkPresentModeKHR choose_present_mode(const std::vector& present_modes, VkPresentModeKHR desired_present_mode); + static VkExtent2D choose_extent(const VkSurfaceCapabilitiesKHR& capabilities, GLFWwindow* window); + void create_instance(); void create_surface(); void pick_physical_device(); void create_logical_device(); + void create_swapchain(VkPresentModeKHR desired_present_mode); public: // Can throw the exception - RenderEngine(CoreInstance& core, GLFWwindow* window); + RenderEngine(CoreInstance& core, GLFWwindow* window, VkPresentModeKHR desired_present_mode = VK_PRESENT_MODE_MAILBOX_KHR); ~RenderEngine(); void start();