1 /* 2 * Copyright (c) Meta Platforms, Inc. and affiliates. 3 * All rights reserved. 4 * 5 * This source code is licensed under the BSD-style license found in the 6 * LICENSE file in the root directory of this source tree. 7 */ 8 9 #pragma once 10 11 // @lint-ignore-every CLANGTIDY facebook-hte-BadMemberName 12 13 #include <executorch/backends/vulkan/runtime/vk_api/vk_api.h> 14 15 #include <executorch/backends/vulkan/runtime/vk_api/Exception.h> 16 17 #include <stack> 18 19 namespace vkcompute { 20 namespace vkapi { 21 22 class VulkanFence final { 23 public: 24 // TODO: This is required for the lazy allocation pattern in api::vTensor. 25 // It will be disabled pending future refactors. 26 explicit VulkanFence(); 27 28 explicit VulkanFence(VkDevice); 29 30 VulkanFence(const VulkanFence&) = delete; 31 VulkanFence& operator=(const VulkanFence&) = delete; 32 33 VulkanFence(VulkanFence&&) noexcept; 34 VulkanFence& operator=(VulkanFence&&) noexcept; 35 36 ~VulkanFence(); 37 38 private: 39 VkDevice device_; 40 VkFence handle_; 41 bool waiting_; 42 43 public: 44 // Used to get the handle for a queue submission. get_submit_handle()45 VkFence get_submit_handle() { 46 if (handle_ != VK_NULL_HANDLE) { 47 // Indicate we are now waiting for this fence to be signaled 48 waiting_ = true; 49 } 50 return handle_; 51 } 52 handle()53 VkFence handle() { 54 return handle_; 55 } 56 57 // Trigger a synchronous wait for the fence to be signaled 58 void wait(); 59 waiting()60 bool waiting() const { 61 return waiting_; 62 } 63 64 operator bool() const { 65 return (handle_ != VK_NULL_HANDLE); 66 } 67 }; 68 69 // A pool to track created Fences and reuse ones that are available. 70 // Only intended to be modified by one thread at a time. 71 struct FencePool final { 72 VkDevice device_; 73 74 std::stack<VulkanFence> pool_; 75 FencePoolfinal76 explicit FencePool(VkDevice device) : device_(device), pool_{} {} 77 78 // Returns an rvalue reference to a fence, so that it can be moved get_fencefinal79 inline VulkanFence get_fence() { 80 if (pool_.empty()) { 81 VulkanFence new_fence = VulkanFence(device_); 82 return new_fence; 83 } 84 85 VulkanFence top_fence = std::move(pool_.top()); 86 pool_.pop(); 87 88 return top_fence; 89 } 90 91 // Marks the fence as available return_fencefinal92 inline void return_fence(VulkanFence& fence) { 93 pool_.push(std::move(fence)); 94 } 95 }; 96 97 } // namespace vkapi 98 } // namespace vkcompute 99