diff --git a/lsfg-vk-common/include/lsfg-vk-common/vulkan/timeline_semaphore.hpp b/lsfg-vk-common/include/lsfg-vk-common/vulkan/timeline_semaphore.hpp index e8c88e8..7fa6755 100644 --- a/lsfg-vk-common/include/lsfg-vk-common/vulkan/timeline_semaphore.hpp +++ b/lsfg-vk-common/include/lsfg-vk-common/vulkan/timeline_semaphore.hpp @@ -15,10 +15,12 @@ namespace vk { /// create a timeline semaphore /// @param vk the vulkan instance /// @param initial initial value of the timeline semaphore - /// @param fd optional file descriptor to import the semaphore from + /// @param importFd optional file descriptor to import from + /// @param exportFd optional file descriptor to export to /// @throws ls::vulkan_error on failure TimelineSemaphore(const vk::Vulkan& vk, uint32_t initial, - std::optional fd = std::nullopt); + std::optional importFd = std::nullopt, + std::optional exportFd = std::nullopt); /// signal the timeline semaphore /// @param vk the vulkan instance @@ -34,6 +36,10 @@ namespace vk { /// @throws ls::vulkan_error on failure [[nodiscard]] bool wait(const vk::Vulkan& vk, uint64_t value, uint64_t timeout = UINT64_MAX) const; + + /// get the underlying VkSemaphore handle + /// @return the VkSemaphore handle + [[nodiscard]] const auto& handle() const { return *this->semaphore; } private: ls::owned_ptr semaphore; }; diff --git a/lsfg-vk-common/src/vulkan/timeline_semaphore.cpp b/lsfg-vk-common/src/vulkan/timeline_semaphore.cpp index 74a0e81..05ae0b0 100644 --- a/lsfg-vk-common/src/vulkan/timeline_semaphore.cpp +++ b/lsfg-vk-common/src/vulkan/timeline_semaphore.cpp @@ -13,7 +13,7 @@ using namespace vk; namespace { /// create a timeline semaphore ls::owned_ptr createTimelineSemaphore(const vk::Vulkan& vk, uint32_t initial, - std::optional fd) { + std::optional importFd, std::optional exportFd) { VkSemaphore handle{}; const VkExportSemaphoreCreateInfo exportInfo{ @@ -22,7 +22,7 @@ namespace { }; const VkSemaphoreTypeCreateInfo typeInfo{ .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO, - .pNext = fd.has_value() ? &exportInfo : nullptr, + .pNext = ( importFd.has_value() || exportFd.has_value() ) ? &exportInfo : nullptr, .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE, .initialValue = initial }; @@ -34,7 +34,7 @@ namespace { if (res != VK_SUCCESS) throw ls::vulkan_error(res, "vkCreateSemaphore() failed"); - if (fd.has_value()) { + if (importFd.has_value()) { // import semaphore from fd auto vkImportSemaphoreFdKHR = reinterpret_cast( vkGetDeviceProcAddr(vk.dev(), "vkImportSemaphoreFdKHR")); // TODO: cache @@ -43,13 +43,31 @@ namespace { .sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR, .semaphore = handle, .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT, - .fd = *fd // closes the fd + .fd = *importFd // closes the fd }; res = vkImportSemaphoreFdKHR(vk.dev(), &importInfo); if (res != VK_SUCCESS) throw ls::vulkan_error(res, "vkImportSemaphoreFdKHR() failed"); } + if (exportFd.has_value()) { + // export semaphore to fd + auto vkGetSemaphoreFdKHR = reinterpret_cast( + vkGetDeviceProcAddr(vk.dev(), "vkGetSemaphoreFdKHR")); // TODO: cache + + const VkSemaphoreGetFdInfoKHR getFdInfo{ + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR, + .semaphore = handle, + .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT + }; + int fd{}; + res = vkGetSemaphoreFdKHR(vk.dev(), &getFdInfo, &fd); + if (res != VK_SUCCESS) + throw ls::vulkan_error(res, "vkGetSemaphoreFdKHR() failed"); + + **exportFd = fd; + } + return ls::owned_ptr( new VkSemaphore(handle), [dev = vk.dev()](VkSemaphore& semaphore) { @@ -59,8 +77,9 @@ namespace { } } -TimelineSemaphore::TimelineSemaphore(const vk::Vulkan& vk, uint32_t initial, std::optional fd) - : semaphore(createTimelineSemaphore(vk, initial, fd)) {} +TimelineSemaphore::TimelineSemaphore(const vk::Vulkan& vk, uint32_t initial, + std::optional importFd, std::optional exportFd) + : semaphore(createTimelineSemaphore(vk, initial, importFd, exportFd)) {} void TimelineSemaphore::signal(const vk::Vulkan& vk, uint64_t value) const { const VkSemaphoreSignalInfo signalInfo{