initial commit
This commit is contained in:
+327
@@ -0,0 +1,327 @@
|
||||
#include "Swapchain.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace
|
||||
{
|
||||
const char* presentModeName(VkPresentModeKHR mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case VK_PRESENT_MODE_FIFO_KHR:
|
||||
return "fifo";
|
||||
|
||||
case VK_PRESENT_MODE_MAILBOX_KHR:
|
||||
return "mailbox";
|
||||
|
||||
case VK_PRESENT_MODE_IMMEDIATE_KHR:
|
||||
return "immediate";
|
||||
|
||||
default:
|
||||
return "other";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Swapchain::Swapchain(
|
||||
VkDevice device,
|
||||
VkPhysicalDevice physicalDevice,
|
||||
VkSurfaceKHR surface,
|
||||
VkRenderPass renderPass,
|
||||
VkPresentModeKHR preferredPresentMode,
|
||||
uint32_t windowWidth,
|
||||
uint32_t windowHeight)
|
||||
: m_device(device)
|
||||
, m_physicalDevice(physicalDevice)
|
||||
, m_surface(surface)
|
||||
, m_preferredPresentMode(preferredPresentMode)
|
||||
{
|
||||
createSwapchain(windowWidth, windowHeight);
|
||||
createImageViews();
|
||||
createFramebuffers(renderPass);
|
||||
|
||||
std::cout << "Swapchain created ("
|
||||
<< m_imageCount << " images)"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
Swapchain::~Swapchain()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void Swapchain::recreate(
|
||||
VkRenderPass renderPass,
|
||||
uint32_t windowWidth,
|
||||
uint32_t windowHeight)
|
||||
{
|
||||
destroy();
|
||||
createSwapchain(windowWidth, windowHeight);
|
||||
createImageViews();
|
||||
createFramebuffers(renderPass);
|
||||
|
||||
std::cout << "Swapchain recreated ("
|
||||
<< m_imageCount << " images)"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
void Swapchain::createSwapchain(
|
||||
uint32_t windowWidth,
|
||||
uint32_t windowHeight)
|
||||
{
|
||||
SwapchainSupportDetails support =
|
||||
querySwapchainSupport(
|
||||
m_physicalDevice,
|
||||
m_surface
|
||||
);
|
||||
|
||||
m_surfaceFormat = support.formats[0];
|
||||
|
||||
for (const auto& availableFormat :
|
||||
support.formats)
|
||||
{
|
||||
if (availableFormat.format ==
|
||||
VK_FORMAT_B8G8R8A8_SRGB &&
|
||||
availableFormat.colorSpace ==
|
||||
VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
|
||||
{
|
||||
m_surfaceFormat = availableFormat;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_presentMode = VK_PRESENT_MODE_FIFO_KHR;
|
||||
|
||||
for (const auto& availablePresentMode :
|
||||
support.presentModes)
|
||||
{
|
||||
if (availablePresentMode == m_preferredPresentMode)
|
||||
{
|
||||
m_presentMode = availablePresentMode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_extent.width = windowWidth;
|
||||
m_extent.height = windowHeight;
|
||||
|
||||
m_imageCount =
|
||||
support.capabilities.minImageCount + 1;
|
||||
|
||||
if (support.capabilities.maxImageCount > 0 &&
|
||||
m_imageCount >
|
||||
support.capabilities.maxImageCount)
|
||||
{
|
||||
m_imageCount =
|
||||
support.capabilities.maxImageCount;
|
||||
}
|
||||
|
||||
VkSwapchainCreateInfoKHR swapchainInfo{};
|
||||
swapchainInfo.sType =
|
||||
VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
||||
swapchainInfo.surface = m_surface;
|
||||
swapchainInfo.minImageCount = m_imageCount;
|
||||
swapchainInfo.imageFormat =
|
||||
m_surfaceFormat.format;
|
||||
swapchainInfo.imageColorSpace =
|
||||
m_surfaceFormat.colorSpace;
|
||||
swapchainInfo.imageExtent = m_extent;
|
||||
swapchainInfo.imageArrayLayers = 1;
|
||||
swapchainInfo.imageUsage =
|
||||
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
|
||||
QueueFamilyIndices indices =
|
||||
findQueueFamilies(
|
||||
m_physicalDevice,
|
||||
m_surface
|
||||
);
|
||||
|
||||
uint32_t queueFamilyIndices[] =
|
||||
{
|
||||
*indices.graphicsFamily,
|
||||
*indices.presentFamily
|
||||
};
|
||||
|
||||
if (*indices.graphicsFamily !=
|
||||
*indices.presentFamily)
|
||||
{
|
||||
swapchainInfo.imageSharingMode =
|
||||
VK_SHARING_MODE_CONCURRENT;
|
||||
swapchainInfo.queueFamilyIndexCount = 2;
|
||||
swapchainInfo.pQueueFamilyIndices =
|
||||
queueFamilyIndices;
|
||||
}
|
||||
else
|
||||
{
|
||||
swapchainInfo.imageSharingMode =
|
||||
VK_SHARING_MODE_EXCLUSIVE;
|
||||
}
|
||||
|
||||
swapchainInfo.preTransform =
|
||||
support.capabilities.currentTransform;
|
||||
swapchainInfo.compositeAlpha =
|
||||
VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
||||
swapchainInfo.presentMode = m_presentMode;
|
||||
swapchainInfo.clipped = VK_TRUE;
|
||||
|
||||
if (vkCreateSwapchainKHR(
|
||||
m_device,
|
||||
&swapchainInfo,
|
||||
nullptr,
|
||||
&m_swapchain) != VK_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"Failed to create swapchain"
|
||||
);
|
||||
}
|
||||
|
||||
vkGetSwapchainImagesKHR(
|
||||
m_device,
|
||||
m_swapchain,
|
||||
&m_imageCount,
|
||||
nullptr
|
||||
);
|
||||
|
||||
m_swapchainImages.resize(m_imageCount);
|
||||
|
||||
vkGetSwapchainImagesKHR(
|
||||
m_device,
|
||||
m_swapchain,
|
||||
&m_imageCount,
|
||||
m_swapchainImages.data()
|
||||
);
|
||||
|
||||
std::cout << "Present mode: "
|
||||
<< presentModeName(m_presentMode)
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
void Swapchain::createImageViews()
|
||||
{
|
||||
m_imageViews.resize(m_swapchainImages.size());
|
||||
|
||||
for (size_t i = 0;
|
||||
i < m_swapchainImages.size();
|
||||
++i)
|
||||
{
|
||||
VkImageViewCreateInfo viewInfo{};
|
||||
viewInfo.sType =
|
||||
VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
viewInfo.image = m_swapchainImages[i];
|
||||
viewInfo.viewType =
|
||||
VK_IMAGE_VIEW_TYPE_2D;
|
||||
viewInfo.format =
|
||||
m_surfaceFormat.format;
|
||||
viewInfo.components.r =
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
viewInfo.components.g =
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
viewInfo.components.b =
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
viewInfo.components.a =
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
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(
|
||||
m_device,
|
||||
&viewInfo,
|
||||
nullptr,
|
||||
&m_imageViews[i]) != VK_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"Failed to create image view"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Image views created"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
void Swapchain::createFramebuffers(
|
||||
VkRenderPass renderPass)
|
||||
{
|
||||
m_framebuffers.resize(m_imageViews.size());
|
||||
|
||||
for (size_t i = 0;
|
||||
i < m_imageViews.size();
|
||||
++i)
|
||||
{
|
||||
VkImageView attachments[] =
|
||||
{
|
||||
m_imageViews[i]
|
||||
};
|
||||
|
||||
VkFramebufferCreateInfo fbInfo{};
|
||||
fbInfo.sType =
|
||||
VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
||||
fbInfo.renderPass = renderPass;
|
||||
fbInfo.attachmentCount = 1;
|
||||
fbInfo.pAttachments = attachments;
|
||||
fbInfo.width = m_extent.width;
|
||||
fbInfo.height = m_extent.height;
|
||||
fbInfo.layers = 1;
|
||||
|
||||
if (vkCreateFramebuffer(
|
||||
m_device,
|
||||
&fbInfo,
|
||||
nullptr,
|
||||
&m_framebuffers[i]) != VK_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"Failed to create framebuffer"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Framebuffers created"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
void Swapchain::destroy()
|
||||
{
|
||||
if (m_swapchain == VK_NULL_HANDLE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (VkFramebuffer fb : m_framebuffers)
|
||||
{
|
||||
vkDestroyFramebuffer(
|
||||
m_device,
|
||||
fb,
|
||||
nullptr
|
||||
);
|
||||
}
|
||||
m_framebuffers.clear();
|
||||
|
||||
for (VkImageView view : m_imageViews)
|
||||
{
|
||||
vkDestroyImageView(
|
||||
m_device,
|
||||
view,
|
||||
nullptr
|
||||
);
|
||||
}
|
||||
m_imageViews.clear();
|
||||
m_swapchainImages.clear();
|
||||
|
||||
vkDestroySwapchainKHR(
|
||||
m_device,
|
||||
m_swapchain,
|
||||
nullptr
|
||||
);
|
||||
m_swapchain = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
void Swapchain::release()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
Reference in New Issue
Block a user