// SPDX-License-Identifier: MPL-2.0 // Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/) #pragma once #include #include "common.h" namespace skyline::gpu::interconnect { /** * @brief Caches guest shader binaries and their memory locations */ class ShaderCache { private: /** * @brief Holds mirror state for a single GPU mapped block */ struct MirrorEntry { span mirror; tsl::robin_map> cache; std::optional trap; static constexpr u32 SkipTrapThreshold{20}; //!< Threshold for the number of times a mirror trap needs to be hit before we fallback to always hashing u32 trapCount{}; //!< The number of times the trap has been hit, used to avoid trapping in cases where the constant retraps would harm performance ContextTag executionTag{}; //!< For the case where `trapCount > SkipTrapThreshold`, the memory sequence number number used to clear the cache after every access bool dirty{}; //!< If the trap has been hit and the cache needs to be cleared MirrorEntry(span alignedMirror) : mirror{alignedMirror} {} }; tsl::robin_map> mirrorMap; std::recursive_mutex trapMutex; //!< Protects accesses from trap handlers to the mirror map std::optional> trapExecutionLock; //!< Persistently held lock over an execution to avoid frequent relocking MirrorEntry *entry{}; span mirrorBlock{}; //!< Guest mapped memory block corresponding to `entry` u64 lastProgramBase{}; u32 lastProgramOffset{}; std::vector splitBinaryStorage; public: /** * @brief Returns the shader binary located at the given address */ std::pair Lookup(InterconnectContext &ctx, u64 programBase, u32 programOffset); bool Refresh(InterconnectContext &ctx, u64 programBase, u32 programOffset); void PurgeCaches(); }; }