diff options
Diffstat (limited to 'src/core/hle/service/nvdrv/core/syncpoint_manager.h')
-rw-r--r-- | src/core/hle/service/nvdrv/core/syncpoint_manager.h | 120 |
1 files changed, 83 insertions, 37 deletions
diff --git a/src/core/hle/service/nvdrv/core/syncpoint_manager.h b/src/core/hle/service/nvdrv/core/syncpoint_manager.h index f332edc6e..bfc8ba84b 100644 --- a/src/core/hle/service/nvdrv/core/syncpoint_manager.h +++ b/src/core/hle/service/nvdrv/core/syncpoint_manager.h @@ -1,10 +1,13 @@ -// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later +// SPDX-FileCopyrightText: 2022 yuzu emulator team and Skyline Team and Contributors +// (https://github.com/skyline-emu/) +// SPDX-License-Identifier: GPL-3.0-or-later Licensed under GPLv3 +// or any later version Refer to the license.txt file included. #pragma once #include <array> #include <atomic> +#include <mutex> #include "common/common_types.h" #include "core/hle/service/nvdrv/nvdata.h" @@ -19,68 +22,111 @@ class Host1x; namespace Service::Nvidia::NvCore { +enum class ChannelType : u32 { + MsEnc = 0, + VIC = 1, + GPU = 2, + NvDec = 3, + Display = 4, + NvJpg = 5, + TSec = 6, + Max = 7 +}; + +/** + * @brief SyncpointManager handles allocating and accessing host1x syncpoints, these are cached + * versions of the HW syncpoints which are intermittently synced + * @note Refer to Chapter 14 of the Tegra X1 TRM for an exhaustive overview of them + * @url https://http.download.nvidia.com/tegra-public-appnotes/host1x.html + * @url + * https://github.com/Jetson-TX1-AndroidTV/android_kernel_jetson_tx1_hdmi_primary/blob/jetson-tx1/drivers/video/tegra/host/nvhost_syncpt.c + */ class SyncpointManager final { public: explicit SyncpointManager(Tegra::Host1x::Host1x& host1x); ~SyncpointManager(); /** - * Returns true if the specified syncpoint is expired for the given value. - * @param syncpoint_id Syncpoint ID to check. - * @param value Value to check against the specified syncpoint. - * @returns True if the specified syncpoint is expired for the given value, otherwise False. + * @brief Checks if the given syncpoint is both allocated and below the number of HW syncpoints */ - bool IsSyncpointExpired(u32 syncpoint_id, u32 value) const { - return (GetSyncpointMax(syncpoint_id) - value) >= (GetSyncpointMin(syncpoint_id) - value); - } + bool IsSyncpointAllocated(u32 id); /** - * Gets the lower bound for the specified syncpoint. - * @param syncpoint_id Syncpoint ID to get the lower bound for. - * @returns The lower bound for the specified syncpoint. + * @brief Finds a free syncpoint and reserves it + * @return The ID of the reserved syncpoint */ - u32 GetSyncpointMin(u32 syncpoint_id) const { - return syncpoints.at(syncpoint_id).min.load(std::memory_order_relaxed); - } + u32 AllocateSyncpoint(bool clientManaged); /** - * Gets the uper bound for the specified syncpoint. - * @param syncpoint_id Syncpoint ID to get the upper bound for. - * @returns The upper bound for the specified syncpoint. + * @url + * https://github.com/Jetson-TX1-AndroidTV/android_kernel_jetson_tx1_hdmi_primary/blob/8f74a72394efb871cb3f886a3de2998cd7ff2990/drivers/gpu/host1x/syncpt.c#L259 */ - u32 GetSyncpointMax(u32 syncpoint_id) const { - return syncpoints.at(syncpoint_id).max.load(std::memory_order_relaxed); + bool HasSyncpointExpired(u32 id, u32 threshold); + + bool IsFenceSignalled(NvFence fence) { + return HasSyncpointExpired(fence.id, fence.value); } /** - * Refreshes the minimum value for the specified syncpoint. - * @param syncpoint_id Syncpoint ID to be refreshed. - * @returns The new syncpoint minimum value. + * @brief Atomically increments the maximum value of a syncpoint by the given amount + * @return The new max value of the syncpoint */ - u32 RefreshSyncpoint(u32 syncpoint_id); + u32 IncrementSyncpointMaxExt(u32 id, u32 amount); /** - * Allocates a new syncoint. - * @returns The syncpoint ID for the newly allocated syncpoint. + * @return The minimum value of the syncpoint */ - u32 AllocateSyncpoint(); + u32 ReadSyncpointMinValue(u32 id); /** - * Increases the maximum value for the specified syncpoint. - * @param syncpoint_id Syncpoint ID to be increased. - * @param value Value to increase the specified syncpoint by. - * @returns The new syncpoint maximum value. + * @brief Synchronises the minimum value of the syncpoint to with the GPU + * @return The new minimum value of the syncpoint */ - u32 IncreaseSyncpoint(u32 syncpoint_id, u32 value); + u32 UpdateMin(u32 id); + + /** + * @return A fence that will be signalled once this syncpoint hits its maximum value + */ + NvFence GetSyncpointFence(u32 id); + + static constexpr std::array<u32, static_cast<u32>(ChannelType::Max)> channel_syncpoints{ + 0x0, // `MsEnc` is unimplemented + 0xC, // `VIC` + 0x0, // `GPU` syncpoints are allocated per-channel instead + 0x36, // `NvDec` + 0x0, // `Display` is unimplemented + 0x37, // `NvJpg` + 0x0, // `TSec` is unimplemented + }; //!< Maps each channel ID to a constant syncpoint private: - struct Syncpoint { - std::atomic<u32> min; - std::atomic<u32> max; - std::atomic<bool> is_allocated; + /** + * @note reservation_lock should be locked when calling this + */ + u32 ReserveSyncpoint(u32 id, bool clientManaged); + + /** + * @return The ID of the first free syncpoint + */ + u32 FindFreeSyncpoint(); + + struct SyncpointInfo { + std::atomic<u32> counterMin; //!< The least value the syncpoint can be (The value it was + //!< when it was last synchronized with host1x) + std::atomic<u32> counterMax; //!< The maximum value the syncpoint can reach according to the + //!< current usage + bool interfaceManaged; //!< If the syncpoint is managed by a host1x client interface, a + //!< client interface is a HW block that can handle host1x + //!< transactions on behalf of a host1x client (Which would otherwise + //!< need to be manually synced using PIO which is synchronous and + //!< requires direct cooperation of the CPU) + bool reserved; //!< If the syncpoint is reserved or not, not to be confused with a reserved + //!< value }; - std::array<Syncpoint, MaxSyncPoints> syncpoints{}; + constexpr static std::size_t SyncpointCount{192}; + std::array<SyncpointInfo, SyncpointCount> syncpoints{}; + std::mutex reservation_lock; Tegra::Host1x::Host1x& host1x; }; |