111 lines
3.7 KiB
C++
111 lines
3.7 KiB
C++
/// =============================================
|
|
// Aster: swapchain.cpp
|
|
// Copyright (c) 2020-2024 Anish Bhobe
|
|
// ==============================================
|
|
|
|
#include "swapchain.h"
|
|
|
|
#include "device.h"
|
|
#include "physical_device.h"
|
|
#include "window.h"
|
|
|
|
Swapchain::Swapchain(const Window *window, const Device *device, NameString &&name)
|
|
: m_Device(device)
|
|
, m_Name(std::move(name))
|
|
{
|
|
this->Create(window);
|
|
}
|
|
|
|
Swapchain::~Swapchain()
|
|
{
|
|
if (m_Swapchain)
|
|
{
|
|
m_Device->m_Device.destroy(m_Swapchain, nullptr);
|
|
m_Swapchain = nullptr;
|
|
DEBUG("Swapchain '{}' destroyed.", m_Name);
|
|
}
|
|
}
|
|
|
|
void
|
|
Swapchain::Create(const Window *window)
|
|
{
|
|
auto surfaceCapabilities = GetSurfaceCapabilities(m_Device->m_PhysicalDevice, window->m_Surface);
|
|
auto surfaceFormats = GetSurfaceFormats(m_Device->m_PhysicalDevice, window->m_Surface);
|
|
auto presentModes = GetSurfacePresentModes(m_Device->m_PhysicalDevice, window->m_Surface);
|
|
|
|
vk::Format swapchainFormat = vk::Format::eUndefined;
|
|
vk::ColorSpaceKHR swapchainColorSpace = vk::ColorSpaceKHR::eSrgbNonlinear;
|
|
for (auto [format, colorSpace] : surfaceFormats)
|
|
{
|
|
if (format == vk::Format::eB8G8R8A8Srgb && colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear)
|
|
{
|
|
swapchainFormat = format;
|
|
swapchainColorSpace = colorSpace;
|
|
}
|
|
}
|
|
if (swapchainFormat == vk::Format::eUndefined)
|
|
{
|
|
WARN("Preferred Swapchain format not found. Falling back.");
|
|
auto [format, colorSpace] = surfaceFormats.front();
|
|
swapchainFormat = format;
|
|
swapchainColorSpace = colorSpace;
|
|
}
|
|
|
|
vk::PresentModeKHR swapchainPresentMode = vk::PresentModeKHR::eFifo;
|
|
for (const auto presentMode : presentModes)
|
|
{
|
|
if (presentMode == vk::PresentModeKHR::eMailbox)
|
|
{
|
|
swapchainPresentMode = presentMode;
|
|
break;
|
|
}
|
|
}
|
|
|
|
vk::Extent2D swapchainExtent;
|
|
if (surfaceCapabilities.currentExtent.width != MaxValue<u32>)
|
|
{
|
|
swapchainExtent = surfaceCapabilities.currentExtent;
|
|
}
|
|
else
|
|
{
|
|
auto [width, height] = window->GetSize();
|
|
auto [minWidth, minHeight] = surfaceCapabilities.minImageExtent;
|
|
auto [maxWidth, maxHeight] = surfaceCapabilities.maxImageExtent;
|
|
|
|
swapchainExtent.width = glm::clamp(width, minWidth, maxWidth);
|
|
swapchainExtent.height = glm::clamp(height, minHeight, maxHeight);
|
|
}
|
|
|
|
u32 swapchainImageCount = 3;
|
|
if (surfaceCapabilities.maxImageCount > 0)
|
|
{
|
|
swapchainImageCount =
|
|
glm::clamp(swapchainImageCount, surfaceCapabilities.minImageCount, surfaceCapabilities.maxImageCount);
|
|
}
|
|
|
|
// TODO: Note that different queues might need the images to be shared.
|
|
|
|
const vk::SwapchainCreateInfoKHR swapchainCreateInfo = {
|
|
.surface = window->m_Surface,
|
|
.minImageCount = swapchainImageCount,
|
|
.imageFormat = swapchainFormat,
|
|
.imageColorSpace = swapchainColorSpace,
|
|
.imageExtent = swapchainExtent,
|
|
.imageArrayLayers = 1,
|
|
.imageUsage = vk::ImageUsageFlagBits::eColorAttachment,
|
|
.imageSharingMode = vk::SharingMode::eExclusive,
|
|
.preTransform = surfaceCapabilities.currentTransform,
|
|
.compositeAlpha = vk::CompositeAlphaFlagBitsKHR::eOpaque,
|
|
.presentMode = swapchainPresentMode,
|
|
.clipped = true,
|
|
.oldSwapchain = m_Swapchain,
|
|
};
|
|
|
|
vk::SwapchainKHR swapchain;
|
|
vk::Result result = m_Device->m_Device.createSwapchainKHR(&swapchainCreateInfo, nullptr, &swapchain);
|
|
ERROR_IF(Failed(result), "Swapchain {} creation failed. Cause {}", m_Name, result)
|
|
THEN_ABORT(result)
|
|
ELSE_DEBUG("Created Swapchain '{}'", m_Name);
|
|
|
|
m_Swapchain = swapchain;
|
|
} |