diff options
Diffstat (limited to 'src/video_core/control')
| -rw-r--r-- | src/video_core/control/channel_state.cpp | 40 | ||||
| -rw-r--r-- | src/video_core/control/channel_state.h | 68 | ||||
| -rw-r--r-- | src/video_core/control/channel_state_cache.cpp | 14 | ||||
| -rw-r--r-- | src/video_core/control/channel_state_cache.h | 101 | ||||
| -rw-r--r-- | src/video_core/control/channel_state_cache.inc | 86 | ||||
| -rw-r--r-- | src/video_core/control/scheduler.cpp | 32 | ||||
| -rw-r--r-- | src/video_core/control/scheduler.h | 37 |
7 files changed, 378 insertions, 0 deletions
diff --git a/src/video_core/control/channel_state.cpp b/src/video_core/control/channel_state.cpp new file mode 100644 index 000000000..cdecc3a91 --- /dev/null +++ b/src/video_core/control/channel_state.cpp | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "common/assert.h" | ||
| 5 | #include "video_core/control/channel_state.h" | ||
| 6 | #include "video_core/dma_pusher.h" | ||
| 7 | #include "video_core/engines/fermi_2d.h" | ||
| 8 | #include "video_core/engines/kepler_compute.h" | ||
| 9 | #include "video_core/engines/kepler_memory.h" | ||
| 10 | #include "video_core/engines/maxwell_3d.h" | ||
| 11 | #include "video_core/engines/maxwell_dma.h" | ||
| 12 | #include "video_core/engines/puller.h" | ||
| 13 | #include "video_core/memory_manager.h" | ||
| 14 | |||
| 15 | namespace Tegra::Control { | ||
| 16 | |||
| 17 | ChannelState::ChannelState(s32 bind_id_) : bind_id{bind_id_}, initialized{} {} | ||
| 18 | |||
| 19 | void ChannelState::Init(Core::System& system, GPU& gpu) { | ||
| 20 | ASSERT(memory_manager); | ||
| 21 | dma_pusher = std::make_unique<Tegra::DmaPusher>(system, gpu, *memory_manager, *this); | ||
| 22 | maxwell_3d = std::make_unique<Engines::Maxwell3D>(system, *memory_manager); | ||
| 23 | fermi_2d = std::make_unique<Engines::Fermi2D>(); | ||
| 24 | kepler_compute = std::make_unique<Engines::KeplerCompute>(system, *memory_manager); | ||
| 25 | maxwell_dma = std::make_unique<Engines::MaxwellDMA>(system, *memory_manager); | ||
| 26 | kepler_memory = std::make_unique<Engines::KeplerMemory>(system, *memory_manager); | ||
| 27 | initialized = true; | ||
| 28 | } | ||
| 29 | |||
| 30 | void ChannelState::BindRasterizer(VideoCore::RasterizerInterface* rasterizer) { | ||
| 31 | dma_pusher->BindRasterizer(rasterizer); | ||
| 32 | memory_manager->BindRasterizer(rasterizer); | ||
| 33 | maxwell_3d->BindRasterizer(rasterizer); | ||
| 34 | fermi_2d->BindRasterizer(rasterizer); | ||
| 35 | kepler_memory->BindRasterizer(rasterizer); | ||
| 36 | kepler_compute->BindRasterizer(rasterizer); | ||
| 37 | maxwell_dma->BindRasterizer(rasterizer); | ||
| 38 | } | ||
| 39 | |||
| 40 | } // namespace Tegra::Control | ||
diff --git a/src/video_core/control/channel_state.h b/src/video_core/control/channel_state.h new file mode 100644 index 000000000..3a7b9872c --- /dev/null +++ b/src/video_core/control/channel_state.h | |||
| @@ -0,0 +1,68 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <memory> | ||
| 7 | |||
| 8 | #include "common/common_types.h" | ||
| 9 | |||
| 10 | namespace Core { | ||
| 11 | class System; | ||
| 12 | } | ||
| 13 | |||
| 14 | namespace VideoCore { | ||
| 15 | class RasterizerInterface; | ||
| 16 | } | ||
| 17 | |||
| 18 | namespace Tegra { | ||
| 19 | |||
| 20 | class GPU; | ||
| 21 | |||
| 22 | namespace Engines { | ||
| 23 | class Puller; | ||
| 24 | class Fermi2D; | ||
| 25 | class Maxwell3D; | ||
| 26 | class MaxwellDMA; | ||
| 27 | class KeplerCompute; | ||
| 28 | class KeplerMemory; | ||
| 29 | } // namespace Engines | ||
| 30 | |||
| 31 | class MemoryManager; | ||
| 32 | class DmaPusher; | ||
| 33 | |||
| 34 | namespace Control { | ||
| 35 | |||
| 36 | struct ChannelState { | ||
| 37 | explicit ChannelState(s32 bind_id); | ||
| 38 | ChannelState(const ChannelState& state) = delete; | ||
| 39 | ChannelState& operator=(const ChannelState&) = delete; | ||
| 40 | ChannelState(ChannelState&& other) noexcept = default; | ||
| 41 | ChannelState& operator=(ChannelState&& other) noexcept = default; | ||
| 42 | |||
| 43 | void Init(Core::System& system, GPU& gpu); | ||
| 44 | |||
| 45 | void BindRasterizer(VideoCore::RasterizerInterface* rasterizer); | ||
| 46 | |||
| 47 | s32 bind_id = -1; | ||
| 48 | /// 3D engine | ||
| 49 | std::unique_ptr<Engines::Maxwell3D> maxwell_3d; | ||
| 50 | /// 2D engine | ||
| 51 | std::unique_ptr<Engines::Fermi2D> fermi_2d; | ||
| 52 | /// Compute engine | ||
| 53 | std::unique_ptr<Engines::KeplerCompute> kepler_compute; | ||
| 54 | /// DMA engine | ||
| 55 | std::unique_ptr<Engines::MaxwellDMA> maxwell_dma; | ||
| 56 | /// Inline memory engine | ||
| 57 | std::unique_ptr<Engines::KeplerMemory> kepler_memory; | ||
| 58 | |||
| 59 | std::shared_ptr<MemoryManager> memory_manager; | ||
| 60 | |||
| 61 | std::unique_ptr<DmaPusher> dma_pusher; | ||
| 62 | |||
| 63 | bool initialized{}; | ||
| 64 | }; | ||
| 65 | |||
| 66 | } // namespace Control | ||
| 67 | |||
| 68 | } // namespace Tegra | ||
diff --git a/src/video_core/control/channel_state_cache.cpp b/src/video_core/control/channel_state_cache.cpp new file mode 100644 index 000000000..4ebeb6356 --- /dev/null +++ b/src/video_core/control/channel_state_cache.cpp | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "video_core/control/channel_state_cache.inc" | ||
| 5 | |||
| 6 | namespace VideoCommon { | ||
| 7 | |||
| 8 | ChannelInfo::ChannelInfo(Tegra::Control::ChannelState& channel_state) | ||
| 9 | : maxwell3d{*channel_state.maxwell_3d}, kepler_compute{*channel_state.kepler_compute}, | ||
| 10 | gpu_memory{*channel_state.memory_manager} {} | ||
| 11 | |||
| 12 | template class VideoCommon::ChannelSetupCaches<VideoCommon::ChannelInfo>; | ||
| 13 | |||
| 14 | } // namespace VideoCommon | ||
diff --git a/src/video_core/control/channel_state_cache.h b/src/video_core/control/channel_state_cache.h new file mode 100644 index 000000000..584a0c26c --- /dev/null +++ b/src/video_core/control/channel_state_cache.h | |||
| @@ -0,0 +1,101 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <deque> | ||
| 7 | #include <limits> | ||
| 8 | #include <mutex> | ||
| 9 | #include <optional> | ||
| 10 | #include <unordered_map> | ||
| 11 | #include <vector> | ||
| 12 | |||
| 13 | #include "common/common_types.h" | ||
| 14 | |||
| 15 | namespace Tegra { | ||
| 16 | |||
| 17 | namespace Engines { | ||
| 18 | class Maxwell3D; | ||
| 19 | class KeplerCompute; | ||
| 20 | } // namespace Engines | ||
| 21 | |||
| 22 | class MemoryManager; | ||
| 23 | |||
| 24 | namespace Control { | ||
| 25 | struct ChannelState; | ||
| 26 | } | ||
| 27 | |||
| 28 | } // namespace Tegra | ||
| 29 | |||
| 30 | namespace VideoCommon { | ||
| 31 | |||
| 32 | class ChannelInfo { | ||
| 33 | public: | ||
| 34 | ChannelInfo() = delete; | ||
| 35 | explicit ChannelInfo(Tegra::Control::ChannelState& state); | ||
| 36 | ChannelInfo(const ChannelInfo& state) = delete; | ||
| 37 | ChannelInfo& operator=(const ChannelInfo&) = delete; | ||
| 38 | ChannelInfo(ChannelInfo&& other) = default; | ||
| 39 | ChannelInfo& operator=(ChannelInfo&& other) = default; | ||
| 40 | |||
| 41 | Tegra::Engines::Maxwell3D& maxwell3d; | ||
| 42 | Tegra::Engines::KeplerCompute& kepler_compute; | ||
| 43 | Tegra::MemoryManager& gpu_memory; | ||
| 44 | }; | ||
| 45 | |||
| 46 | template <class P> | ||
| 47 | class ChannelSetupCaches { | ||
| 48 | public: | ||
| 49 | /// Operations for seting the channel of execution. | ||
| 50 | virtual ~ChannelSetupCaches(); | ||
| 51 | |||
| 52 | /// Create channel state. | ||
| 53 | virtual void CreateChannel(Tegra::Control::ChannelState& channel); | ||
| 54 | |||
| 55 | /// Bind a channel for execution. | ||
| 56 | void BindToChannel(s32 id); | ||
| 57 | |||
| 58 | /// Erase channel's state. | ||
| 59 | void EraseChannel(s32 id); | ||
| 60 | |||
| 61 | Tegra::MemoryManager* GetFromID(size_t id) const { | ||
| 62 | std::unique_lock<std::mutex> lk(config_mutex); | ||
| 63 | const auto ref = address_spaces.find(id); | ||
| 64 | return ref->second.gpu_memory; | ||
| 65 | } | ||
| 66 | |||
| 67 | std::optional<size_t> getStorageID(size_t id) const { | ||
| 68 | std::unique_lock<std::mutex> lk(config_mutex); | ||
| 69 | const auto ref = address_spaces.find(id); | ||
| 70 | if (ref == address_spaces.end()) { | ||
| 71 | return std::nullopt; | ||
| 72 | } | ||
| 73 | return ref->second.storage_id; | ||
| 74 | } | ||
| 75 | |||
| 76 | protected: | ||
| 77 | static constexpr size_t UNSET_CHANNEL{std::numeric_limits<size_t>::max()}; | ||
| 78 | |||
| 79 | P* channel_state; | ||
| 80 | size_t current_channel_id{UNSET_CHANNEL}; | ||
| 81 | size_t current_address_space{}; | ||
| 82 | Tegra::Engines::Maxwell3D* maxwell3d; | ||
| 83 | Tegra::Engines::KeplerCompute* kepler_compute; | ||
| 84 | Tegra::MemoryManager* gpu_memory; | ||
| 85 | |||
| 86 | std::deque<P> channel_storage; | ||
| 87 | std::deque<size_t> free_channel_ids; | ||
| 88 | std::unordered_map<s32, size_t> channel_map; | ||
| 89 | std::vector<size_t> active_channel_ids; | ||
| 90 | struct AddresSpaceRef { | ||
| 91 | size_t ref_count; | ||
| 92 | size_t storage_id; | ||
| 93 | Tegra::MemoryManager* gpu_memory; | ||
| 94 | }; | ||
| 95 | std::unordered_map<size_t, AddresSpaceRef> address_spaces; | ||
| 96 | mutable std::mutex config_mutex; | ||
| 97 | |||
| 98 | virtual void OnGPUASRegister([[maybe_unused]] size_t map_id) {} | ||
| 99 | }; | ||
| 100 | |||
| 101 | } // namespace VideoCommon | ||
diff --git a/src/video_core/control/channel_state_cache.inc b/src/video_core/control/channel_state_cache.inc new file mode 100644 index 000000000..460313893 --- /dev/null +++ b/src/video_core/control/channel_state_cache.inc | |||
| @@ -0,0 +1,86 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include <algorithm> | ||
| 5 | |||
| 6 | #include "video_core/control/channel_state.h" | ||
| 7 | #include "video_core/control/channel_state_cache.h" | ||
| 8 | #include "video_core/engines/kepler_compute.h" | ||
| 9 | #include "video_core/engines/maxwell_3d.h" | ||
| 10 | #include "video_core/memory_manager.h" | ||
| 11 | |||
| 12 | namespace VideoCommon { | ||
| 13 | |||
| 14 | template <class P> | ||
| 15 | ChannelSetupCaches<P>::~ChannelSetupCaches() = default; | ||
| 16 | |||
| 17 | template <class P> | ||
| 18 | void ChannelSetupCaches<P>::CreateChannel(struct Tegra::Control::ChannelState& channel) { | ||
| 19 | std::unique_lock<std::mutex> lk(config_mutex); | ||
| 20 | ASSERT(channel_map.find(channel.bind_id) == channel_map.end() && channel.bind_id >= 0); | ||
| 21 | auto new_id = [this, &channel]() { | ||
| 22 | if (!free_channel_ids.empty()) { | ||
| 23 | auto id = free_channel_ids.front(); | ||
| 24 | free_channel_ids.pop_front(); | ||
| 25 | new (&channel_storage[id]) P(channel); | ||
| 26 | return id; | ||
| 27 | } | ||
| 28 | channel_storage.emplace_back(channel); | ||
| 29 | return channel_storage.size() - 1; | ||
| 30 | }(); | ||
| 31 | channel_map.emplace(channel.bind_id, new_id); | ||
| 32 | if (current_channel_id != UNSET_CHANNEL) { | ||
| 33 | channel_state = &channel_storage[current_channel_id]; | ||
| 34 | } | ||
| 35 | active_channel_ids.push_back(new_id); | ||
| 36 | auto as_it = address_spaces.find(channel.memory_manager->GetID()); | ||
| 37 | if (as_it != address_spaces.end()) { | ||
| 38 | as_it->second.ref_count++; | ||
| 39 | return; | ||
| 40 | } | ||
| 41 | AddresSpaceRef new_gpu_mem_ref{ | ||
| 42 | .ref_count = 1, | ||
| 43 | .storage_id = address_spaces.size(), | ||
| 44 | .gpu_memory = channel.memory_manager.get(), | ||
| 45 | }; | ||
| 46 | address_spaces.emplace(channel.memory_manager->GetID(), new_gpu_mem_ref); | ||
| 47 | OnGPUASRegister(channel.memory_manager->GetID()); | ||
| 48 | } | ||
| 49 | |||
| 50 | /// Bind a channel for execution. | ||
| 51 | template <class P> | ||
| 52 | void ChannelSetupCaches<P>::BindToChannel(s32 id) { | ||
| 53 | std::unique_lock<std::mutex> lk(config_mutex); | ||
| 54 | auto it = channel_map.find(id); | ||
| 55 | ASSERT(it != channel_map.end() && id >= 0); | ||
| 56 | current_channel_id = it->second; | ||
| 57 | channel_state = &channel_storage[current_channel_id]; | ||
| 58 | maxwell3d = &channel_state->maxwell3d; | ||
| 59 | kepler_compute = &channel_state->kepler_compute; | ||
| 60 | gpu_memory = &channel_state->gpu_memory; | ||
| 61 | current_address_space = gpu_memory->GetID(); | ||
| 62 | } | ||
| 63 | |||
| 64 | /// Erase channel's channel_state. | ||
| 65 | template <class P> | ||
| 66 | void ChannelSetupCaches<P>::EraseChannel(s32 id) { | ||
| 67 | std::unique_lock<std::mutex> lk(config_mutex); | ||
| 68 | const auto it = channel_map.find(id); | ||
| 69 | ASSERT(it != channel_map.end() && id >= 0); | ||
| 70 | const auto this_id = it->second; | ||
| 71 | free_channel_ids.push_back(this_id); | ||
| 72 | channel_map.erase(it); | ||
| 73 | if (this_id == current_channel_id) { | ||
| 74 | current_channel_id = UNSET_CHANNEL; | ||
| 75 | channel_state = nullptr; | ||
| 76 | maxwell3d = nullptr; | ||
| 77 | kepler_compute = nullptr; | ||
| 78 | gpu_memory = nullptr; | ||
| 79 | } else if (current_channel_id != UNSET_CHANNEL) { | ||
| 80 | channel_state = &channel_storage[current_channel_id]; | ||
| 81 | } | ||
| 82 | active_channel_ids.erase( | ||
| 83 | std::find(active_channel_ids.begin(), active_channel_ids.end(), this_id)); | ||
| 84 | } | ||
| 85 | |||
| 86 | } // namespace VideoCommon | ||
diff --git a/src/video_core/control/scheduler.cpp b/src/video_core/control/scheduler.cpp new file mode 100644 index 000000000..f7cbe204e --- /dev/null +++ b/src/video_core/control/scheduler.cpp | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include <memory> | ||
| 5 | |||
| 6 | #include "common/assert.h" | ||
| 7 | #include "video_core/control/channel_state.h" | ||
| 8 | #include "video_core/control/scheduler.h" | ||
| 9 | #include "video_core/gpu.h" | ||
| 10 | |||
| 11 | namespace Tegra::Control { | ||
| 12 | Scheduler::Scheduler(GPU& gpu_) : gpu{gpu_} {} | ||
| 13 | |||
| 14 | Scheduler::~Scheduler() = default; | ||
| 15 | |||
| 16 | void Scheduler::Push(s32 channel, CommandList&& entries) { | ||
| 17 | std::unique_lock lk(scheduling_guard); | ||
| 18 | auto it = channels.find(channel); | ||
| 19 | ASSERT(it != channels.end()); | ||
| 20 | auto channel_state = it->second; | ||
| 21 | gpu.BindChannel(channel_state->bind_id); | ||
| 22 | channel_state->dma_pusher->Push(std::move(entries)); | ||
| 23 | channel_state->dma_pusher->DispatchCalls(); | ||
| 24 | } | ||
| 25 | |||
| 26 | void Scheduler::DeclareChannel(std::shared_ptr<ChannelState> new_channel) { | ||
| 27 | s32 channel = new_channel->bind_id; | ||
| 28 | std::unique_lock lk(scheduling_guard); | ||
| 29 | channels.emplace(channel, new_channel); | ||
| 30 | } | ||
| 31 | |||
| 32 | } // namespace Tegra::Control | ||
diff --git a/src/video_core/control/scheduler.h b/src/video_core/control/scheduler.h new file mode 100644 index 000000000..44addf61c --- /dev/null +++ b/src/video_core/control/scheduler.h | |||
| @@ -0,0 +1,37 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <memory> | ||
| 7 | #include <mutex> | ||
| 8 | #include <unordered_map> | ||
| 9 | |||
| 10 | #include "video_core/dma_pusher.h" | ||
| 11 | |||
| 12 | namespace Tegra { | ||
| 13 | |||
| 14 | class GPU; | ||
| 15 | |||
| 16 | namespace Control { | ||
| 17 | |||
| 18 | struct ChannelState; | ||
| 19 | |||
| 20 | class Scheduler { | ||
| 21 | public: | ||
| 22 | explicit Scheduler(GPU& gpu_); | ||
| 23 | ~Scheduler(); | ||
| 24 | |||
| 25 | void Push(s32 channel, CommandList&& entries); | ||
| 26 | |||
| 27 | void DeclareChannel(std::shared_ptr<ChannelState> new_channel); | ||
| 28 | |||
| 29 | private: | ||
| 30 | std::unordered_map<s32, std::shared_ptr<ChannelState>> channels; | ||
| 31 | std::mutex scheduling_guard; | ||
| 32 | GPU& gpu; | ||
| 33 | }; | ||
| 34 | |||
| 35 | } // namespace Control | ||
| 36 | |||
| 37 | } // namespace Tegra | ||