151 lines
6.7 KiB
C++
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);
|
|
}
|