fix: alot of stuff changed. Mostly bugfixxes / architechture changes

This commit is contained in:
2026-08-09 02:24:17 +02:00
parent 4b6f773c0c
commit 05384debbf
98 changed files with 5461 additions and 1751 deletions
+136 -79
View File
@@ -1,12 +1,13 @@
#include <format>
#include <limits>
#include <stdexcept>
#include <destrum/Graphics/Swapchain.h>
#include <destrum/Graphics/Util.h>
#include <destrum/Graphics/GfxDevice.h>
#include <destrum/Graphics/Init.h>
#include "volk.h"
#include "tracy/Tracy.hpp"
#include <volk.h>
#include <tracy/Tracy.hpp>
void Swapchain::initSync(VkDevice device) {
@@ -23,31 +24,39 @@ void Swapchain::initSync(VkDevice device) {
}
}
void Swapchain::createSwapchain(GfxDevice* gfxDevice, VkFormat format, std::uint32_t width, std::uint32_t height, bool vSync) {
void Swapchain::createSwapchain(
VkDevice,
vkb::Device vkbDevice,
VkSurfaceKHR surf,
VkFormat format,
std::uint32_t width,
std::uint32_t height,
bool vSync)
{
ZoneScopedN("Swapchain::createSwapchain");
m_gfxDevice = gfxDevice;
assert(format == VK_FORMAT_B8G8R8A8_SRGB && "TODO: test other formats");
// vSync = true;
surface = surf;
{
ZoneScopedN("vkb::SwapchainBuilder::build");
auto res = vkb::SwapchainBuilder{gfxDevice->getDevice()}
auto res = vkb::SwapchainBuilder{vkbDevice, surface}
.set_desired_format(VkSurfaceFormatKHR{
.format = format,
.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
})
.add_image_usage_flags(VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
.add_image_usage_flags(
VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
.set_desired_present_mode(
vSync ? VK_PRESENT_MODE_FIFO_KHR : VK_PRESENT_MODE_IMMEDIATE_KHR)
vSync ? VK_PRESENT_MODE_FIFO_KHR
: VK_PRESENT_MODE_IMMEDIATE_KHR)
.set_desired_extent(width, height)
.build();
if (!res.has_value()) {
// throw std::runtime_error(std::format(
// "failed to create swapchain: error = {}, vk result = {}",
// res.full_error().type.message(),
// string_VkResult(res.full_error().vk_result)));
throw std::runtime_error(
"Failed to create swapchain: " + res.error().message());
}
m_swapchain = res.value();
}
@@ -55,8 +64,13 @@ void Swapchain::createSwapchain(GfxDevice* gfxDevice, VkFormat format, std::uint
{
ZoneScopedN("Get Swapchain Images / Views");
images = m_swapchain.get_images().value();
imageViews = m_swapchain.get_image_views().value();
const auto imageResult = m_swapchain.get_images();
const auto viewResult = m_swapchain.get_image_views();
if (!imageResult.has_value() || !viewResult.has_value()) {
throw std::runtime_error("Failed to retrieve swapchain images or views");
}
images = imageResult.value();
imageViews = viewResult.value();
}
imageRenderSemaphores.resize(images.size());
@@ -65,20 +79,20 @@ void Swapchain::createSwapchain(GfxDevice* gfxDevice, VkFormat format, std::uint
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO
};
for (auto& sem: imageRenderSemaphores) {
for (auto& sem : imageRenderSemaphores) {
ZoneScopedN("Create Image Render Semaphore");
VK_CHECK(vkCreateSemaphore(m_gfxDevice->getDevice(), &sci, nullptr, &sem));
VK_CHECK(vkCreateSemaphore(vkbDevice, &sci, nullptr, &sem));
}
// TODO: if re-creation of swapchain is supported, don't forget to call
// vkutil::initSwapchainViews here.
extent = m_swapchain.extent;
dirty = false;
}
void Swapchain::recreateSwapchain(
const GfxDevice& gfxDevice,
VkDevice,
vkb::Device vkbDevice,
VkSurfaceKHR surf,
VkFormat format,
std::uint32_t width,
std::uint32_t height,
@@ -91,11 +105,11 @@ void Swapchain::recreateSwapchain(
return;
}
VkDevice device = gfxDevice.getDevice();
surface = surf;
{
ZoneScopedN("vkDeviceWaitIdle");
vkDeviceWaitIdle(device);
vkDeviceWaitIdle(vkbDevice);
}
auto oldSwapchain = m_swapchain;
@@ -103,23 +117,24 @@ void Swapchain::recreateSwapchain(
{
ZoneScopedN("vkb::SwapchainBuilder::rebuild");
auto res = vkb::SwapchainBuilder{gfxDevice.getVkbDevice()}
auto res = vkb::SwapchainBuilder{vkbDevice, surface}
.set_old_swapchain(oldSwapchain)
.set_desired_format(VkSurfaceFormatKHR{
.format = format,
.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
})
.add_image_usage_flags(VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
.add_image_usage_flags(
VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
.set_desired_present_mode(
vSync ? VK_PRESENT_MODE_FIFO_KHR : VK_PRESENT_MODE_IMMEDIATE_KHR)
vSync ? VK_PRESENT_MODE_FIFO_KHR
: VK_PRESENT_MODE_IMMEDIATE_KHR)
.set_desired_extent(width, height)
.build();
if (!res.has_value()) {
// throw std::runtime_error(std::format(
// "failed to create swapchain: error = {}, vk result = {}",
// res.full_error().type.message(),
// string_VkResult(res.full_error().vk_result)));
throw std::runtime_error(
"Failed to recreate swapchain: " + res.error().message());
}
m_swapchain = res.value();
@@ -129,7 +144,7 @@ void Swapchain::recreateSwapchain(
ZoneScopedN("Destroy Old Image Render Semaphores");
for (auto sem : imageRenderSemaphores) {
vkDestroySemaphore(device, sem, nullptr);
vkDestroySemaphore(vkbDevice, sem, nullptr);
}
imageRenderSemaphores.clear();
}
@@ -138,7 +153,7 @@ void Swapchain::recreateSwapchain(
ZoneScopedN("Destroy Old Image Views");
for (auto imageView : imageViews) {
vkDestroyImageView(device, imageView, nullptr);
vkDestroyImageView(vkbDevice, imageView, nullptr);
}
imageViews.clear();
}
@@ -151,8 +166,13 @@ void Swapchain::recreateSwapchain(
{
ZoneScopedN("Get New Swapchain Images / Views");
images = m_swapchain.get_images().value();
imageViews = m_swapchain.get_image_views().value();
const auto imageResult = m_swapchain.get_images();
const auto viewResult = m_swapchain.get_image_views();
if (!imageResult.has_value() || !viewResult.has_value()) {
throw std::runtime_error("Failed to retrieve recreated swapchain images or views");
}
images = imageResult.value();
imageViews = viewResult.value();
}
VkSemaphoreCreateInfo sci{
@@ -164,57 +184,68 @@ void Swapchain::recreateSwapchain(
for (auto& sem : imageRenderSemaphores) {
ZoneScopedN("Create New Image Render Semaphore");
VK_CHECK(vkCreateSemaphore(device, &sci, nullptr, &sem));
VK_CHECK(vkCreateSemaphore(vkbDevice, &sci, nullptr, &sem));
}
extent = m_swapchain.extent;
dirty = false;
}
void Swapchain::cleanup() {
for (auto& frame: frames) {
vkDestroyFence(m_gfxDevice->getDevice(), frame.renderFence, nullptr);
vkDestroySemaphore(m_gfxDevice->getDevice(), frame.swapchainSemaphore, nullptr);
} {
// destroy swapchain and its views
for (auto imageView: imageViews) {
vkDestroyImageView(m_gfxDevice->getDevice(), imageView, nullptr);
void Swapchain::cleanup(VkDevice device) {
for (auto& frame : frames) {
if (frame.renderFence != VK_NULL_HANDLE) {
vkDestroyFence(device, frame.renderFence, nullptr);
frame.renderFence = VK_NULL_HANDLE;
}
if (frame.swapchainSemaphore != VK_NULL_HANDLE) {
vkDestroySemaphore(device, frame.swapchainSemaphore, nullptr);
frame.swapchainSemaphore = VK_NULL_HANDLE;
}
imageViews.clear();
vkb::destroy_swapchain(m_swapchain);
}
for (auto& semaphore : imageRenderSemaphores) {
if (semaphore != VK_NULL_HANDLE) {
vkDestroySemaphore(device, semaphore, nullptr);
semaphore = VK_NULL_HANDLE;
}
}
imageRenderSemaphores.clear();
for (auto imageView : imageViews) {
vkDestroyImageView(device, imageView, nullptr);
}
imageViews.clear();
vkb::destroy_swapchain(m_swapchain);
m_swapchain = {};
images.clear();
extent = {};
dirty = false;
}
void Swapchain::beginFrame(int index) const {
void Swapchain::beginFrame(VkDevice device, int index) const {
ZoneScopedN("Swapchain::beginFrame");
auto& frame = frames[index];
{
ZoneScopedN("vkWaitForFences");
VK_CHECK(vkWaitForFences(m_gfxDevice->getDevice(), 1, &frame.renderFence, true, std::numeric_limits<std::uint64_t>::max()));
VK_CHECK(vkWaitForFences(device, 1, &frame.renderFence, true, std::numeric_limits<std::uint64_t>::max()));
}
}
void Swapchain::resetFences(int index) const {
void Swapchain::resetFences(VkDevice device, int index) const {
ZoneScopedN("Swapchain::resetFences");
auto& frame = frames[index];
{
ZoneScopedN("vkResetFences");
VK_CHECK(vkResetFences(m_gfxDevice->getDevice(), 1, &frame.renderFence));
VK_CHECK(vkResetFences(device, 1, &frame.renderFence));
}
}
struct SwapchainAcquireResult {
VkResult result = VK_SUCCESS;
VkImage image = VK_NULL_HANDLE;
uint32_t imageIndex = 0;
};
std::pair<VkImage, int> Swapchain::acquireNextImage(int index) {
Swapchain::AcquireResult Swapchain::acquireNextImage(VkDevice device, std::uint32_t index) {
ZoneScopedN("Swapchain::acquireNextImage");
std::uint32_t swapchainImageIndex{};
@@ -225,7 +256,7 @@ std::pair<VkImage, int> Swapchain::acquireNextImage(int index) {
ZoneScopedN("vkAcquireNextImageKHR");
result = vkAcquireNextImageKHR(
m_gfxDevice->getDevice(),
device,
m_swapchain,
std::numeric_limits<std::uint64_t>::max(),
frames[index].swapchainSemaphore,
@@ -233,29 +264,42 @@ std::pair<VkImage, int> Swapchain::acquireNextImage(int index) {
&swapchainImageIndex);
}
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) {
if (result == VK_ERROR_OUT_OF_DATE_KHR) {
dirty = true;
return {images[swapchainImageIndex], swapchainImageIndex};
} else if (result != VK_SUCCESS) {
return {.result = result};
}
if (result == VK_SUBOPTIMAL_KHR) {
dirty = true;
return {
.result = result,
.image = images.at(swapchainImageIndex),
.imageIndex = swapchainImageIndex,
};
}
if (result != VK_SUCCESS) {
throw std::runtime_error("failed to acquire swap chain image!");
}
return {images[swapchainImageIndex], swapchainImageIndex};
return {
.result = result,
.image = images.at(swapchainImageIndex),
.imageIndex = swapchainImageIndex,
};
}
void Swapchain::submitAndPresent(
VkDevice device,
VkCommandBuffer cmd,
VkQueue graphicsQueue,
uint32_t imageIndex, // from vkAcquireNextImageKHR
uint32_t frameIndex) // 0..FRAMES_IN_FLIGHT-1
VkQueue presentQueue,
std::uint32_t imageIndex,
std::uint32_t frameIndex)
{
ZoneScopedN("Swapchain::submitAndPresent");
auto& frame = frames[frameIndex]; // ✅ per-frame
auto& frame = frames[frameIndex];
VkSemaphore renderFinished = imageRenderSemaphores[imageIndex];
VkSemaphore renderFinished = imageRenderSemaphores[imageIndex]; // ✅ per-image
// submit
VkCommandBufferSubmitInfo cmdInfo{
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
.commandBuffer = cmd,
@@ -263,38 +307,51 @@ void Swapchain::submitAndPresent(
VkSemaphoreSubmitInfo waitInfo =
vkinit::semaphoreSubmitInfo(
VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR,
frame.swapchainSemaphore); // ✅ acquire semaphore (per-frame)
VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
frame.swapchainSemaphore);
VkSemaphoreSubmitInfo signalInfo =
vkinit::semaphoreSubmitInfo(
VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT,
renderFinished); // ✅ signal semaphore (per-image)
VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
renderFinished);
VkSubmitInfo2 submit = vkinit::submitInfo(&cmdInfo, &waitInfo, &signalInfo);
VK_CHECK(vkResetFences(device, 1, &frame.renderFence));
{
ZoneScopedN("vkQueueSubmit2");
VK_CHECK(vkQueueSubmit2(graphicsQueue, 1, &submit, frame.renderFence)); // ✅ fence (per-frame)
const VkResult submitResult = vkQueueSubmit2(graphicsQueue, 1, &submit, frame.renderFence);
if (submitResult != VK_SUCCESS) {
vkDestroyFence(device, frame.renderFence, nullptr);
constexpr VkFenceCreateInfo fenceInfo{
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
.flags = VK_FENCE_CREATE_SIGNALED_BIT,
};
VK_CHECK(vkCreateFence(device, &fenceInfo, nullptr, &frame.renderFence));
checkVkResult(submitResult, "vkQueueSubmit2", __FILE__, __LINE__);
}
}
// present
VkPresentInfoKHR presentInfo{
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
.waitSemaphoreCount = 1,
.pWaitSemaphores = &renderFinished,
.swapchainCount = 1,
.pSwapchains = &m_swapchain.swapchain,
.pImageIndices = &imageIndex, // ✅ imageIndex, NOT frameIndex
.pImageIndices = &imageIndex,
};
VkResult res = VK_SUCCESS;
{
ZoneScopedN("vkQueuePresentKHR");
res = vkQueuePresentKHR(graphicsQueue, &presentInfo);
res = vkQueuePresentKHR(presentQueue, &presentInfo);
}
if (res == VK_ERROR_OUT_OF_DATE_KHR || res == VK_SUBOPTIMAL_KHR) dirty = true;
else if (res != VK_SUCCESS) dirty = true;
if (res == VK_ERROR_OUT_OF_DATE_KHR || res == VK_SUBOPTIMAL_KHR) {
dirty = true;
} else if (res != VK_SUCCESS) {
throw std::runtime_error("failed to present swap chain image");
}
}