#include "Swapchain.hpp" #include #include #include #include "Device.hpp" #include "PhysicalDevice.hpp" #include "Surface.hpp" #include "DeviceFunctions/DeviceFunctions.hpp" VkObjects::Swapchain::SwapchainSupportDetails VkObjects::Swapchain::query_swapchain_details(const Surface& surface, const PhysicalDevice& physical_device) { SwapchainSupportDetails details; vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device.get_native(), surface.get_native(), &details.capabilities); uint32_t surface_format_cnt = 0; VK_CHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device.get_native(), surface.get_native(), &surface_format_cnt, nullptr)) details.formats.resize(surface_format_cnt); VK_CHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device.get_native(), surface.get_native(), &surface_format_cnt, details.formats.data())) uint32_t present_modes_cnt = 0; VK_CHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device.get_native(), surface.get_native(), &present_modes_cnt, nullptr)) details.present_modes.resize(surface_format_cnt); VK_CHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device.get_native(), surface.get_native(), &present_modes_cnt, details.present_modes.data())) return details; } VkSurfaceFormatKHR VkObjects::Swapchain::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 VkObjects::Swapchain::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; } void VkObjects::Swapchain::create_swapchain(const Surface& surface, const PhysicalDevice& physical_device, GLFWwindow* window) { SwapchainSupportDetails swapchain_support = query_swapchain_details(surface, physical_device); VkSurfaceFormatKHR surface_format = choose_surface_format(swapchain_support.formats); VkPresentModeKHR present_mode = choose_present_mode(swapchain_support.present_modes, VK_PRESENT_MODE_MAILBOX_KHR); VkExtent2D extent = DeviceFunctions::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.get_native(); 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; VkObjects::PhysicalDevice::QueueFamilyIndices family_indices = physical_device.get_queue_family_indices(); const std::set queue_family_indices = { family_indices.graphics_family, family_indices.present_family, family_indices.transfer_family }; std::vector arr_families; if (queue_family_indices.size() > 1) { arr_families.reserve(queue_family_indices.size()); for(auto& i : queue_family_indices) arr_families.push_back(i); swapchain_create_info.imageSharingMode = VK_SHARING_MODE_CONCURRENT; swapchain_create_info.queueFamilyIndexCount = static_cast(arr_families.size()); swapchain_create_info.pQueueFamilyIndices = arr_families.data(); } else { swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; swapchain_create_info.queueFamilyIndexCount = 0; swapchain_create_info.pQueueFamilyIndices = nullptr; } VK_CHECK(vkCreateSwapchainKHR(device_.get_native(), &swapchain_create_info, nullptr, &swapchain_)) vkGetSwapchainImagesKHR(device_.get_native(), swapchain_, &image_count, nullptr); swapchain_images_.resize(image_count); vkGetSwapchainImagesKHR(device_.get_native(), swapchain_, &image_count, swapchain_images_.data()); swapchain_image_format_ = surface_format.format; swapchain_extent_ = extent; } void VkObjects::Swapchain::create_image_views() { VkImageViewCreateInfo image_view_info{}; image_view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; image_view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; image_view_info.format = swapchain_image_format_; image_view_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; image_view_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; image_view_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; image_view_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; image_view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; image_view_info.subresourceRange.baseMipLevel = 0; image_view_info.subresourceRange.levelCount = 1; image_view_info.subresourceRange.baseArrayLayer = 0; image_view_info.subresourceRange.layerCount = 1; swapchain_image_views_.resize(swapchain_images_.size()); for (uint32_t i = 0; i < swapchain_images_.size(); ++i) { image_view_info.image = swapchain_images_[i]; VK_CHECK(vkCreateImageView(device_.get_native(), &image_view_info, nullptr, &swapchain_image_views_[i])) } } VkObjects::Swapchain::Swapchain(const Surface& surface, const PhysicalDevice& physical_device, const Device& device, GLFWwindow* window): device_(device) { create_swapchain(surface, physical_device, window); create_image_views(); } VkObjects::Swapchain::~Swapchain() { for (auto image_view : swapchain_image_views_) vkDestroyImageView(device_.get_native(), image_view, nullptr); swapchain_image_views_.clear(); if (swapchain_ != nullptr) vkDestroySwapchainKHR(device_.get_native(), swapchain_, nullptr); }