From 13076e9fe3522ee5545a573e5498f1015ed5e5a6 Mon Sep 17 00:00:00 2001 From: PancakeTAS Date: Tue, 1 Jul 2025 09:59:24 +0200 Subject: [PATCH] simple presenting logic --- include/application.hpp | 19 +++++++++++++++++-- src/application.cpp | 29 +++++++++++++++++++++++++++++ src/hooks.cpp | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 2 deletions(-) diff --git a/include/application.hpp b/include/application.hpp index 60bad94..0556b5b 100644 --- a/include/application.hpp +++ b/include/application.hpp @@ -33,11 +33,26 @@ public: /// @param images The swapchain images. /// /// @throws std::invalid_argument if the handle is already added. - /// @throws ls::vulkan_error if any Vulkan call fails. + /// @throws LSFG::vulkan_error if any Vulkan call fails. /// void addSwapchain(VkSwapchainKHR handle, VkFormat format, VkExtent2D extent, const std::vector& images); + /// + /// Present the next frame on a given swapchain. + /// + /// @param handle The Vulkan handle of the swapchain to present on. + /// @param queue The Vulkan queue to present the frame on. + /// @param semaphores The semaphores to wait on before presenting. + /// @param idx The index of the swapchain image to present. + /// + /// @throws std::invalid_argument if the handle is not found. + /// @throws LSFG::vulkan_error if any Vulkan call fails. + /// + void presentSwapchain(VkSwapchainKHR handle, VkQueue queue, + const std::vector& semaphores, uint32_t idx); + + /// /// Remove a swapchain from the application. /// @@ -86,7 +101,7 @@ public: /// @param images The swapchain images. /// /// @throws std::invalid_argument if any parameter is null - /// @throws ls::vulkan_error if any Vulkan call fails. + /// @throws LSFG::vulkan_error if any Vulkan call fails. /// SwapchainContext(VkSwapchainKHR swapchain, VkFormat format, VkExtent2D extent, const std::vector& images); diff --git a/src/application.cpp b/src/application.cpp index 7f06f81..3a69504 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -1,5 +1,7 @@ #include "application.hpp" +#include + #include Application::Application(VkDevice device, VkPhysicalDevice physicalDevice) @@ -19,6 +21,33 @@ void Application::addSwapchain(VkSwapchainKHR handle, VkFormat format, VkExtent2 this->swapchains.emplace(handle, SwapchainContext(handle, format, extent, images)); } +void Application::presentSwapchain(VkSwapchainKHR handle, VkQueue queue, + const std::vector& semaphores, uint32_t idx) { + if (handle == VK_NULL_HANDLE) + throw std::invalid_argument("Invalid swapchain handle"); + + // find the swapchain context + auto it = this->swapchains.find(handle); + if (it == this->swapchains.end()) + throw std::logic_error("Swapchain not found"); + + // TODO: present + const VkPresentInfoKHR presentInfo = { + .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, + .pNext = nullptr, + .waitSemaphoreCount = static_cast(semaphores.size()), + .pWaitSemaphores = semaphores.data(), + .swapchainCount = 1, + .pSwapchains = &handle, + .pImageIndices = &idx, + .pResults = nullptr // can be null if not needed + }; + auto res = vkQueuePresentKHR(queue, &presentInfo); + if (res != VK_SUCCESS) // do NOT check VK_SUBOPTIMAL_KHR + throw LSFG::vulkan_error(res, "Failed to present swapchain"); +} + + SwapchainContext::SwapchainContext(VkSwapchainKHR swapchain, VkFormat format, VkExtent2D extent, const std::vector& images) : swapchain(swapchain), format(format), extent(extent), images(images) { diff --git a/src/hooks.cpp b/src/hooks.cpp index 518aaf0..40773a1 100644 --- a/src/hooks.cpp +++ b/src/hooks.cpp @@ -88,6 +88,36 @@ namespace { return res; } + VkResult myvkQueuePresentKHR( + VkQueue queue, + const VkPresentInfoKHR* pPresentInfo) { + if (!application.has_value()) { + Log::error("Application not initialized, cannot present frame"); + return VK_ERROR_INITIALIZATION_FAILED; + } + + // present the next frame + try { + std::vector waitSemaphores(pPresentInfo->waitSemaphoreCount); + std::copy_n(pPresentInfo->pWaitSemaphores, waitSemaphores.size(), waitSemaphores.data()); + + application->presentSwapchain(*pPresentInfo->pSwapchains, + queue, waitSemaphores, *pPresentInfo->pImageIndices); + + Log::info("lsfg-vk(hooks): Frame presented successfully"); + } catch (const LSFG::vulkan_error& e) { + Log::error("Encountered Vulkan error {:x} while presenting: {}", + static_cast(e.error()), e.what()); + return e.error(); // do not exit + } catch (const std::exception& e) { + Log::error("Encountered error while creating presenting: {}", e.what()); + exit(EXIT_FAILURE); + } + + return VK_SUCCESS; + } + + void myvkDestroySwapchainKHR( VkDevice device, VkSwapchainKHR swapchain, @@ -140,6 +170,8 @@ void Hooks::initialize() { reinterpret_cast(myvkCreateSwapchainKHR)); Loader::VK::registerSymbol("vkDestroySwapchainKHR", reinterpret_cast(myvkDestroySwapchainKHR)); + Loader::VK::registerSymbol("vkQueuePresentKHR", + reinterpret_cast(myvkQueuePresentKHR)); // register hooks to dynamic loader under libvulkan.so.1 Loader::DL::File vk1("libvulkan.so.1"); @@ -151,6 +183,8 @@ void Hooks::initialize() { reinterpret_cast(myvkCreateSwapchainKHR)); vk1.defineSymbol("vkDestroySwapchainKHR", reinterpret_cast(myvkDestroySwapchainKHR)); + vk1.defineSymbol("vkQueuePresentKHR", + reinterpret_cast(myvkQueuePresentKHR)); Loader::DL::registerFile(vk1); // register hooks to dynamic loader under libvulkan.so @@ -163,5 +197,7 @@ void Hooks::initialize() { reinterpret_cast(myvkCreateSwapchainKHR)); vk2.defineSymbol("vkDestroySwapchainKHR", reinterpret_cast(myvkDestroySwapchainKHR)); + vk2.defineSymbol("vkQueuePresentKHR", + reinterpret_cast(myvkQueuePresentKHR)); Loader::DL::registerFile(vk2); }