xref: /aosp_15_r20/external/executorch/backends/vulkan/runtime/vk_api/Fence.h (revision 523fa7a60841cd1ecfb9cc4201f1ca8b03ed023a)
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