blob: acd7782be2a8c69281dc84e2e8017185560d933b [file] [log] [blame]
Jason Macnak9a061662024-04-15 08:51:37 -07001// 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
29namespace gfxstream {
30namespace vk {
31
Gurchetan Singh1cc4e5c2024-06-14 01:24:17 +000032class DeviceOpTracker;
33using DeviceOpTrackerPtr = std::shared_ptr<DeviceOpTracker>;
34
Jason Macnak9a061662024-04-15 08:51:37 -070035using DeviceOpWaitable = std::shared_future<void>;
36
37inline bool IsDone(const DeviceOpWaitable& waitable) {
38 return waitable.wait_for(std::chrono::milliseconds(0)) == std::future_status::ready;
39}
40
41enum class DeviceOpStatus { kPending, kDone, kFailure };
42
43// Helper class to track the completion of host operations for a specific VkDevice.
44class 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
Gurchetan Singh1cc4e5c2024-06-14 01:24:17 +000062 // 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
Jason Macnak9a061662024-04-15 08:51:37 -070067 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
81 std::mutex mPollFunctionsMutex;
82 std::deque<OpPollingFunction> mPollFunctions;
83
84 struct PendingGarabage {
85 DeviceOpWaitable waitable;
86 std::variant<VkFence, VkSemaphore> obj;
87 std::chrono::time_point<std::chrono::system_clock> timepoint;
88 };
89 std::mutex mPendingGarbageMutex;
90 std::deque<PendingGarabage> mPendingGarbage;
91};
92
93class DeviceOpBuilder {
94 public:
95 DeviceOpBuilder(DeviceOpTracker& tracker);
96
97 DeviceOpBuilder(const DeviceOpBuilder& rhs) = delete;
98 DeviceOpBuilder& operator=(const DeviceOpBuilder& rhs) = delete;
99
100 DeviceOpBuilder(DeviceOpBuilder&& rhs) = delete;
101 DeviceOpBuilder& operator=(DeviceOpBuilder&& rhs) = delete;
102
103 ~DeviceOpBuilder();
104
105 // Returns a VkFence that can be used to track resource usage for
106 // host ops if a VkFence is not already readily available. This
107 // DeviceOpBuilder and its underlying DeviceOpTracker maintain
108 // ownership of the VkFence and will destroy it when then host op
109 // has completed.
110 VkFence CreateFenceForOp();
111
112 // Returns a waitable that can be used to check whether a host op
113 // has completed.
114 DeviceOpWaitable OnQueueSubmittedWithFence(VkFence fence);
115
116 private:
117 DeviceOpTracker& mTracker;
118
119 std::optional<VkFence> mCreatedFence;
120 std::optional<VkFence> mSubmittedFence;
121};
122
123} // namespace vk
124} // namespace gfxstream