blob: acd7782be2a8c69281dc84e2e8017185560d933b [file] [log] [blame]
// Copyright 2024 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either expresso or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <vulkan/vulkan.h>
#include <chrono>
#include <deque>
#include <functional>
#include <future>
#include <mutex>
#include <optional>
#include <variant>
#include "VulkanDispatch.h"
namespace gfxstream {
namespace vk {
class DeviceOpTracker;
using DeviceOpTrackerPtr = std::shared_ptr<DeviceOpTracker>;
using DeviceOpWaitable = std::shared_future<void>;
inline bool IsDone(const DeviceOpWaitable& waitable) {
return waitable.wait_for(std::chrono::milliseconds(0)) == std::future_status::ready;
}
enum class DeviceOpStatus { kPending, kDone, kFailure };
// Helper class to track the completion of host operations for a specific VkDevice.
class DeviceOpTracker {
public:
DeviceOpTracker(VkDevice device, VulkanDispatch* deviceDispatch);
DeviceOpTracker(const DeviceOpTracker& rhs) = delete;
DeviceOpTracker& operator=(const DeviceOpTracker& rhs) = delete;
DeviceOpTracker(DeviceOpTracker&& rhs) = delete;
DeviceOpTracker& operator=(DeviceOpTracker&& rhs) = delete;
// Transfers ownership of the fence to this helper and marks that the given fence
// can be destroyed once the waitable has finished.
void AddPendingGarbage(DeviceOpWaitable waitable, VkFence fence);
// Transfers ownership of the semaphore to this helper and marks that the given
// semaphore can be destroyed once the waitable has finished.
void AddPendingGarbage(DeviceOpWaitable waitable, VkSemaphore semaphore);
// Checks for completion of previously submitted waitables and sets their state accordingly .
// This function is thread-safe
void Poll();
// Calls Poll(), and also destroys dependent objects accordingly
void PollAndProcessGarbage();
void OnDestroyDevice();
private:
VkDevice mDevice = VK_NULL_HANDLE;
VulkanDispatch* mDeviceDispatch = nullptr;
friend class DeviceOpBuilder;
using OpPollingFunction = std::function<DeviceOpStatus()>;
void AddPendingDeviceOp(OpPollingFunction pollFunction);
std::mutex mPollFunctionsMutex;
std::deque<OpPollingFunction> mPollFunctions;
struct PendingGarabage {
DeviceOpWaitable waitable;
std::variant<VkFence, VkSemaphore> obj;
std::chrono::time_point<std::chrono::system_clock> timepoint;
};
std::mutex mPendingGarbageMutex;
std::deque<PendingGarabage> mPendingGarbage;
};
class DeviceOpBuilder {
public:
DeviceOpBuilder(DeviceOpTracker& tracker);
DeviceOpBuilder(const DeviceOpBuilder& rhs) = delete;
DeviceOpBuilder& operator=(const DeviceOpBuilder& rhs) = delete;
DeviceOpBuilder(DeviceOpBuilder&& rhs) = delete;
DeviceOpBuilder& operator=(DeviceOpBuilder&& rhs) = delete;
~DeviceOpBuilder();
// Returns a VkFence that can be used to track resource usage for
// host ops if a VkFence is not already readily available. This
// DeviceOpBuilder and its underlying DeviceOpTracker maintain
// ownership of the VkFence and will destroy it when then host op
// has completed.
VkFence CreateFenceForOp();
// Returns a waitable that can be used to check whether a host op
// has completed.
DeviceOpWaitable OnQueueSubmittedWithFence(VkFence fence);
private:
DeviceOpTracker& mTracker;
std::optional<VkFence> mCreatedFence;
std::optional<VkFence> mSubmittedFence;
};
} // namespace vk
} // namespace gfxstream