1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#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/macro.h"
#include "video_core/memory_manager.h"
#include "video_core/nx2.h"
namespace Tegra::Control {
namespace {
// Match NVK/Nouveau's initial pushbuffer subchannel layout.
constexpr u32 Nvk3DSubchannel = 0;
constexpr u32 NvkComputeSubchannel = 1;
constexpr u32 NvkM2mfSubchannel = 2;
constexpr u32 Nvk2DSubchannel = 3;
constexpr u32 NvkCopySubchannel = 4;
// Switch 2 channels of a process share one TSG, whose graphics context holds the macro RAM.
std::shared_ptr<NativeMacroContext> Nx2MacroContext() {
static const auto context = [] {
auto created = std::make_shared<NativeMacroContext>();
created->engine.native_turing = true;
created->compute_engine.native_turing = true;
return created;
}();
return context;
}
void BindNvkDefaultSubchannels(ChannelState::Payload& payload) {
auto& dma_pusher = payload.dma_pusher;
dma_pusher.BindSubchannel(&payload.maxwell_3d, Nvk3DSubchannel, Engines::EngineTypes::Maxwell3D);
dma_pusher.BindSubchannel(&payload.kepler_compute, NvkComputeSubchannel,
Engines::EngineTypes::KeplerCompute);
// Subchannel 2 is M2MF/inline-to-memory there (NVN uses it without binding a class);
// KeplerMemory has the same LINE_LENGTH_IN/OFFSET_OUT/LAUNCH_DMA/LOAD_INLINE_DATA layout.
dma_pusher.BindSubchannel(&payload.kepler_memory, NvkM2mfSubchannel,
Engines::EngineTypes::KeplerMemory);
dma_pusher.BindSubchannel(&payload.fermi_2d, Nvk2DSubchannel, Engines::EngineTypes::Fermi2D);
dma_pusher.BindSubchannel(&payload.maxwell_dma, NvkCopySubchannel,
Engines::EngineTypes::MaxwellDMA);
}
} // Anonymous namespace
ChannelState::Payload::Payload(Core::System& system, MemoryManager& memory_manager, ChannelState& channel_state)
: maxwell_3d(memory_manager)
, fermi_2d(memory_manager)
, kepler_compute(memory_manager)
, maxwell_dma(memory_manager)
, kepler_memory(memory_manager)
, nv01_timer(memory_manager)
, dma_pusher(system, memory_manager, channel_state)
{}
ChannelState::ChannelState(s32 bind_id_)
: bind_id{bind_id_}
{}
void ChannelState::Init(Core::System& system, u64 program_id_) {
ASSERT(memory_manager);
program_id = program_id_;
payload.emplace(system, *memory_manager, *this);
BindNvkDefaultSubchannels(*payload);
if (g_nx2_ampere) {
// Switch 2 command streams use Ampere classes with Turing+ (MME64) macros, and its
// block-linear surfaces the console's GOB swizzle.
memory_manager->EnableNativeTiling();
const auto macros = Nx2MacroContext();
payload->maxwell_3d.SetNativeMacroContext(macros);
payload->maxwell_3d.SetNativeTuringMacroMode(true);
payload->kepler_compute.SetNativeMacroMode(¯os->engine, macros->positions,
macros.get());
payload->kepler_compute.SetNativeDataRam(&payload->maxwell_3d.GetNativeDataRam());
}
initialized = true;
}
void ChannelState::BindRasterizer(VideoCore::RasterizerInterface* rasterizer) {
payload->dma_pusher.BindRasterizer(rasterizer);
memory_manager->BindRasterizer(rasterizer);
payload->maxwell_3d.BindRasterizer(rasterizer);
payload->fermi_2d.BindRasterizer(rasterizer);
payload->kepler_memory.BindRasterizer(rasterizer);
payload->kepler_compute.BindRasterizer(rasterizer);
payload->maxwell_dma.BindRasterizer(rasterizer);
//payload->nv01_timer.BindRasterizer(rasterizer);
}
} // namespace Tegra::Control
|