diff options
author | yuzubot <[email protected]> | 2024-03-04 00:57:21 +0000 |
---|---|---|
committer | yuzubot <[email protected]> | 2024-03-04 00:57:21 +0000 |
commit | 276ceb26d0c58a00a0e65e3bf4d9c4371428f82d (patch) | |
tree | 587c6b5415501f1b1a1795ddd6df8d3403252cb4 /src/video_core/host1x/host1x.h | |
parent | 15e6e48bef0216480661444a8d8b348c1cca47bb (diff) | |
download | yuzu-android-276ceb26d0c58a00a0e65e3bf4d9c4371428f82d.tar.gz yuzu-android-276ceb26d0c58a00a0e65e3bf4d9c4371428f82d.zip |
Merge yuzu-emu#12461
Diffstat (limited to 'src/video_core/host1x/host1x.h')
-rw-r--r-- | src/video_core/host1x/host1x.h | 148 |
1 files changed, 143 insertions, 5 deletions
diff --git a/src/video_core/host1x/host1x.h b/src/video_core/host1x/host1x.h index d72d97b7b..8debac93d 100644 --- a/src/video_core/host1x/host1x.h +++ b/src/video_core/host1x/host1x.h @@ -3,9 +3,14 @@ #pragma once +#include <unordered_map> +#include <unordered_set> +#include <queue> + #include "common/common_types.h" #include "common/address_space.h" +#include "video_core/cdma_pusher.h" #include "video_core/host1x/gpu_device_memory_manager.h" #include "video_core/host1x/syncpoint_manager.h" #include "video_core/memory_manager.h" @@ -14,15 +19,137 @@ namespace Core { class System; } // namespace Core -namespace Tegra { +namespace FFmpeg { +class Frame; +} // namespace FFmpeg + +namespace Tegra::Host1x { +class Nvdec; + +class FrameQueue { +public: + void Open(s32 fd) { + std::scoped_lock l{m_mutex}; + m_presentation_order.insert({fd, {}}); + m_decode_order.insert({fd, {}}); + } + + void Close(s32 fd) { + std::scoped_lock l{m_mutex}; + m_presentation_order.erase(fd); + m_decode_order.erase(fd); + } + + s32 VicFindNvdecFdFromOffset(u64 search_offset) { + std::scoped_lock l{m_mutex}; + // Vic does not know which nvdec is producing frames for it, so search all the fds here for + // the given offset. + for (auto& map : m_presentation_order) { + for (auto& [offset, frame] : map.second) { + if (offset == search_offset) { + return map.first; + } + } + } + + for (auto& map : m_decode_order) { + for (auto& [offset, frame] : map.second) { + if (offset == search_offset) { + return map.first; + } + } + } + + return -1; + } -namespace Host1x { + void PushPresentOrder(s32 fd, u64 offset, std::shared_ptr<FFmpeg::Frame>&& frame) { + std::scoped_lock l{m_mutex}; + auto map = m_presentation_order.find(fd); + if (map == m_presentation_order.end()) { + return; + } + map->second.emplace_back(offset, std::move(frame)); + } + + void PushDecodeOrder(s32 fd, u64 offset, std::shared_ptr<FFmpeg::Frame>&& frame) { + std::scoped_lock l{m_mutex}; + auto map = m_decode_order.find(fd); + if (map == m_decode_order.end()) { + return; + } + map->second.insert_or_assign(offset, std::move(frame)); + } + + std::shared_ptr<FFmpeg::Frame> GetFrame(s32 fd, u64 offset) { + if (fd == -1) { + return {}; + } + + std::scoped_lock l{m_mutex}; + auto present_map = m_presentation_order.find(fd); + if (present_map != m_presentation_order.end() && present_map->second.size() > 0) { + return GetPresentOrderLocked(fd); + } + + auto decode_map = m_decode_order.find(fd); + if (decode_map != m_decode_order.end() && decode_map->second.size() > 0) { + return GetDecodeOrderLocked(fd, offset); + } + + return {}; + } + +private: + std::shared_ptr<FFmpeg::Frame> GetPresentOrderLocked(s32 fd) { + auto map = m_presentation_order.find(fd); + if (map == m_presentation_order.end() || map->second.size() == 0) { + return {}; + } + auto frame = std::move(map->second.front().second); + map->second.pop_front(); + return frame; + } + + std::shared_ptr<FFmpeg::Frame> GetDecodeOrderLocked(s32 fd, u64 offset) { + auto map = m_decode_order.find(fd); + if (map == m_decode_order.end() || map->second.size() == 0) { + return {}; + } + auto it = map->second.find(offset); + if (it == map->second.end()) { + return {}; + } + return std::move(map->second.extract(it).mapped()); + } + + using FramePtr = std::shared_ptr<FFmpeg::Frame>; + + std::mutex m_mutex{}; + std::unordered_map<s32, std::deque<std::pair<u64, FramePtr>>> m_presentation_order; + std::unordered_map<s32, std::unordered_map<u64, FramePtr>> m_decode_order; +}; + +enum class ChannelType : u32 { + MsEnc = 0, + VIC = 1, + GPU = 2, + NvDec = 3, + Display = 4, + NvJpg = 5, + TSec = 6, + Max = 7, +}; class Host1x { public: explicit Host1x(Core::System& system); ~Host1x(); + Core::System& System() { + return system; + } + SyncpointManager& GetSyncpointManager() { return syncpoint_manager; } @@ -55,14 +182,25 @@ public: return *allocator; } + void StartDevice(s32 fd, ChannelType type, u32 syncpt); + void StopDevice(s32 fd, ChannelType type); + + void PushEntries(s32 fd, ChCommandHeaderList&& entries) { + auto it = devices.find(fd); + if (it == devices.end()) { + return; + } + it->second->PushEntries(std::move(entries)); + } + private: Core::System& system; SyncpointManager syncpoint_manager; Tegra::MaxwellDeviceMemoryManager memory_manager; Tegra::MemoryManager gmmu_manager; std::unique_ptr<Common::FlatAllocator<u32, 0, 32>> allocator; + FrameQueue frame_queue; + std::unordered_map<s32, std::unique_ptr<CDmaPusher>> devices; }; -} // namespace Host1x - -} // namespace Tegra +} // namespace Tegra::Host1x |