|
|
@@ -10,23 +10,35 @@
|
|
|
#include <stdexcept>
|
|
|
|
|
|
// VULKAN
|
|
|
-#include <VkBootstrap.h>
|
|
|
#include "vk_initializers.h"
|
|
|
|
|
|
using namespace coral_3d;
|
|
|
|
|
|
+coral_swapchain::coral_swapchain(coral_device& device, VkExtent2D extent, std::shared_ptr<coral_swapchain> old_swapchain)
|
|
|
+ : device_{ device }, window_extent_{ extent }, old_swapchain_{old_swapchain}
|
|
|
+{
|
|
|
+ init();
|
|
|
+
|
|
|
+ old_swapchain_ = nullptr;
|
|
|
+}
|
|
|
+
|
|
|
coral_swapchain::coral_swapchain(coral_device& device, VkExtent2D extent)
|
|
|
- :device_{ device }, window_extent_{ extent }
|
|
|
+ : device_{ device }, window_extent_{ extent }
|
|
|
{
|
|
|
- create_swapchain();
|
|
|
- create_render_pass();
|
|
|
- create_depth_resources();
|
|
|
- create_frame_buffers();
|
|
|
- create_sync_structures();
|
|
|
+ init();
|
|
|
}
|
|
|
|
|
|
coral_swapchain::~coral_swapchain()
|
|
|
{
|
|
|
+ for (auto image_view : swapchain_image_views_)
|
|
|
+ {
|
|
|
+ vkDestroyImageView(device_.device(), image_view, nullptr);
|
|
|
+ }
|
|
|
+ swapchain_image_views_.clear();
|
|
|
+
|
|
|
+ vkDestroySwapchainKHR(device_.device(), swapchain_, nullptr);
|
|
|
+ swapchain_ = nullptr;
|
|
|
+
|
|
|
deletion_queue_.flush();
|
|
|
}
|
|
|
|
|
|
@@ -38,7 +50,7 @@ VkFormat coral_swapchain::find_depth_format()
|
|
|
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT);
|
|
|
}
|
|
|
|
|
|
-VkResult coral_3d::coral_swapchain::aqcuire_next_image(uint32_t* image_index)
|
|
|
+VkResult coral_swapchain::aqcuire_next_image(uint32_t* image_index)
|
|
|
{
|
|
|
// NOTE: as of 04/07, vkDeviceWaitIdle is about 3% faster when rendering a single triangle.
|
|
|
vkDeviceWaitIdle(device_.device());
|
|
|
@@ -102,28 +114,103 @@ VkResult coral_swapchain::submit_command_buffer(const VkCommandBuffer* buffers,
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
+void coral_swapchain::init()
|
|
|
+{
|
|
|
+ create_swapchain();
|
|
|
+ create_image_views();
|
|
|
+ create_render_pass();
|
|
|
+ create_depth_resources();
|
|
|
+ create_frame_buffers();
|
|
|
+ create_sync_structures();
|
|
|
+}
|
|
|
+
|
|
|
void coral_swapchain::create_swapchain()
|
|
|
{
|
|
|
- vkb::SwapchainBuilder swapchain_builder{ device_.physical_device(), device_.device(), device_.surface() };
|
|
|
+ SwapchainSupportDetails swap_chain_support = device_.get_swapchain_support();
|
|
|
+
|
|
|
+ VkSurfaceFormatKHR surface_format = choose_swapchain_format(swap_chain_support.formats);
|
|
|
+ VkPresentModeKHR present_mode = choose_present_mode(swap_chain_support.present_modes);
|
|
|
+ VkExtent2D extent = choose_swap_extent(swap_chain_support.capabilities);
|
|
|
+
|
|
|
+ uint32_t image_count = swap_chain_support.capabilities.minImageCount + 1;
|
|
|
+ if (swap_chain_support.capabilities.maxImageCount > 0 &&
|
|
|
+ image_count > swap_chain_support.capabilities.maxImageCount)
|
|
|
+ {
|
|
|
+ image_count = swap_chain_support.capabilities.maxImageCount;
|
|
|
+ }
|
|
|
+
|
|
|
+ VkSwapchainCreateInfoKHR create_info = {};
|
|
|
+ create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
|
|
+ create_info.surface = device_.surface();
|
|
|
+
|
|
|
+ create_info.minImageCount = image_count;
|
|
|
+ create_info.imageFormat = surface_format.format;
|
|
|
+ create_info.imageColorSpace = surface_format.colorSpace;
|
|
|
+ create_info.imageExtent = extent;
|
|
|
+ create_info.imageArrayLayers = 1;
|
|
|
+ create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
|
|
+
|
|
|
+ QueueFamilyIndices indices = device_.find_physical_queue_families();
|
|
|
+ uint32_t queueFamilyIndices[] = { indices.graphics_family, indices.present_family };
|
|
|
+
|
|
|
+ if (indices.graphics_family != indices.present_family) {
|
|
|
+ create_info.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
|
|
|
+ create_info.queueFamilyIndexCount = 2;
|
|
|
+ create_info.pQueueFamilyIndices = queueFamilyIndices;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
|
|
+ create_info.queueFamilyIndexCount = 0; // Optional
|
|
|
+ create_info.pQueueFamilyIndices = nullptr; // Optional
|
|
|
+ }
|
|
|
+
|
|
|
+ create_info.preTransform = swap_chain_support.capabilities.currentTransform;
|
|
|
+ create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
|
|
+
|
|
|
+ create_info.presentMode = present_mode;
|
|
|
+ create_info.clipped = VK_TRUE;
|
|
|
+
|
|
|
+ create_info.oldSwapchain = old_swapchain_ == nullptr ? VK_NULL_HANDLE : old_swapchain_->swapchain_;
|
|
|
|
|
|
- vkb::Swapchain vkb_swapchain = swapchain_builder
|
|
|
- .use_default_format_selection()
|
|
|
- // use VSync present mode
|
|
|
- .set_desired_present_mode(VK_PRESENT_MODE_MAILBOX_KHR)
|
|
|
- .set_desired_extent(window_extent_.width, window_extent_.height)
|
|
|
- .build()
|
|
|
- .value();
|
|
|
+ if (vkCreateSwapchainKHR(device_.device(), &create_info, nullptr, &swapchain_) != VK_SUCCESS)
|
|
|
+ throw std::runtime_error("ERROR! coral_swapchain::create_swapchain() >> Failed to create swapchain!");
|
|
|
|
|
|
- // store swap chain and its related data
|
|
|
- swapchain_ = vkb_swapchain.swapchain;
|
|
|
- swapchain_images_ = vkb_swapchain.get_images().value();
|
|
|
- swapchain_image_views_ = vkb_swapchain.get_image_views().value();
|
|
|
- swapchain_image_format_ = vkb_swapchain.image_format;
|
|
|
+ // we only specified a minimum number of images in the swap chain, so the implementation is
|
|
|
+ // allowed to create a swap chain with more. That's why we'll first query the final number of
|
|
|
+ // images with vkGetSwapchainImagesKHR, then resize the container and finally call it again to
|
|
|
+ // retrieve the handles.
|
|
|
+ vkGetSwapchainImagesKHR(device_.device(), swapchain_, &image_count, nullptr);
|
|
|
+ swapchain_images_.resize(image_count);
|
|
|
+ vkGetSwapchainImagesKHR(device_.device(), swapchain_, &image_count, swapchain_images_.data());
|
|
|
|
|
|
- swapchain_extent_ = vkb_swapchain.extent;
|
|
|
+ swapchain_image_format_ = surface_format.format;
|
|
|
+ swapchain_extent_ = extent;
|
|
|
+}
|
|
|
+
|
|
|
+void coral_swapchain::create_image_views()
|
|
|
+{
|
|
|
+ swapchain_image_views_.resize(swapchain_images_.size());
|
|
|
+
|
|
|
+ for (size_t i = 0; i < swapchain_images_.size(); i++)
|
|
|
+ {
|
|
|
+ VkImageViewCreateInfo viewInfo{};
|
|
|
+ viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
|
|
+ viewInfo.image = swapchain_images_[i];
|
|
|
+ viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
|
|
+ viewInfo.format = swapchain_image_format_;
|
|
|
+ viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
|
+ viewInfo.subresourceRange.baseMipLevel = 0;
|
|
|
+ viewInfo.subresourceRange.levelCount = 1;
|
|
|
+ viewInfo.subresourceRange.baseArrayLayer = 0;
|
|
|
+ viewInfo.subresourceRange.layerCount = 1;
|
|
|
+
|
|
|
+ if (vkCreateImageView(device_.device(), &viewInfo, nullptr, &swapchain_image_views_[i]) != VK_SUCCESS)
|
|
|
+ throw std::runtime_error("ERROR! coral_swapchain::create_image_views() >> Failed to create image view!");
|
|
|
+ }
|
|
|
|
|
|
deletion_queue_.deletors.emplace_back([=]() {
|
|
|
- vkDestroySwapchainKHR(device_.device(), swapchain_, nullptr);
|
|
|
+ // swapchain_image_views_.clear();
|
|
|
});
|
|
|
}
|
|
|
|
|
|
@@ -266,7 +353,7 @@ void coral_swapchain::create_frame_buffers()
|
|
|
|
|
|
deletion_queue_.deletors.emplace_back([=]() {
|
|
|
vkDestroyFramebuffer(device_.device(), swapchain_frame_buffers_[i], nullptr);
|
|
|
- vkDestroyImageView(device_.device(), swapchain_image_views_[i], nullptr);
|
|
|
+ // vkDestroyImageView(device_.device(), swapchain_image_views_[i], nullptr);
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
@@ -298,4 +385,51 @@ void coral_swapchain::create_sync_structures()
|
|
|
vkDestroySemaphore(device_.device(), frames_[i].render_semaphore, nullptr);
|
|
|
});
|
|
|
}
|
|
|
+}
|
|
|
+
|
|
|
+VkSurfaceFormatKHR coral_swapchain::choose_swapchain_format(const std::vector<VkSurfaceFormatKHR>& available_formats)
|
|
|
+{
|
|
|
+ for (const auto& available_format : available_formats)
|
|
|
+ {
|
|
|
+ if (available_format.format == VK_FORMAT_B8G8R8A8_SRGB &&
|
|
|
+ available_format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
|
|
|
+ {
|
|
|
+ return available_format;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return available_formats[0];
|
|
|
+}
|
|
|
+
|
|
|
+VkPresentModeKHR coral_swapchain::choose_present_mode(const std::vector<VkPresentModeKHR>& available_present_modes)
|
|
|
+{
|
|
|
+ for (const auto& available_present_mode : available_present_modes)
|
|
|
+ {
|
|
|
+ if (available_present_mode == VK_PRESENT_MODE_MAILBOX_KHR)
|
|
|
+ {
|
|
|
+ std::cout << "Present mode: Mailbox" << std::endl;
|
|
|
+ return available_present_mode;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+VkExtent2D coral_swapchain::choose_swap_extent(const VkSurfaceCapabilitiesKHR& capabilities)
|
|
|
+{
|
|
|
+ if (capabilities.currentExtent.width != std::numeric_limits<uint32_t>::max())
|
|
|
+ {
|
|
|
+ return capabilities.currentExtent;
|
|
|
+ }
|
|
|
+
|
|
|
+ else
|
|
|
+ {
|
|
|
+ VkExtent2D actualExtent = window_extent_;
|
|
|
+ actualExtent.width = std::max(
|
|
|
+ capabilities.minImageExtent.width,
|
|
|
+ std::min(capabilities.maxImageExtent.width, actualExtent.width));
|
|
|
+ actualExtent.height = std::max(
|
|
|
+ capabilities.minImageExtent.height,
|
|
|
+ std::min(capabilities.maxImageExtent.height, actualExtent.height));
|
|
|
+
|
|
|
+ return actualExtent;
|
|
|
+ }
|
|
|
}
|