Big changes

This commit is contained in:
2026-08-26 03:18:05 -07:00
parent d09f01402d
commit 99e06bbbb1
22 changed files with 1127 additions and 135 deletions
+220
View File
@@ -0,0 +1,220 @@
#include "swapchain.hpp"
#include <algorithm>
#include <limits>
#include <sophia/util/logger.hpp>
namespace sophia {
Swapchain::Swapchain(Device& device, vk::Extent2D extent)
: device{device}, extent{extent} {
initialize();
}
Swapchain::Swapchain(Device& device, vk::Extent2D extent,
std::shared_ptr<Swapchain> previous)
: device{device}, extent{extent}, oldSwapchain{previous} {
initialize();
this->oldSwapchain = nullptr;
}
Swapchain::~Swapchain() {
this->images.clear();
this->depthImages.clear();
this->device.get()->destroySwapchainKHR(this->swapchain);
// log::trace("destroyed vk::SwapchainKHR");
}
vk::Result Swapchain::acquireNextImage(vk::Semaphore signalSemaphore,
u32& imageIndex) {
return this->device.get()->acquireNextImageKHR(
this->swapchain, std::numeric_limits<u64>::max(), signalSemaphore,
VK_NULL_HANDLE, &imageIndex);
}
vk::Result Swapchain::present(vk::Queue presentQueue, u32 imageIndex,
vk::Semaphore waitSemaphore) {
vk::PresentInfoKHR presentInfo = {};
presentInfo.waitSemaphoreCount = 1;
presentInfo.pWaitSemaphores = &waitSemaphore;
vk::SwapchainKHR swapChains[] = {this->swapchain};
presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = swapChains;
presentInfo.pImageIndices = &imageIndex;
return presentQueue.presentKHR(&presentInfo);
}
void Swapchain::initialize() {
setDefaultCreateInfo();
createSwapchain();
createImages();
createDepthImages();
}
void Swapchain::setDefaultCreateInfo() {
SwapchainSupportDetails swapchainSupport = this->device.getSwapchainSupport();
vk::SurfaceFormatKHR surfaceFormat =
chooseSurfaceFormat(swapchainSupport.formats);
vk::PresentModeKHR presentMode =
choosePresentMode(swapchainSupport.presentModes);
this->extent = chooseExtent(swapchainSupport.capabilities);
u32 imageCount = swapchainSupport.capabilities.minImageCount + 1;
if (swapchainSupport.capabilities.maxImageCount > 0 &&
imageCount > swapchainSupport.capabilities.maxImageCount) {
imageCount = swapchainSupport.capabilities.maxImageCount;
}
this->swapchainCreateInfo = {vk::SwapchainCreateFlagsKHR(),
this->device.getSurface(),
imageCount,
surfaceFormat.format,
surfaceFormat.colorSpace,
this->extent,
1,
vk::ImageUsageFlagBits::eColorAttachment};
QueueFamilyIndices indices = this->device.getQueueIndices();
u32 queueFamilyIndices[] = {indices.graphicsFamily.value(),
indices.presentFamily.value()};
if (indices.graphicsFamily != indices.presentFamily) {
swapchainCreateInfo.imageSharingMode = vk::SharingMode::eConcurrent;
swapchainCreateInfo.queueFamilyIndexCount = 2;
swapchainCreateInfo.pQueueFamilyIndices = queueFamilyIndices;
} else {
swapchainCreateInfo.imageSharingMode = vk::SharingMode::eExclusive;
}
swapchainCreateInfo.preTransform =
swapchainSupport.capabilities.currentTransform;
swapchainCreateInfo.compositeAlpha = vk::CompositeAlphaFlagBitsKHR::eOpaque;
swapchainCreateInfo.presentMode = presentMode;
swapchainCreateInfo.clipped = VK_TRUE;
swapchainCreateInfo.oldSwapchain = vk::SwapchainKHR(nullptr);
swapchainCreateInfo.oldSwapchain = this->oldSwapchain == nullptr
? VK_NULL_HANDLE
: this->oldSwapchain->swapchain;
this->imageFormat = surfaceFormat.format;
}
void Swapchain::createSwapchain() {
try {
this->swapchain =
this->device.get()->createSwapchainKHR(this->swapchainCreateInfo);
// log::trace("created vk::SwapchainKHR");
} catch (const vk::SystemError& err) {
log::fatal("failed to create swapchain. Error: ", err.what());
throw std::runtime_error("failed to create swapchain");
}
}
void Swapchain::createImages() {
std::vector<vk::Image> swapchainImages =
this->device.get()->getSwapchainImagesKHR(this->swapchain);
this->images.clear();
this->images.reserve(swapchainImages.size());
for (vk::Image image : swapchainImages) {
this->images.push_back(Image::Builder(this->device)
.wrapExisting(image)
.setFormat(this->imageFormat)
.setExtent(width(), height())
.withView()
.build());
}
// log::trace("created all swapchain vk::ImageView");
}
void Swapchain::createDepthImages() {
this->depthFormat = findDepthFormat();
this->depthImages.clear();
this->depthImages.reserve(imageCount());
for (size_t i = 0; i < imageCount(); i++) {
this->depthImages.push_back(Image::Builder(this->device)
.asDepthAttachment()
.setFormat(this->depthFormat)
.setExtent(width(), height())
.withView()
.build());
}
// log::trace("created all depth resources");
}
vk::SurfaceFormatKHR Swapchain::chooseSurfaceFormat(
const std::vector<vk::SurfaceFormatKHR>& availableFormats) {
if (availableFormats.size() == 1 &&
availableFormats[0].format == vk::Format::eUndefined) {
return {vk::Format::eB8G8R8A8Unorm, vk::ColorSpaceKHR::eSrgbNonlinear};
}
for (const auto& availableFormat : availableFormats) {
if (availableFormat.format == vk::Format::eB8G8R8A8Unorm &&
availableFormat.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear) {
return availableFormat;
}
}
log::info("No available surface formats, choosing default.");
return availableFormats[0];
}
vk::PresentModeKHR Swapchain::choosePresentMode(
const std::vector<vk::PresentModeKHR> availablePresentModes) {
vk::PresentModeKHR bestMode = vk::PresentModeKHR::eFifo;
for (const auto& availablePresentMode : availablePresentModes) {
if (availablePresentMode == vk::PresentModeKHR::eMailbox) {
log::info("Selected present mode: MAILBOX (triple buffering)");
return availablePresentMode;
} else if (availablePresentMode == vk::PresentModeKHR::eImmediate) {
bestMode = availablePresentMode;
}
}
log::warning("Present mode MAILBOX not available.");
if (bestMode == vk::PresentModeKHR::eImmediate) {
log::info("Selected present mode: IMMEDIATE (no vsync)");
} else {
log::info("Selected present mode: FIFO (vsync)");
}
return bestMode;
}
vk::Extent2D Swapchain::chooseExtent(
const vk::SurfaceCapabilitiesKHR& capabilities) {
if (capabilities.currentExtent.width != std::numeric_limits<u32>::max()) {
return capabilities.currentExtent;
} else {
vk::Extent2D choosenExtent = {};
choosenExtent.width =
std::clamp(this->extent.width, capabilities.minImageExtent.width,
capabilities.maxImageExtent.width);
choosenExtent.height =
std::clamp(this->extent.height, capabilities.minImageExtent.height,
capabilities.maxImageExtent.height);
return choosenExtent;
}
}
vk::Format Swapchain::findDepthFormat() {
return this->device.findSupportedFormat(
{vk::Format::eD32Sfloat, vk::Format::eD32SfloatS8Uint,
vk::Format::eD24UnormS8Uint},
vk::ImageTiling::eOptimal,
vk::FormatFeatureFlagBits::eDepthStencilAttachment);
}
} // namespace sophia