Swapchain added.

This commit is contained in:
Anish Bhobe 2024-06-26 19:49:55 +02:00
parent c16456c610
commit e55f30e7e7
6 changed files with 198 additions and 3 deletions

View File

@ -18,7 +18,8 @@ set(HEADER_FILES
context.h context.h
window.h window.h
physical_device.h physical_device.h
device.h) device.h
swapchain.h)
set(SOURCE_FILES set(SOURCE_FILES
logger.cpp logger.cpp
@ -26,7 +27,8 @@ set(SOURCE_FILES
context.cpp context.cpp
window.cpp window.cpp
physical_device.cpp physical_device.cpp
device.cpp) device.cpp
swapchain.cpp)
add_library(aster_core STATIC ${SOURCE_FILES} ${HEADER_FILES}) add_library(aster_core STATIC ${SOURCE_FILES} ${HEADER_FILES})
set_property(TARGET aster_core PROPERTY CXX_STANDARD 20) set_property(TARGET aster_core PROPERTY CXX_STANDARD 20)

155
aster/swapchain.cpp Normal file
View File

@ -0,0 +1,155 @@
/// =============================================
// Aster: swapchain.cpp
// Copyright (c) 2020-2024 Anish Bhobe
// ==============================================
#include "swapchain.h"
#include "device.h"
#include "physical_device.h"
#include "window.h"
vk::SurfaceCapabilitiesKHR
getSurfaceCapabilities(vk::PhysicalDevice physicalDevice, const vk::SurfaceKHR surface)
{
vk::SurfaceCapabilitiesKHR surfaceCapabilities;
vk::Result result = physicalDevice.getSurfaceCapabilitiesKHR(surface, &surfaceCapabilities);
ERROR_IF(failed(result), "Fetching surface capabilities failed. Cause: {}", result)
THEN_ABORT(result);
return surfaceCapabilities;
}
eastl::vector<vk::SurfaceFormatKHR>
getSurfaceFormats(vk::PhysicalDevice physicalDevice, const vk::SurfaceKHR surface)
{
u32 count = 0;
vk::Result result = physicalDevice.getSurfaceFormatsKHR(surface, &count, nullptr);
ERROR_IF(failed(result), "Fetching surface formats failed. Cause: {}", result)
THEN_ABORT(result);
eastl::vector<vk::SurfaceFormatKHR> surfaceFormats(count);
result = physicalDevice.getSurfaceFormatsKHR(surface, &count, surfaceFormats.data());
ERROR_IF(failed(result), "Fetching surface formats failed. Cause: {}", result)
THEN_ABORT(result);
return surfaceFormats;
}
eastl::vector<vk::PresentModeKHR>
getSurfacePresentModes(vk::PhysicalDevice physicalDevice, const vk::SurfaceKHR surface)
{
u32 count = 0;
vk::Result result = physicalDevice.getSurfacePresentModesKHR(surface, &count, nullptr);
ERROR_IF(failed(result), "Fetching surface present modes failed. Cause: {}", result)
THEN_ABORT(result);
eastl::vector<vk::PresentModeKHR> surfacePresentModes(count);
result = physicalDevice.getSurfacePresentModesKHR(surface, &count, surfacePresentModes.data());
ERROR_IF(failed(result), "Fetching surface present modes failed. Cause: {}", result)
THEN_ABORT(result);
return surfacePresentModes;
}
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 surfaceFormat = surfaceFormats.front();
swapchainFormat = surfaceFormat.format;
swapchainColorSpace = surfaceFormat.colorSpace;
}
vk::PresentModeKHR swapchainPresentMode = vk::PresentModeKHR::eFifo;
for (auto presentMode : presentModes)
{
if (presentMode == vk::PresentModeKHR::eMailbox)
{
swapchainPresentMode = presentMode;
break;
}
}
vk::Extent2D swapchainExtent;
if (surfaceCapabilities.currentExtent.width != MaxValue<u32>)
{
swapchainExtent = surfaceCapabilities.currentExtent;
}
else
{
vk::Extent2D extent = window->GetSize();
vk::Extent2D minExtent = surfaceCapabilities.minImageExtent;
vk::Extent2D maxExtent = surfaceCapabilities.maxImageExtent;
swapchainExtent.width = glm::clamp(extent.width, minExtent.width, maxExtent.width);
swapchainExtent.height = glm::clamp(extent.height, minExtent.height, maxExtent.height);
}
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;
}

