From 70bf51fa725b2d8518f0000e874d3b24542d7803 Mon Sep 17 00:00:00 2001 From: PancakeTAS Date: Tue, 1 Jul 2025 11:18:05 +0200 Subject: [PATCH] lots of fixes --- include/application.hpp | 8 ++-- include/mini/semaphore.hpp | 53 ++++++++++++++++++++++ lsfg-vk-gen/src/context.cpp | 5 ++- lsfg-vk-gen/src/core/commandbuffer.cpp | 6 ++- lsfg-vk-gen/src/core/semaphore.cpp | 3 ++ src/application.cpp | 18 ++++---- src/hooks.cpp | 8 +++- src/mini/semaphore.cpp | 61 ++++++++++++++++++++++++++ 8 files changed, 142 insertions(+), 20 deletions(-) create mode 100644 include/mini/semaphore.hpp create mode 100644 src/mini/semaphore.cpp diff --git a/include/application.hpp b/include/application.hpp index 045982a..1da5417 100644 --- a/include/application.hpp +++ b/include/application.hpp @@ -130,14 +130,12 @@ public: /// Get the swapchain images. [[nodiscard]] const std::vector& getImages() const { return this->images; } - // Non-copyable, trivially moveable + // Non-copyable, trivially moveable and destructible SwapchainContext(const SwapchainContext&) = delete; SwapchainContext& operator=(const SwapchainContext&) = delete; SwapchainContext(SwapchainContext&&) = default; SwapchainContext& operator=(SwapchainContext&&) = default; - - /// Destructor, cleans up resources. - ~SwapchainContext(); + ~SwapchainContext() = default; private: // (non-owned resources) VkSwapchainKHR swapchain; @@ -147,7 +145,7 @@ private: // (owned resources) Mini::Image frame_0, frame_1; - int32_t lsfgId; + std::shared_ptr lsfgId; }; #endif // APPLICATION_HPP diff --git a/include/mini/semaphore.hpp b/include/mini/semaphore.hpp new file mode 100644 index 0000000..833ce35 --- /dev/null +++ b/include/mini/semaphore.hpp @@ -0,0 +1,53 @@ +#ifndef SEMAPHORE_HPP +#define SEMAPHORE_HPP + +#include + +#include + +namespace Mini { + + /// + /// C++ wrapper class for a Vulkan semaphore. + /// + /// This class manages the lifetime of a Vulkan semaphore. + /// + class Semaphore { + public: + Semaphore() noexcept = default; + + /// + /// Create the semaphore. + /// + /// @param device Vulkan device + /// + /// @throws LSFG::vulkan_error if object creation fails. + /// + Semaphore(VkDevice device); + + /// + /// Import a semaphore. + /// + /// @param device Vulkan device + /// @param fd File descriptor to import the semaphore from. + /// + /// @throws LSFG::vulkan_error if object creation fails. + /// + Semaphore(VkDevice device, int* fd); + + /// Get the Vulkan handle. + [[nodiscard]] auto handle() const { return *this->semaphore; } + + // Trivially copyable, moveable and destructible + Semaphore(const Semaphore&) noexcept = default; + Semaphore& operator=(const Semaphore&) noexcept = default; + Semaphore(Semaphore&&) noexcept = default; + Semaphore& operator=(Semaphore&&) noexcept = default; + ~Semaphore() = default; + private: + std::shared_ptr semaphore; + }; + +} + +#endif // SEMAPHORE_HPP diff --git a/lsfg-vk-gen/src/context.cpp b/lsfg-vk-gen/src/context.cpp index 46ee8ed..fcfbef4 100644 --- a/lsfg-vk-gen/src/context.cpp +++ b/lsfg-vk-gen/src/context.cpp @@ -4,6 +4,7 @@ #include #include +#include using namespace LSFG; @@ -119,8 +120,8 @@ void Context::present(const Core::Device& device, int inSem, int outSem) { cmdBuffer.end(); cmdBuffer.submit(device.getComputeQueue(), std::nullopt, - { inSemaphore }, {}, - { outSemaphore }, {}); + { inSemaphore }, std::nullopt, + { outSemaphore }, std::nullopt); fc++; } diff --git a/lsfg-vk-gen/src/core/commandbuffer.cpp b/lsfg-vk-gen/src/core/commandbuffer.cpp index c556127..86a1d0e 100644 --- a/lsfg-vk-gen/src/core/commandbuffer.cpp +++ b/lsfg-vk-gen/src/core/commandbuffer.cpp @@ -83,10 +83,12 @@ void CommandBuffer::submit(VkQueue queue, std::optional fence, timelineInfo.pSignalSemaphoreValues = signalSemaphoreValues->data(); } - std::vector waitSemaphoresHandles(waitSemaphores.size()); + std::vector waitSemaphoresHandles; + waitSemaphoresHandles.reserve(waitSemaphores.size()); for (const auto& semaphore : waitSemaphores) waitSemaphoresHandles.push_back(semaphore.handle()); - std::vector signalSemaphoresHandles(signalSemaphores.size()); + std::vector signalSemaphoresHandles; + signalSemaphoresHandles.reserve(signalSemaphores.size()); for (const auto& semaphore : signalSemaphores) signalSemaphoresHandles.push_back(semaphore.handle()); diff --git a/lsfg-vk-gen/src/core/semaphore.cpp b/lsfg-vk-gen/src/core/semaphore.cpp index 78b66d4..267c8f5 100644 --- a/lsfg-vk-gen/src/core/semaphore.cpp +++ b/lsfg-vk-gen/src/core/semaphore.cpp @@ -45,6 +45,9 @@ Semaphore::Semaphore(const Core::Device& device, int fd) { throw LSFG::vulkan_error(res, "Unable to create semaphore"); // import semaphore from fd + auto vkImportSemaphoreFdKHR = reinterpret_cast( + vkGetDeviceProcAddr(device.handle(), "vkImportSemaphoreFdKHR")); + const VkImportSemaphoreFdInfoKHR importInfo{ .sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR, .semaphore = semaphoreHandle, diff --git a/src/application.cpp b/src/application.cpp index 11dfd84..8646a0f 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -1,8 +1,10 @@ #include "application.hpp" #include "log.hpp" #include "mini/image.hpp" +#include "mini/semaphore.hpp" #include +#include #include Application::Application(VkDevice device, VkPhysicalDevice physicalDevice, @@ -38,7 +40,13 @@ SwapchainContext::SwapchainContext(const Application& app, VkSwapchainKHR swapch VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_ASPECT_COLOR_BIT, &frame1fd ); - this->lsfgId = LSFG::createContext(extent.width, extent.height, frame0fd, frame1fd); + auto id = LSFG::createContext(extent.width, extent.height, frame0fd, frame1fd); + this->lsfgId = std::shared_ptr( + new int32_t(id), + [](const int32_t* id) { + LSFG::deleteContext(*id); + } + ); } void Application::presentSwapchain(VkSwapchainKHR handle, VkQueue queue, @@ -65,14 +73,6 @@ void SwapchainContext::present(const Application& app, VkQueue queue, throw LSFG::vulkan_error(res, "Failed to present swapchain"); } -SwapchainContext::~SwapchainContext() { - try { - LSFG::deleteContext(this->lsfgId); - } catch (const std::exception&) { - return; - } -} - bool Application::removeSwapchain(VkSwapchainKHR handle) { auto it = this->swapchains.find(handle); if (it == this->swapchains.end()) diff --git a/src/hooks.cpp b/src/hooks.cpp index e908dcb..2c2e5cd 100644 --- a/src/hooks.cpp +++ b/src/hooks.cpp @@ -7,6 +7,7 @@ #include #include +#include using namespace Hooks; @@ -24,7 +25,8 @@ namespace { const std::vector requiredExtensions = { VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, - VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME + VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME, + VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME }; for (const auto& ext : requiredExtensions) { auto it = std::ranges::find(extensions, ext); @@ -49,7 +51,9 @@ namespace { const std::vector requiredExtensions = { VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME, - VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME + VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, + VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME, + VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME }; for (const auto& ext : requiredExtensions) { auto it = std::ranges::find(extensions, ext); diff --git a/src/mini/semaphore.cpp b/src/mini/semaphore.cpp new file mode 100644 index 0000000..e798563 --- /dev/null +++ b/src/mini/semaphore.cpp @@ -0,0 +1,61 @@ +#include "mini/semaphore.hpp" +#include "lsfg.hpp" +#include + +using namespace Mini; + +Semaphore::Semaphore(VkDevice device) { + // create semaphore + const VkSemaphoreCreateInfo desc{ + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO + }; + VkSemaphore semaphoreHandle{}; + auto res = vkCreateSemaphore(device, &desc, nullptr, &semaphoreHandle); + if (res != VK_SUCCESS || semaphoreHandle == VK_NULL_HANDLE) + throw LSFG::vulkan_error(res, "Unable to create semaphore"); + + // store semaphore in shared ptr + this->semaphore = std::shared_ptr( + new VkSemaphore(semaphoreHandle), + [dev = device](VkSemaphore* semaphoreHandle) { + vkDestroySemaphore(dev, *semaphoreHandle, nullptr); + } + ); +} + +Semaphore::Semaphore(VkDevice device, int* fd) { + // create semaphore + const VkExportSemaphoreCreateInfo exportInfo{ + .sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO, + .handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT + }; + const VkSemaphoreCreateInfo desc{ + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, + .pNext = &exportInfo + }; + VkSemaphore semaphoreHandle{}; + auto res = vkCreateSemaphore(device, &desc, nullptr, &semaphoreHandle); + if (res != VK_SUCCESS || semaphoreHandle == VK_NULL_HANDLE) + throw LSFG::vulkan_error(res, "Unable to create semaphore"); + + // export semaphore to fd + auto vkGetSemaphoreFdKHR = reinterpret_cast( + vkGetDeviceProcAddr(device, "vkGetSemaphoreFdKHR")); + + const VkSemaphoreGetFdInfoKHR fdInfo{ + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR, + .semaphore = semaphoreHandle, + .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT + }; + res = vkGetSemaphoreFdKHR(device, &fdInfo, fd); + if (res != VK_SUCCESS || *fd < 0) + throw LSFG::vulkan_error(res, "Unable to export semaphore to fd"); + + // store semaphore in shared ptr + this->semaphore = std::shared_ptr( + new VkSemaphore(semaphoreHandle), + [dev = device](VkSemaphore* semaphoreHandle) { + vkDestroySemaphore(dev, *semaphoreHandle, nullptr); + } + ); +}