// Copyright 2021 yuzu Emulator Project // Licensed under GPLv3 or any later version // Refer to the license.txt file included. #pragma once #include #include #include #include #include #include #include "common/common_types.h" namespace Tegra { namespace Host1x { class SyncpointManager { public: u32 GetGuestSyncpointValue(u32 id) { return syncpoints_guest[id].load(std::memory_order_acquire); } u32 GetHostSyncpointValue(u32 id) { return syncpoints_host[id].load(std::memory_order_acquire); } struct RegisteredAction { RegisteredAction(u32 expected_value_, std::function& action_) : expected_value{expected_value_}, action{action_} {} u32 expected_value; std::function action; }; using ActionHandle = std::list::iterator; template ActionHandle RegisterGuestAction(u32 syncpoint_id, u32 expected_value, Func&& action) { std::function func(action); return RegisterAction(syncpoints_guest[syncpoint_id], guest_action_storage[syncpoint_id], expected_value, func); } template ActionHandle RegisterHostAction(u32 syncpoint_id, u32 expected_value, Func&& action) { std::function func(action); return RegisterAction(syncpoints_host[syncpoint_id], host_action_storage[syncpoint_id], expected_value, func); } void DeregisterGuestAction(u32 syncpoint_id, ActionHandle& handle); void DeregisterHostAction(u32 syncpoint_id, ActionHandle& handle); void IncrementGuest(u32 syncpoint_id); void IncrementHost(u32 syncpoint_id); void WaitGuest(u32 syncpoint_id, u32 expected_value); void WaitHost(u32 syncpoint_id, u32 expected_value); bool IsReadyGuest(u32 syncpoint_id, u32 expected_value) { return syncpoints_guest[syncpoint_id].load(std::memory_order_acquire) >= expected_value; } bool IsReadyHost(u32 syncpoint_id, u32 expected_value) { return syncpoints_host[syncpoint_id].load(std::memory_order_acquire) >= expected_value; } private: void Increment(std::atomic& syncpoint, std::condition_variable& wait_cv, std::list& action_storage); ActionHandle RegisterAction(std::atomic& syncpoint, std::list& action_storage, u32 expected_value, std::function& action); void DeregisterAction(std::list& action_storage, ActionHandle& handle); void Wait(std::atomic& syncpoint, std::condition_variable& wait_cv, u32 expected_value); static constexpr size_t NUM_MAX_SYNCPOINTS = 192; std::array, NUM_MAX_SYNCPOINTS> syncpoints_guest{}; std::array, NUM_MAX_SYNCPOINTS> syncpoints_host{}; std::array, NUM_MAX_SYNCPOINTS> guest_action_storage; std::array, NUM_MAX_SYNCPOINTS> host_action_storage; std::mutex guard; std::condition_variable wait_guest_cv; std::condition_variable wait_host_cv; }; } // namespace Host1x } // namespace Tegra