23
aster/swapchain.h Normal file
View File

@ -0,0 +1,23 @@
/// =============================================
// Aster: swapchain.h
// Copyright (c) 2020-2024 Anish Bhobe
// ==============================================
#pragma once
#include "global.h"
struct PhysicalDevice;
struct Window;
struct Device;
struct Swapchain final
{
const Device *m_Device;
vk::SwapchainKHR m_Swapchain;
NameString m_Name;
Swapchain(const Window *window, const Device *device, NameString &&name);
~Swapchain();
void Create(const Window *window);
};

View File

@ -4,6 +4,7 @@
// ============================================= // =============================================
#include "window.h" #include "window.h"
#include "context.h" #include "context.h"
#include "glfw_context.h" #include "glfw_context.h"
#include "logger.h" #include "logger.h"
@ -20,6 +21,15 @@ Window::SetWindowSize(const u32 width, const u32 height) const noexcept
glfwSetWindowSize(m_Window, cast<i32>(width), cast<i32>(height)); glfwSetWindowSize(m_Window, cast<i32>(width), cast<i32>(height));
} }
vk::Extent2D
Window::GetSize() const
{
int width;
int height;
glfwGetWindowSize(m_Window, &width, &height);
return {cast<u32>(width), cast<u32>(height)};
}
Window::Window(cstr title, Context *context, vk::Extent2D extent, b8 isFullScreen) Window::Window(cstr title, Context *context, vk::Extent2D extent, b8 isFullScreen)
{ {
m_Context = context; m_Context = context;

View File

@ -29,6 +29,7 @@ struct Window final
void SetWindowSize(const vk::Extent2D &extent) const noexcept; void SetWindowSize(const vk::Extent2D &extent) const noexcept;
void SetWindowSize(u32 width, u32 height) const noexcept; void SetWindowSize(u32 width, u32 height) const noexcept;
[[nodiscard]] vk::Extent2D GetSize() const;
// Ctor/Dtor // Ctor/Dtor
Window(cstr title, Context *context, vk::Extent2D extent, b8 isFullScreen = false); Window(cstr title, Context *context, vk::Extent2D extent, b8 isFullScreen = false);

View File

@ -1,10 +1,12 @@
#include "aster/constants.h" #include "aster/constants.h"
#include "aster/context.h"
#include "aster/device.h" #include "aster/device.h"
#include "aster/glfw_context.h" #include "aster/glfw_context.h"
#include "aster/physical_device.h" #include "aster/physical_device.h"
#include "aster/window.h" #include "aster/window.h"
#include "aster/global.h" #include "aster/global.h"
#include "aster/swapchain.h"
constexpr QueueSupportFlags REQUIRED_QUEUE_SUPPORT = QueueSupportFlags{} | QueueSupportFlagBits::eGraphics | constexpr QueueSupportFlags REQUIRED_QUEUE_SUPPORT = QueueSupportFlags{} | QueueSupportFlagBits::eGraphics |
QueueSupportFlagBits::eCompute | QueueSupportFlagBits::ePresent | QueueSupportFlagBits::eCompute | QueueSupportFlagBits::ePresent |
@ -62,7 +64,7 @@ findAppropriateQueueAllocation(const PhysicalDevice *physicalDevice)
int int
main(int, char **) main(int, char **)
{ {
MIN_LOG_LEVEL(Logger::LogType::eInfo); MIN_LOG_LEVEL(Logger::LogType::eDebug);
GlfwContext glfwContext = {}; GlfwContext glfwContext = {};
Context context = {"Aster", VERSION}; Context context = {"Aster", VERSION};
@ -78,6 +80,8 @@ main(int, char **)
Device device = {&context, &deviceToUse, &features, {queueAllocation}, "Primary Device"}; Device device = {&context, &deviceToUse, &features, {queueAllocation}, "Primary Device"};
Swapchain swapchain = {&window, &device, "Primary Chain"};
while (window.Poll()) while (window.Poll())
{ {
} }