Files
UwU-Engine/UwURenderEngine/RenderEngine/VkObjects/Swapchain.cpp
T

151 lines
6.7 KiB
C++

#include "Swapchain.hpp"
#include <set>
#include <stdexcept>
#include <string>
#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<VkSurfaceFormatKHR>& 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<VkPresentModeKHR>& 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<uint32_t> queue_family_indices = { family_indices.graphics_family,
family_indices.present_family,
family_indices.transfer_family };
std::vector<uint32_t> 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<uint32_t>(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);
}