mirror of
https://github.com/yuzu-emu/yuzu-android.git
synced 2025-06-17 15:07:58 -05:00
VideoCore: implement channels on gpu caches.
This commit is contained in:
44
src/video_core/control/channel_state.cpp
Normal file
44
src/video_core/control/channel_state.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
// Copyright 2021 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "video_core/control/channel_state.h"
|
||||
#include "video_core/dma_pusher.h"
|
||||
#include "video_core/engines/fermi_2d.h"
|
||||
#include "video_core/engines/kepler_compute.h"
|
||||
#include "video_core/engines/kepler_memory.h"
|
||||
#include "video_core/engines/maxwell_3d.h"
|
||||
#include "video_core/engines/maxwell_dma.h"
|
||||
#include "video_core/engines/puller.h"
|
||||
#include "video_core/memory_manager.h"
|
||||
|
||||
namespace Tegra::Control {
|
||||
|
||||
ChannelState::ChannelState(s32 bind_id_) {
|
||||
bind_id = bind_id_;
|
||||
initiated = false;
|
||||
}
|
||||
|
||||
void ChannelState::Init(Core::System& system, GPU& gpu) {
|
||||
ASSERT(memory_manager);
|
||||
dma_pusher = std::make_unique<Tegra::DmaPusher>(system, gpu, *memory_manager, *this);
|
||||
maxwell_3d = std::make_unique<Engines::Maxwell3D>(system, *memory_manager);
|
||||
fermi_2d = std::make_unique<Engines::Fermi2D>();
|
||||
kepler_compute = std::make_unique<Engines::KeplerCompute>(system, *memory_manager);
|
||||
maxwell_dma = std::make_unique<Engines::MaxwellDMA>(system, *memory_manager);
|
||||
kepler_memory = std::make_unique<Engines::KeplerMemory>(system, *memory_manager);
|
||||
initiated = true;
|
||||
}
|
||||
|
||||
void ChannelState::BindRasterizer(VideoCore::RasterizerInterface* rasterizer) {
|
||||
dma_pusher->BindRasterizer(rasterizer);
|
||||
memory_manager->BindRasterizer(rasterizer);
|
||||
maxwell_3d->BindRasterizer(rasterizer);
|
||||
fermi_2d->BindRasterizer(rasterizer);
|
||||
kepler_memory->BindRasterizer(rasterizer);
|
||||
kepler_compute->BindRasterizer(rasterizer);
|
||||
maxwell_dma->BindRasterizer(rasterizer);
|
||||
}
|
||||
|
||||
} // namespace Tegra::Control
|
69
src/video_core/control/channel_state.h
Normal file
69
src/video_core/control/channel_state.h
Normal file
@ -0,0 +1,69 @@
|
||||
// Copyright 2021 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace VideoCore {
|
||||
class RasterizerInterface;
|
||||
}
|
||||
|
||||
namespace Tegra {
|
||||
|
||||
class GPU;
|
||||
|
||||
namespace Engines {
|
||||
class Puller;
|
||||
class Fermi2D;
|
||||
class Maxwell3D;
|
||||
class MaxwellDMA;
|
||||
class KeplerCompute;
|
||||
class KeplerMemory;
|
||||
} // namespace Engines
|
||||
|
||||
class MemoryManager;
|
||||
class DmaPusher;
|
||||
|
||||
namespace Control {
|
||||
|
||||
struct ChannelState {
|
||||
ChannelState(s32 bind_id);
|
||||
ChannelState(const ChannelState& state) = delete;
|
||||
ChannelState& operator=(const ChannelState&) = delete;
|
||||
ChannelState(ChannelState&& other) noexcept = default;
|
||||
ChannelState& operator=(ChannelState&& other) noexcept = default;
|
||||
|
||||
void Init(Core::System& system, GPU& gpu);
|
||||
|
||||
void BindRasterizer(VideoCore::RasterizerInterface* rasterizer);
|
||||
|
||||
s32 bind_id = -1;
|
||||
/// 3D engine
|
||||
std::unique_ptr<Engines::Maxwell3D> maxwell_3d;
|
||||
/// 2D engine
|
||||
std::unique_ptr<Engines::Fermi2D> fermi_2d;
|
||||
/// Compute engine
|
||||
std::unique_ptr<Engines::KeplerCompute> kepler_compute;
|
||||
/// DMA engine
|
||||
std::unique_ptr<Engines::MaxwellDMA> maxwell_dma;
|
||||
/// Inline memory engine
|
||||
std::unique_ptr<Engines::KeplerMemory> kepler_memory;
|
||||
|
||||
std::shared_ptr<MemoryManager> memory_manager;
|
||||
|
||||
std::unique_ptr<DmaPusher> dma_pusher;
|
||||
|
||||
bool initiated{};
|
||||
};
|
||||
|
||||
} // namespace Control
|
||||
|
||||
} // namespace Tegra
|
5
src/video_core/control/channel_state_cache.cpp
Normal file
5
src/video_core/control/channel_state_cache.cpp
Normal file
@ -0,0 +1,5 @@
|
||||
#include "video_core/control/channel_state_cache.inc"
|
||||
|
||||
namespace VideoCommon {
|
||||
template class VideoCommon::ChannelSetupCaches<VideoCommon::ChannelInfo>;
|
||||
}
|
68
src/video_core/control/channel_state_cache.h
Normal file
68
src/video_core/control/channel_state_cache.h
Normal file
@ -0,0 +1,68 @@
|
||||
#pragma once
|
||||
|
||||
#include <deque>
|
||||
#include <limits>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Tegra {
|
||||
|
||||
namespace Engines {
|
||||
class Maxwell3D;
|
||||
class KeplerCompute;
|
||||
} // namespace Engines
|
||||
|
||||
class MemoryManager;
|
||||
|
||||
namespace Control {
|
||||
struct ChannelState;
|
||||
}
|
||||
|
||||
} // namespace Tegra
|
||||
|
||||
namespace VideoCommon {
|
||||
|
||||
class ChannelInfo {
|
||||
public:
|
||||
ChannelInfo() = delete;
|
||||
ChannelInfo(Tegra::Control::ChannelState& state);
|
||||
ChannelInfo(const ChannelInfo& state) = delete;
|
||||
ChannelInfo& operator=(const ChannelInfo&) = delete;
|
||||
ChannelInfo(ChannelInfo&& other) = default;
|
||||
ChannelInfo& operator=(ChannelInfo&& other) = default;
|
||||
|
||||
Tegra::Engines::Maxwell3D& maxwell3d;
|
||||
Tegra::Engines::KeplerCompute& kepler_compute;
|
||||
Tegra::MemoryManager& gpu_memory;
|
||||
};
|
||||
|
||||
template <class P>
|
||||
class ChannelSetupCaches {
|
||||
public:
|
||||
/// Operations for seting the channel of execution.
|
||||
|
||||
/// Create channel state.
|
||||
void CreateChannel(Tegra::Control::ChannelState& channel);
|
||||
|
||||
/// Bind a channel for execution.
|
||||
void BindToChannel(s32 id);
|
||||
|
||||
/// Erase channel's state.
|
||||
void EraseChannel(s32 id);
|
||||
|
||||
protected:
|
||||
static constexpr size_t UNSET_CHANNEL{std::numeric_limits<size_t>::max()};
|
||||
|
||||
std::deque<P> channel_storage;
|
||||
std::deque<size_t> free_channel_ids;
|
||||
std::unordered_map<s32, size_t> channel_map;
|
||||
|
||||
P* channel_state;
|
||||
size_t current_channel_id{UNSET_CHANNEL};
|
||||
Tegra::Engines::Maxwell3D* maxwell3d;
|
||||
Tegra::Engines::KeplerCompute* kepler_compute;
|
||||
Tegra::MemoryManager* gpu_memory;
|
||||
};
|
||||
|
||||
} // namespace VideoCommon
|
64
src/video_core/control/channel_state_cache.inc
Normal file
64
src/video_core/control/channel_state_cache.inc
Normal file
@ -0,0 +1,64 @@
|
||||
#include "video_core/control/channel_state.h"
|
||||
#include "video_core/control/channel_state_cache.h"
|
||||
#include "video_core/engines/kepler_compute.h"
|
||||
#include "video_core/engines/maxwell_3d.h"
|
||||
#include "video_core/memory_manager.h"
|
||||
|
||||
namespace VideoCommon {
|
||||
|
||||
ChannelInfo::ChannelInfo(Tegra::Control::ChannelState& channel_state)
|
||||
: maxwell3d{*channel_state.maxwell_3d}, kepler_compute{*channel_state.kepler_compute},
|
||||
gpu_memory{*channel_state.memory_manager} {}
|
||||
|
||||
template <class P>
|
||||
void ChannelSetupCaches<P>::CreateChannel(struct Tegra::Control::ChannelState& channel) {
|
||||
ASSERT(channel_map.find(channel.bind_id) == channel_map.end() && channel.bind_id >= 0);
|
||||
auto new_id = [this, &channel]() {
|
||||
if (!free_channel_ids.empty()) {
|
||||
auto id = free_channel_ids.front();
|
||||
free_channel_ids.pop_front();
|
||||
new (&channel_storage[id]) ChannelInfo(channel);
|
||||
return id;
|
||||
}
|
||||
channel_storage.emplace_back(channel);
|
||||
return channel_storage.size() - 1;
|
||||
}();
|
||||
channel_map.emplace(channel.bind_id, new_id);
|
||||
if (current_channel_id != UNSET_CHANNEL) {
|
||||
channel_state = &channel_storage[current_channel_id];
|
||||
}
|
||||
}
|
||||
|
||||
/// Bind a channel for execution.
|
||||
template <class P>
|
||||
void ChannelSetupCaches<P>::BindToChannel(s32 id) {
|
||||
auto it = channel_map.find(id);
|
||||
ASSERT(it != channel_map.end() && id >= 0);
|
||||
current_channel_id = it->second;
|
||||
channel_state = &channel_storage[current_channel_id];
|
||||
maxwell3d = &channel_state->maxwell3d;
|
||||
kepler_compute = &channel_state->kepler_compute;
|
||||
gpu_memory = &channel_state->gpu_memory;
|
||||
}
|
||||
|
||||
/// Erase channel's channel_state.
|
||||
template <class P>
|
||||
void ChannelSetupCaches<P>::EraseChannel(s32 id) {
|
||||
const auto it = channel_map.find(id);
|
||||
ASSERT(it != channel_map.end() && id >= 0);
|
||||
const auto this_id = it->second;
|
||||
free_channel_ids.push_back(this_id);
|
||||
channel_map.erase(it);
|
||||
if (this_id == current_channel_id) {
|
||||
current_channel_id = UNSET_CHANNEL;
|
||||
channel_state = nullptr;
|
||||
maxwell3d = nullptr;
|
||||
kepler_compute = nullptr;
|
||||
gpu_memory = nullptr;
|
||||
} else if (current_channel_id != UNSET_CHANNEL) {
|
||||
channel_state = &channel_storage[current_channel_id];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace VideoCommon
|
31
src/video_core/control/scheduler.cpp
Normal file
31
src/video_core/control/scheduler.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright 2021 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "video_core/control/channel_state.h"
|
||||
#include "video_core/control/scheduler.h"
|
||||
#include "video_core/gpu.h"
|
||||
|
||||
namespace Tegra::Control {
|
||||
Scheduler::Scheduler(GPU& gpu_) : gpu{gpu_} {}
|
||||
|
||||
Scheduler::~Scheduler() = default;
|
||||
|
||||
void Scheduler::Push(s32 channel, CommandList&& entries) {
|
||||
std::unique_lock<std::mutex> lk(scheduling_guard);
|
||||
auto it = channels.find(channel);
|
||||
auto channel_state = it->second;
|
||||
gpu.BindChannel(channel_state->bind_id);
|
||||
channel_state->dma_pusher->Push(std::move(entries));
|
||||
channel_state->dma_pusher->DispatchCalls();
|
||||
}
|
||||
|
||||
void Scheduler::DeclareChannel(std::shared_ptr<ChannelState> new_channel) {
|
||||
s32 channel = new_channel->bind_id;
|
||||
std::unique_lock<std::mutex> lk(scheduling_guard);
|
||||
channels.emplace(channel, new_channel);
|
||||
}
|
||||
|
||||
} // namespace Tegra::Control
|
38
src/video_core/control/scheduler.h
Normal file
38
src/video_core/control/scheduler.h
Normal file
@ -0,0 +1,38 @@
|
||||
// Copyright 2021 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "video_core/dma_pusher.h"
|
||||
|
||||
namespace Tegra {
|
||||
|
||||
class GPU;
|
||||
|
||||
namespace Control {
|
||||
|
||||
struct ChannelState;
|
||||
|
||||
class Scheduler {
|
||||
public:
|
||||
Scheduler(GPU& gpu_);
|
||||
~Scheduler();
|
||||
|
||||
void Push(s32 channel, CommandList&& entries);
|
||||
|
||||
void DeclareChannel(std::shared_ptr<ChannelState> new_channel);
|
||||
|
||||
private:
|
||||
std::unordered_map<s32, std::shared_ptr<ChannelState>> channels;
|
||||
std::mutex scheduling_guard;
|
||||
GPU& gpu;
|
||||
};
|
||||
|
||||
} // namespace Control
|
||||
|
||||
} // namespace Tegra
|
Reference in New Issue
Block a user