Swapchain added.
This commit is contained in:
parent
c16456c610
commit
e55f30e7e7
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
};
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue