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