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 #include "aemu/base/ThreadAnnotations.h"
29
30 namespace gfxstream {
31 namespace vk {
32
33 class DeviceOpTracker;
34 using DeviceOpTrackerPtr = std::shared_ptr<DeviceOpTracker>;
35
36 using DeviceOpWaitable = std::shared_future<void>;
37
IsDone(const DeviceOpWaitable & waitable)38 inline bool IsDone(const DeviceOpWaitable& waitable) {
39 return waitable.wait_for(std::chrono::milliseconds(0)) == std::future_status::ready;
40 }
41
42 enum class DeviceOpStatus { kPending, kDone, kFailure };
43
44 // Helper class to track the completion of host operations for a specific VkDevice.
45 class DeviceOpTracker {
46 public:
47 DeviceOpTracker(VkDevice device, VulkanDispatch* deviceDispatch);
48
49 DeviceOpTracker(const DeviceOpTracker& rhs) = delete;
50 DeviceOpTracker& operator=(const DeviceOpTracker& rhs) = delete;
51
52 DeviceOpTracker(DeviceOpTracker&& rhs) = delete;
53 DeviceOpTracker& operator=(DeviceOpTracker&& rhs) = delete;
54
55 // Transfers ownership of the fence to this helper and marks that the given fence
56 // can be destroyed once the waitable has finished.
57 void AddPendingGarbage(DeviceOpWaitable waitable, VkFence fence);
58
59 // Transfers ownership of the semaphore to this helper and marks that the given
60 // semaphore can be destroyed once the waitable has finished.
61 void AddPendingGarbage(DeviceOpWaitable waitable, VkSemaphore semaphore);
62
63 // Checks for completion of previously submitted waitables and destroys dependent
64 // objects.
65 void PollAndProcessGarbage();
66
67 void OnDestroyDevice();
68
69 private:
70 VkDevice mDevice = VK_NULL_HANDLE;
71 VulkanDispatch* mDeviceDispatch = nullptr;
72
73 friend class DeviceOpBuilder;
74
75 using OpPollingFunction = std::function<DeviceOpStatus()>;
76
77 void AddPendingDeviceOp(OpPollingFunction pollFunction);
78 struct PollFunction {
79 OpPollingFunction func;
80 std::chrono::time_point<std::chrono::system_clock> timepoint;
81 };
82 std::mutex mPollFunctionsMutex;
83 std::deque<PollFunction> mPollFunctions GUARDED_BY(mPollFunctionsMutex);
84
85 struct PendingGarbage {
86 DeviceOpWaitable waitable;
87 std::variant<VkFence, VkSemaphore> obj;
88 std::chrono::time_point<std::chrono::system_clock> timepoint;
89 };
90 std::mutex mPendingGarbageMutex;
91 std::deque<PendingGarbage> mPendingGarbage GUARDED_BY(mPendingGarbageMutex);
92 };
93
94 class DeviceOpBuilder {
95 public:
96 DeviceOpBuilder(DeviceOpTracker& tracker);
97
98 DeviceOpBuilder(const DeviceOpBuilder& rhs) = delete;
99 DeviceOpBuilder& operator=(const DeviceOpBuilder& rhs) = delete;
100
101 DeviceOpBuilder(DeviceOpBuilder&& rhs) = delete;
102 DeviceOpBuilder& operator=(DeviceOpBuilder&& rhs) = delete;
103
104 ~DeviceOpBuilder();
105
106 // Returns a VkFence that can be used to track resource usage for
107 // host ops if a VkFence is not already readily available. This
108 // DeviceOpBuilder and its underlying DeviceOpTracker maintain
109 // ownership of the VkFence and will destroy it when then host op
110 // has completed.
111 VkFence CreateFenceForOp();
112
113 // Returns a waitable that can be used to check whether a host op
114 // has completed.
115 DeviceOpWaitable OnQueueSubmittedWithFence(VkFence fence);
116
117 private:
118 DeviceOpTracker& mTracker;
119
120 std::optional<VkFence> mCreatedFence;
121 std::optional<VkFence> mSubmittedFence;
122 };
123
124 } // namespace vk
125 } // namespace gfxstream