• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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