1 // Copyright 2024 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either expresso or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #pragma once
16
17 #include <vulkan/vulkan.h>
18
19 #include <chrono>
20 #include <deque>
21 #include <functional>
22 #include <future>
23 #include <mutex>
24 #include <optional>
25 #include <variant>
26
27 #include "VulkanDispatch.h"
28
29 namespace gfxstream {
30 namespace vk {
31
32 class DeviceOpTracker;
33 using DeviceOpTrackerPtr = std::shared_ptr<DeviceOpTracker>;
34
35 using DeviceOpWaitable = std::shared_future<void>;
36
IsDone(const DeviceOpWaitable & waitable)37 inline bool IsDone(const DeviceOpWaitable& waitable) {
38 return waitable.wait_for(std::chrono::milliseconds(0)) == std::future_status::ready;
39 }
40
41 enum class DeviceOpStatus { kPending, kDone, kFailure };
42
43 // Helper class to track the completion of host operations for a specific VkDevice.
44 class DeviceOpTracker {
45 public:
46 DeviceOpTracker(VkDevice device, VulkanDispatch* deviceDispatch);
47
48 DeviceOpTracker(const DeviceOpTracker& rhs) = delete;
49 DeviceOpTracker& operator=(const DeviceOpTracker& rhs) = delete;
50
51 DeviceOpTracker(DeviceOpTracker&& rhs) = delete;
52 DeviceOpTracker& operator=(DeviceOpTracker&& rhs) = delete;
53
54 // Transfers ownership of the fence to this helper and marks that the given fence
55 // can be destroyed once the waitable has finished.
56 void AddPendingGarbage(DeviceOpWaitable waitable, VkFence fence);
57
58 // Transfers ownership of the semaphore to this helper and marks that the given
59 // semaphore can be destroyed once the waitable has finished.
60 void AddPendingGarbage(DeviceOpWaitable waitable, VkSemaphore semaphore);
61
62 // Checks for completion of previously submitted waitables and sets their state accordingly .
63 // This function is thread-safe
64 void Poll();
65
66 // Calls Poll(), and also destroys dependent objects accordingly
67 void PollAndProcessGarbage();
68
69 void OnDestroyDevice();
70
71 private:
72 VkDevice mDevice = VK_NULL_HANDLE;
73 VulkanDispatch* mDeviceDispatch = nullptr;
74
75 friend class DeviceOpBuilder;
76
77 using OpPollingFunction = std::function<DeviceOpStatus()>;
78
79 void AddPendingDeviceOp(OpPollingFunction pollFunction);
80 struct PollFunction {
81 OpPollingFunction func;
82 std::chrono::time_point<std::chrono::system_clock> timepoint;
83 };
84 std::mutex mPollFunctionsMutex;
85 std::deque<PollFunction> mPollFunctions;
86
87 struct PendingGarbage {
88 DeviceOpWaitable waitable;
89 std::variant<VkFence, VkSemaphore> obj;
90 std::chrono::time_point<std::chrono::system_clock> timepoint;
91 };
92 std::mutex mPendingGarbageMutex;
93 std::deque<PendingGarbage> mPendingGarbage;
94 };
95
96 class DeviceOpBuilder {
97 public:
98 DeviceOpBuilder(DeviceOpTracker& tracker);
99
100 DeviceOpBuilder(const DeviceOpBuilder& rhs) = delete;
101 DeviceOpBuilder& operator=(const DeviceOpBuilder& rhs) = delete;
102
103 DeviceOpBuilder(DeviceOpBuilder&& rhs) = delete;
104 DeviceOpBuilder& operator=(DeviceOpBuilder&& rhs) = delete;
105
106 ~DeviceOpBuilder();
107
108 // Returns a VkFence that can be used to track resource usage for
109 // host ops if a VkFence is not already readily available. This
110 // DeviceOpBuilder and its underlying DeviceOpTracker maintain
111 // ownership of the VkFence and will destroy it when then host op
112 // has completed.
113 VkFence CreateFenceForOp();
114
115 // Returns a waitable that can be used to check whether a host op
116 // has completed.
117 DeviceOpWaitable OnQueueSubmittedWithFence(VkFence fence);
118
119 private:
120 DeviceOpTracker& mTracker;
121
122 std::optional<VkFence> mCreatedFence;
123 std::optional<VkFence> mSubmittedFence;
124 };
125
126 } // namespace vk
127 } // namespace gfxstream