/* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. */ #pragma once // @lint-ignore-every CLANGTIDY facebook-hte-BadMemberName #include #include #include namespace vkcompute { namespace vkapi { class VulkanFence final { public: // TODO: This is required for the lazy allocation pattern in api::vTensor. // It will be disabled pending future refactors. explicit VulkanFence(); explicit VulkanFence(VkDevice); VulkanFence(const VulkanFence&) = delete; VulkanFence& operator=(const VulkanFence&) = delete; VulkanFence(VulkanFence&&) noexcept; VulkanFence& operator=(VulkanFence&&) noexcept; ~VulkanFence(); private: VkDevice device_; VkFence handle_; bool waiting_; public: // Used to get the handle for a queue submission. VkFence get_submit_handle() { if (handle_ != VK_NULL_HANDLE) { // Indicate we are now waiting for this fence to be signaled waiting_ = true; } return handle_; } VkFence handle() { return handle_; } // Trigger a synchronous wait for the fence to be signaled void wait(); bool waiting() const { return waiting_; } operator bool() const { return (handle_ != VK_NULL_HANDLE); } }; // A pool to track created Fences and reuse ones that are available. // Only intended to be modified by one thread at a time. struct FencePool final { VkDevice device_; std::stack pool_; explicit FencePool(VkDevice device) : device_(device), pool_{} {} // Returns an rvalue reference to a fence, so that it can be moved inline VulkanFence get_fence() { if (pool_.empty()) { VulkanFence new_fence = VulkanFence(device_); return new_fence; } VulkanFence top_fence = std::move(pool_.top()); pool_.pop(); return top_fence; } // Marks the fence as available inline void return_fence(VulkanFence& fence) { pool_.push(std::move(fence)); } }; } // namespace vkapi } // namespace vkcompute