remove implicit system saved in struct, pass as first param

This commit is contained in:
lizzie 2026-05-01 00:45:45 +00:00
parent b64ebc71f7
commit d5a06a4889
18 changed files with 117 additions and 117 deletions

View file

@ -29,7 +29,7 @@ void CpuManager::Initialize() {
for (std::size_t core = 0; core < num_cores; core++) for (std::size_t core = 0; core < num_cores; core++)
core_data[core].host_thread = std::jthread([this, core](std::stop_token token) { core_data[core].host_thread = std::jthread([this, core](std::stop_token token) {
RunThread(token, core); RunThread(token, core);
}, core); });
} }
void CpuManager::Shutdown() { void CpuManager::Shutdown() {

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2022 yuzu Emulator Project // SPDX-FileCopyrightText: 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2021 yuzu Emulator Project // SPDX-FileCopyrightText: 2021 yuzu Emulator Project

View file

@ -176,8 +176,10 @@ void DmaPusher::CallMethod(u32 argument) {
}); });
} else { } else {
auto subchannel = subchannels[dma_state.subchannel]; auto subchannel = subchannels[dma_state.subchannel];
if (subchannel->execution_mask[dma_state.method]) { if (!subchannel->execution_mask[dma_state.method]) {
subchannel->ConsumeSink(); subchannel->method_sink.emplace_back(dma_state.method, argument);
} else {
subchannel->ConsumeSink(system);
subchannel->current_dma_segment = dma_state.dma_get + dma_state.dma_word_offset; subchannel->current_dma_segment = dma_state.dma_get + dma_state.dma_word_offset;
subchannel->CallMethod(dma_state.method, argument, dma_state.is_last_call); subchannel->CallMethod(dma_state.method, argument, dma_state.is_last_call);
} else { } else {
@ -191,7 +193,7 @@ void DmaPusher::CallMultiMethod(const u32* base_start, u32 num_methods) {
puller.CallMultiMethod(*this, dma_state.method, dma_state.subchannel, base_start, num_methods, dma_state.method_count); puller.CallMultiMethod(*this, dma_state.method, dma_state.subchannel, base_start, num_methods, dma_state.method_count);
} else { } else {
auto subchannel = subchannels[dma_state.subchannel]; auto subchannel = subchannels[dma_state.subchannel];
subchannel->ConsumeSink(); subchannel->ConsumeSink(system);
subchannel->current_dma_segment = dma_state.dma_get + dma_state.dma_word_offset; subchannel->current_dma_segment = dma_state.dma_get + dma_state.dma_word_offset;
subchannel->CallMultiMethod(dma_state.method, base_start, num_methods, dma_state.method_count); subchannel->CallMultiMethod(dma_state.method, base_start, num_methods, dma_state.method_count);
} }

View file

@ -12,6 +12,10 @@
#include "common/common_types.h" #include "common/common_types.h"
namespace Core {
class System;
}
namespace Tegra::Engines { namespace Tegra::Engines {
enum class EngineTypes : u32 { enum class EngineTypes : u32 {
@ -28,28 +32,25 @@ public:
virtual ~EngineInterface() = default; virtual ~EngineInterface() = default;
/// Write the value to the register identified by method. /// Write the value to the register identified by method.
virtual void CallMethod(u32 method, u32 method_argument, bool is_last_call) = 0; virtual void CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) = 0;
/// Write multiple values to the register identified by method. /// Write multiple values to the register identified by method.
virtual void CallMultiMethod(u32 method, const u32* base_start, u32 amount, virtual void CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) = 0;
u32 methods_pending) = 0;
void ConsumeSink() { void ConsumeSink(Core::System& system) {
if (method_sink.empty()) { if (!method_sink.empty()) {
return; ConsumeSinkImpl(system);
} }
ConsumeSinkImpl();
} }
std::bitset<(std::numeric_limits<u16>::max)()> execution_mask{}; std::bitset<(std::numeric_limits<u16>::max)()> execution_mask{};
std::vector<std::pair<u32, u32>> method_sink{}; std::vector<std::pair<u32, u32>> method_sink{};
bool current_dirty{};
GPUVAddr current_dma_segment; GPUVAddr current_dma_segment;
bool current_dirty{};
protected: protected:
virtual void ConsumeSinkImpl() { virtual void ConsumeSinkImpl(Core::System& system) {
for (auto [method, value] : method_sink) { for (auto [method, value] : method_sink) {
CallMethod(method, value, true); CallMethod(system, method, value, true);
} }
method_sink.clear(); method_sink.clear();
} }

View file

@ -36,9 +36,8 @@ void Fermi2D::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) {
rasterizer = rasterizer_; rasterizer = rasterizer_;
} }
void Fermi2D::CallMethod(u32 method, u32 method_argument, bool is_last_call) { void Fermi2D::CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) {
ASSERT_MSG(method < Regs::NUM_REGS, ASSERT_MSG(method < Regs::NUM_REGS, "Invalid Fermi2D register, increase the size of the Regs structure");
"Invalid Fermi2D register, increase the size of the Regs structure");
regs.reg_array[method] = method_argument; regs.reg_array[method] = method_argument;
if (method == FERMI2D_REG_INDEX(pixels_from_memory.src_y0) + 1) { if (method == FERMI2D_REG_INDEX(pixels_from_memory.src_y0) + 1) {
@ -46,13 +45,13 @@ void Fermi2D::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
} }
} }
void Fermi2D::CallMultiMethod(u32 method, const u32* base_start, u32 amount, u32 methods_pending) { void Fermi2D::CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) {
for (u32 i = 0; i < amount; ++i) { for (u32 i = 0; i < amount; ++i) {
CallMethod(method, base_start[i], methods_pending - i <= 1); CallMethod(system, method, base_start[i], methods_pending - i <= 1);
} }
} }
void Fermi2D::ConsumeSinkImpl() { void Fermi2D::ConsumeSinkImpl(Core::System& system) {
for (auto [method, value] : method_sink) { for (auto [method, value] : method_sink) {
regs.reg_array[method] = value; regs.reg_array[method] = value;
} }
@ -60,8 +59,7 @@ void Fermi2D::ConsumeSinkImpl() {
} }
void Fermi2D::Blit() { void Fermi2D::Blit() {
LOG_DEBUG(HW_GPU, "called. source address=0x{:x}, destination address=0x{:x}", LOG_DEBUG(HW_GPU, "called. source address=0x{:x}, destination address=0x{:x}", regs.src.Address(), regs.dst.Address());
regs.src.Address(), regs.dst.Address());
UNIMPLEMENTED_IF_MSG(regs.operation != Operation::SrcCopy, "Operation is not copy"); UNIMPLEMENTED_IF_MSG(regs.operation != Operation::SrcCopy, "Operation is not copy");
UNIMPLEMENTED_IF_MSG(regs.src.layer != 0, "Source layer is not zero"); UNIMPLEMENTED_IF_MSG(regs.src.layer != 0, "Source layer is not zero");

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@ -44,11 +47,10 @@ public:
void BindRasterizer(VideoCore::RasterizerInterface* rasterizer); void BindRasterizer(VideoCore::RasterizerInterface* rasterizer);
/// Write the value to the register identified by method. /// Write the value to the register identified by method.
void CallMethod(u32 method, u32 method_argument, bool is_last_call) override; void CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) override;
/// Write multiple values to the register identified by method. /// Write multiple values to the register identified by method.
void CallMultiMethod(u32 method, const u32* base_start, u32 amount, void CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) override;
u32 methods_pending) override;
enum class Origin : u32 { enum class Origin : u32 {
Center = 0, Center = 0,
@ -311,7 +313,7 @@ private:
/// registers. /// registers.
void Blit(); void Blit();
void ConsumeSinkImpl() override; void ConsumeSinkImpl(Core::System& system) override;
}; };
#define ASSERT_REG_POSITION(field_name, position) \ #define ASSERT_REG_POSITION(field_name, position) \

View file

@ -16,8 +16,10 @@
namespace Tegra::Engines { namespace Tegra::Engines {
KeplerCompute::KeplerCompute(Core::System& system_, MemoryManager& memory_manager_) KeplerCompute::KeplerCompute(MemoryManager& memory_manager_)
: system{system_}, memory_manager{memory_manager_}, upload_state{memory_manager, regs.upload} { : memory_manager{memory_manager_}
, upload_state{memory_manager, regs.upload}
{
execution_mask.reset(); execution_mask.reset();
execution_mask[KEPLER_COMPUTE_REG_INDEX(exec_upload)] = true; execution_mask[KEPLER_COMPUTE_REG_INDEX(exec_upload)] = true;
execution_mask[KEPLER_COMPUTE_REG_INDEX(data_upload)] = true; execution_mask[KEPLER_COMPUTE_REG_INDEX(data_upload)] = true;
@ -31,16 +33,15 @@ void KeplerCompute::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_)
upload_state.BindRasterizer(rasterizer); upload_state.BindRasterizer(rasterizer);
} }
void KeplerCompute::ConsumeSinkImpl() { void KeplerCompute::ConsumeSinkImpl(Core::System& system) {
for (auto [method, value] : method_sink) { for (auto [method, value] : method_sink) {
regs.reg_array[method] = value; regs.reg_array[method] = value;
} }
method_sink.clear(); method_sink.clear();
} }
void KeplerCompute::CallMethod(u32 method, u32 method_argument, bool is_last_call) { void KeplerCompute::CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) {
ASSERT_MSG(method < Regs::NUM_REGS, ASSERT_MSG(method < Regs::NUM_REGS, "Invalid KeplerCompute register, increase the size of the Regs structure");
"Invalid KeplerCompute register, increase the size of the Regs structure");
regs.reg_array[method] = method_argument; regs.reg_array[method] = method_argument;
@ -78,8 +79,7 @@ void KeplerCompute::CallMethod(u32 method, u32 method_argument, bool is_last_cal
} }
} }
void KeplerCompute::CallMultiMethod(u32 method, const u32* base_start, u32 amount, void KeplerCompute::CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) {
u32 methods_pending) {
switch (method) { switch (method) {
case KEPLER_COMPUTE_REG_INDEX(data_upload): case KEPLER_COMPUTE_REG_INDEX(data_upload):
upload_address = current_dma_segment; upload_address = current_dma_segment;
@ -87,7 +87,7 @@ void KeplerCompute::CallMultiMethod(u32 method, const u32* base_start, u32 amoun
return; return;
default: default:
for (u32 i = 0; i < amount; i++) { for (u32 i = 0; i < amount; i++) {
CallMethod(method, base_start[i], methods_pending - i <= 1); CallMethod(system, method, base_start[i], methods_pending - i <= 1);
} }
break; break;
} }

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@ -42,7 +45,7 @@ namespace Tegra::Engines {
class KeplerCompute final : public EngineInterface { class KeplerCompute final : public EngineInterface {
public: public:
explicit KeplerCompute(Core::System& system, MemoryManager& memory_manager); explicit KeplerCompute(MemoryManager& memory_manager);
~KeplerCompute(); ~KeplerCompute();
/// Binds a rasterizer to this engine. /// Binds a rasterizer to this engine.
@ -199,11 +202,10 @@ public:
"KeplerCompute LaunchParams has wrong size"); "KeplerCompute LaunchParams has wrong size");
/// Write the value to the register identified by method. /// Write the value to the register identified by method.
void CallMethod(u32 method, u32 method_argument, bool is_last_call) override; void CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) override;
/// Write multiple values to the register identified by method. /// Write multiple values to the register identified by method.
void CallMultiMethod(u32 method, const u32* base_start, u32 amount, void CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) override;
u32 methods_pending) override;
std::optional<GPUVAddr> GetIndirectComputeAddress() const { std::optional<GPUVAddr> GetIndirectComputeAddress() const {
return indirect_compute; return indirect_compute;
@ -212,7 +214,7 @@ public:
private: private:
void ProcessLaunch(); void ProcessLaunch();
void ConsumeSinkImpl() override; void ConsumeSinkImpl(Core::System& system) override;
/// Retrieves information about a specific TIC entry from the TIC buffer. /// Retrieves information about a specific TIC entry from the TIC buffer.
Texture::TICEntry GetTICEntry(u32 tic_index) const; Texture::TICEntry GetTICEntry(u32 tic_index) const;
@ -220,7 +222,6 @@ private:
/// Retrieves information about a specific TSC entry from the TSC buffer. /// Retrieves information about a specific TSC entry from the TSC buffer.
Texture::TSCEntry GetTSCEntry(u32 tsc_index) const; Texture::TSCEntry GetTSCEntry(u32 tsc_index) const;
Core::System& system;
MemoryManager& memory_manager; MemoryManager& memory_manager;
VideoCore::RasterizerInterface* rasterizer = nullptr; VideoCore::RasterizerInterface* rasterizer = nullptr;
Upload::State upload_state; Upload::State upload_state;

View file

@ -14,8 +14,9 @@
namespace Tegra::Engines { namespace Tegra::Engines {
KeplerMemory::KeplerMemory(Core::System& system_, MemoryManager& memory_manager) KeplerMemory::KeplerMemory(MemoryManager& memory_manager)
: system{system_}, upload_state{memory_manager, regs.upload} {} : upload_state{memory_manager, regs.upload}
{}
KeplerMemory::~KeplerMemory() = default; KeplerMemory::~KeplerMemory() = default;
@ -27,16 +28,15 @@ void KeplerMemory::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) {
execution_mask[KEPLERMEMORY_REG_INDEX(data)] = true; execution_mask[KEPLERMEMORY_REG_INDEX(data)] = true;
} }
void KeplerMemory::ConsumeSinkImpl() { void KeplerMemory::ConsumeSinkImpl(Core::System& system) {
for (auto [method, value] : method_sink) { for (auto [method, value] : method_sink) {
regs.reg_array[method] = value; regs.reg_array[method] = value;
} }
method_sink.clear(); method_sink.clear();
} }
void KeplerMemory::CallMethod(u32 method, u32 method_argument, bool is_last_call) { void KeplerMemory::CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) {
ASSERT_MSG(method < Regs::NUM_REGS, ASSERT_MSG(method < Regs::NUM_REGS, "Invalid KeplerMemory register, increase the size of the Regs structure");
"Invalid KeplerMemory register, increase the size of the Regs structure");
regs.reg_array[method] = method_argument; regs.reg_array[method] = method_argument;
@ -52,15 +52,14 @@ void KeplerMemory::CallMethod(u32 method, u32 method_argument, bool is_last_call
} }
} }
void KeplerMemory::CallMultiMethod(u32 method, const u32* base_start, u32 amount, void KeplerMemory::CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) {
u32 methods_pending) {
switch (method) { switch (method) {
case KEPLERMEMORY_REG_INDEX(data): case KEPLERMEMORY_REG_INDEX(data):
upload_state.ProcessData(base_start, amount); upload_state.ProcessData(base_start, amount);
return; return;
default: default:
for (u32 i = 0; i < amount; i++) { for (u32 i = 0; i < amount; i++) {
CallMethod(method, base_start[i], methods_pending - i <= 1); CallMethod(system, method, base_start[i], methods_pending - i <= 1);
} }
break; break;
} }

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@ -36,18 +39,17 @@ namespace Tegra::Engines {
class KeplerMemory final : public EngineInterface { class KeplerMemory final : public EngineInterface {
public: public:
explicit KeplerMemory(Core::System& system_, MemoryManager& memory_manager); explicit KeplerMemory(MemoryManager& memory_manager);
~KeplerMemory() override; ~KeplerMemory() override;
/// Binds a rasterizer to this engine. /// Binds a rasterizer to this engine.
void BindRasterizer(VideoCore::RasterizerInterface* rasterizer); void BindRasterizer(VideoCore::RasterizerInterface* rasterizer);
/// Write the value to the register identified by method. /// Write the value to the register identified by method.
void CallMethod(u32 method, u32 method_argument, bool is_last_call) override; void CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) override;
/// Write multiple values to the register identified by method. /// Write multiple values to the register identified by method.
void CallMultiMethod(u32 method, const u32* base_start, u32 amount, void CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) override;
u32 methods_pending) override;
struct Regs { struct Regs {
static constexpr size_t NUM_REGS = 0x7F; static constexpr size_t NUM_REGS = 0x7F;
@ -73,9 +75,7 @@ public:
} regs{}; } regs{};
private: private:
void ConsumeSinkImpl() override; void ConsumeSinkImpl(Core::System& system) override;
Core::System& system;
Upload::State upload_state; Upload::State upload_state;
}; };

View file

@ -25,9 +25,8 @@ namespace Tegra::Engines {
/// First register id that is actually a Macro call. /// First register id that is actually a Macro call.
constexpr u32 MacroRegistersStart = 0xE00; constexpr u32 MacroRegistersStart = 0xE00;
Maxwell3D::Maxwell3D(Core::System& system_, MemoryManager& memory_manager_) Maxwell3D::Maxwell3D(MemoryManager& memory_manager_)
: draw_manager() : draw_manager()
, system{system_}
, memory_manager{memory_manager_} , memory_manager{memory_manager_}
#ifdef ARCHITECTURE_x86_64 #ifdef ARCHITECTURE_x86_64
, macro_engine(bool(Settings::values.disable_macro_jit)) , macro_engine(bool(Settings::values.disable_macro_jit))
@ -201,11 +200,10 @@ bool Maxwell3D::IsMethodExecutable(u32 method) {
} }
} }
void Maxwell3D::ProcessMacro(u32 method, const u32* base_start, u32 amount, bool is_last_call) { void Maxwell3D::ProcessMacro(Core::System& system, u32 method, const u32* base_start, u32 amount, bool is_last_call) {
if (executing_macro == 0) { if (executing_macro == 0) {
// A macro call must begin by writing the macro method's register, not its argument. // A macro call must begin by writing the macro method's register, not its argument.
ASSERT_MSG((method % 2) == 0, ASSERT((method % 2) == 0 && "Can't start macro execution by writing to the ARGS register");
"Can't start macro execution by writing to the ARGS register");
executing_macro = method; executing_macro = method;
} }
@ -219,7 +217,7 @@ void Maxwell3D::ProcessMacro(u32 method, const u32* base_start, u32 amount, bool
// Call the macro when there are no more parameters in the command buffer // Call the macro when there are no more parameters in the command buffer
if (is_last_call) { if (is_last_call) {
ConsumeSink(); ConsumeSink(system);
CallMacroMethod(executing_macro, macro_params); CallMacroMethod(executing_macro, macro_params);
macro_params.clear(); macro_params.clear();
macro_addresses.clear(); macro_addresses.clear();
@ -287,7 +285,7 @@ u32 Maxwell3D::ProcessShadowRam(u32 method, u32 argument) {
return argument; return argument;
} }
void Maxwell3D::ConsumeSinkImpl() { void Maxwell3D::ConsumeSinkImpl(Core::System& system) {
const auto control = shadow_state.shadow_ram_control; const auto control = shadow_state.shadow_ram_control;
if (control == Regs::ShadowRamControl::Track || control == Regs::ShadowRamControl::TrackWithFilter) { if (control == Regs::ShadowRamControl::Track || control == Regs::ShadowRamControl::TrackWithFilter) {
for (auto [method, value] : method_sink) { for (auto [method, value] : method_sink) {
@ -391,7 +389,7 @@ void Maxwell3D::CallMacroMethod(u32 method, const std::vector<u32>& parameters)
draw_manager.DrawDeferred(*this); draw_manager.DrawDeferred(*this);
} }
void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) { void Maxwell3D::CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) {
// It is an error to write to a register other than the current macro's ARG register before // It is an error to write to a register other than the current macro's ARG register before
// it has finished execution. // it has finished execution.
if (executing_macro != 0) { if (executing_macro != 0) {
@ -401,7 +399,7 @@ void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
// Methods after 0xE00 are special, they're actually triggers for some microcode that was // Methods after 0xE00 are special, they're actually triggers for some microcode that was
// uploaded to the GPU during initialization. // uploaded to the GPU during initialization.
if (method >= MacroRegistersStart) { if (method >= MacroRegistersStart) {
ProcessMacro(method, &method_argument, 1, is_last_call); ProcessMacro(system, method, &method_argument, 1, is_last_call);
return; return;
} }
@ -411,12 +409,11 @@ void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
ProcessMethodCall(method, argument, method_argument, is_last_call); ProcessMethodCall(method, argument, method_argument, is_last_call);
} }
void Maxwell3D::CallMultiMethod(u32 method, const u32* base_start, u32 amount, void Maxwell3D::CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) {
u32 methods_pending) {
// Methods after 0xE00 are special, they're actually triggers for some microcode that was // Methods after 0xE00 are special, they're actually triggers for some microcode that was
// uploaded to the GPU during initialization. // uploaded to the GPU during initialization.
if (method >= MacroRegistersStart) { if (method >= MacroRegistersStart) {
ProcessMacro(method, base_start, amount, amount == methods_pending); ProcessMacro(system, method, base_start, amount, amount == methods_pending);
return; return;
} }
switch (method) { switch (method) {
@ -445,7 +442,7 @@ void Maxwell3D::CallMultiMethod(u32 method, const u32* base_start, u32 amount,
} }
default: default:
for (u32 i = 0; i < amount; i++) { for (u32 i = 0; i < amount; i++) {
CallMethod(method, base_start[i], methods_pending - i <= 1); CallMethod(system, method, base_start[i], methods_pending - i <= 1);
} }
break; break;
} }
@ -467,7 +464,7 @@ void Maxwell3D::ProcessFirmwareCall4() {
regs.shadow_scratch[0] = 1; regs.shadow_scratch[0] = 1;
} }
void Maxwell3D::StampQueryResult(u64 payload, bool long_query) { void Maxwell3D::StampQueryResult(Core::System& system, u64 payload, bool long_query) {
const GPUVAddr sequence_address{regs.report_semaphore.Address()}; const GPUVAddr sequence_address{regs.report_semaphore.Address()};
if (long_query) { if (long_query) {
memory_manager.Write<u64>(sequence_address + sizeof(u64), system.GPU().GetTicks()); memory_manager.Write<u64>(sequence_address + sizeof(u64), system.GPU().GetTicks());

View file

@ -55,7 +55,7 @@ namespace Tegra::Engines {
class Maxwell3D final : public EngineInterface { class Maxwell3D final : public EngineInterface {
public: public:
explicit Maxwell3D(Core::System& system, MemoryManager& memory_manager); explicit Maxwell3D(MemoryManager& memory_manager);
~Maxwell3D(); ~Maxwell3D();
/// Binds a rasterizer to this engine. /// Binds a rasterizer to this engine.
@ -3129,11 +3129,10 @@ public:
u32 GetRegisterValue(u32 method) const; u32 GetRegisterValue(u32 method) const;
/// Write the value to the register identified by method. /// Write the value to the register identified by method.
void CallMethod(u32 method, u32 method_argument, bool is_last_call) override; void CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) override;
/// Write multiple values to the register identified by method. /// Write multiple values to the register identified by method.
void CallMultiMethod(u32 method, const u32* base_start, u32 amount, void CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) override;
u32 methods_pending) override;
bool ShouldExecute() const { bool ShouldExecute() const {
return execute_on; return execute_on;
@ -3190,13 +3189,13 @@ public:
private: private:
void InitializeRegisterDefaults(); void InitializeRegisterDefaults();
void ProcessMacro(u32 method, const u32* base_start, u32 amount, bool is_last_call); void ProcessMacro(Core::System& system, u32 method, const u32* base_start, u32 amount, bool is_last_call);
u32 ProcessShadowRam(u32 method, u32 argument); u32 ProcessShadowRam(u32 method, u32 argument);
void ProcessDirtyRegisters(u32 method, u32 argument); void ProcessDirtyRegisters(u32 method, u32 argument);
void ConsumeSinkImpl() override; void ConsumeSinkImpl(Core::System& system) override;
void ProcessMethodCall(u32 method, u32 argument, u32 nonshadow_argument, bool is_last_call); void ProcessMethodCall(u32 method, u32 argument, u32 nonshadow_argument, bool is_last_call);
@ -3227,7 +3226,7 @@ private:
void ProcessQueryGet(); void ProcessQueryGet();
/// Writes the query result accordingly. /// Writes the query result accordingly.
void StampQueryResult(u64 payload, bool long_query); void StampQueryResult(Core::System& system, u64 payload, bool long_query);
/// Handles conditional rendering. /// Handles conditional rendering.
void ProcessQueryCondition(); void ProcessQueryCondition();
@ -3242,7 +3241,6 @@ private:
bool IsMethodExecutable(u32 method); bool IsMethodExecutable(u32 method);
Core::System& system;
MemoryManager& memory_manager; MemoryManager& memory_manager;
VideoCore::RasterizerInterface* rasterizer = nullptr; VideoCore::RasterizerInterface* rasterizer = nullptr;

View file

@ -21,8 +21,9 @@ namespace Tegra::Engines {
using namespace Texture; using namespace Texture;
MaxwellDMA::MaxwellDMA(Core::System& system_, MemoryManager& memory_manager_) MaxwellDMA::MaxwellDMA(MemoryManager& memory_manager_)
: system{system_}, memory_manager{memory_manager_} { : memory_manager{memory_manager_}
{
execution_mask.reset(); execution_mask.reset();
execution_mask[offsetof(Regs, launch_dma) / sizeof(u32)] = true; execution_mask[offsetof(Regs, launch_dma) / sizeof(u32)] = true;
} }
@ -33,14 +34,14 @@ void MaxwellDMA::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) {
rasterizer = rasterizer_; rasterizer = rasterizer_;
} }
void MaxwellDMA::ConsumeSinkImpl() { void MaxwellDMA::ConsumeSinkImpl(Core::System& system) {
for (auto [method, value] : method_sink) { for (auto [method, value] : method_sink) {
regs.reg_array[method] = value; regs.reg_array[method] = value;
} }
method_sink.clear(); method_sink.clear();
} }
void MaxwellDMA::CallMethod(u32 method, u32 method_argument, bool is_last_call) { void MaxwellDMA::CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) {
ASSERT_MSG(method < NUM_REGS, "Invalid MaxwellDMA register"); ASSERT_MSG(method < NUM_REGS, "Invalid MaxwellDMA register");
regs.reg_array[method] = method_argument; regs.reg_array[method] = method_argument;
@ -50,16 +51,14 @@ void MaxwellDMA::CallMethod(u32 method, u32 method_argument, bool is_last_call)
} }
} }
void MaxwellDMA::CallMultiMethod(u32 method, const u32* base_start, u32 amount, void MaxwellDMA::CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) {
u32 methods_pending) {
for (u32 i = 0; i < amount; ++i) { for (u32 i = 0; i < amount; ++i) {
CallMethod(method, base_start[i], methods_pending - i <= 1); CallMethod(system, method, base_start[i], methods_pending - i <= 1);
} }
} }
void MaxwellDMA::Launch() { void MaxwellDMA::Launch() {
LOG_TRACE(Render_OpenGL, "DMA copy 0x{:x} -> 0x{:x}", static_cast<GPUVAddr>(regs.offset_in), LOG_TRACE(Render_OpenGL, "DMA copy 0x{:x} -> 0x{:x}", static_cast<GPUVAddr>(regs.offset_in), GPUVAddr(regs.offset_out));
static_cast<GPUVAddr>(regs.offset_out));
// TODO(Subv): Perform more research and implement all features of this engine. // TODO(Subv): Perform more research and implement all features of this engine.
const LaunchDMA& launch = regs.launch_dma; const LaunchDMA& launch = regs.launch_dma;

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@ -238,15 +241,14 @@ public:
void BindRasterizer(VideoCore::RasterizerInterface* rasterizer); void BindRasterizer(VideoCore::RasterizerInterface* rasterizer);
explicit MaxwellDMA(Core::System& system_, MemoryManager& memory_manager_); explicit MaxwellDMA(MemoryManager& memory_manager_);
~MaxwellDMA() override; ~MaxwellDMA() override;
/// Write the value to the register identified by method. /// Write the value to the register identified by method.
void CallMethod(u32 method, u32 method_argument, bool is_last_call) override; void CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) override;
/// Write multiple values to the register identified by method. /// Write multiple values to the register identified by method.
void CallMultiMethod(u32 method, const u32* base_start, u32 amount, void CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) override;
u32 methods_pending) override;
private: private:
/// Performs the copy from the source buffer to the destination buffer as configured in the /// Performs the copy from the source buffer to the destination buffer as configured in the
@ -261,9 +263,7 @@ private:
void ReleaseSemaphore(); void ReleaseSemaphore();
void ConsumeSinkImpl() override; void ConsumeSinkImpl(Core::System& system) override;
Core::System& system;
MemoryManager& memory_manager; MemoryManager& memory_manager;
VideoCore::RasterizerInterface* rasterizer = nullptr; VideoCore::RasterizerInterface* rasterizer = nullptr;

View file

@ -26,18 +26,16 @@ class MemoryManager;
namespace Tegra::Engines { namespace Tegra::Engines {
class Nv01Timer final : public EngineInterface { class Nv01Timer final : public EngineInterface {
public: public:
explicit Nv01Timer(Core::System& system_, MemoryManager& memory_manager) explicit Nv01Timer(MemoryManager& memory_manager) noexcept {}
: system{system_} ~Nv01Timer() noexcept override {}
{}
~Nv01Timer() override;
/// Write the value to the register identified by method. /// Write the value to the register identified by method.
void CallMethod(u32 method, u32 method_argument, bool is_last_call) override { void CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) override {
LOG_DEBUG(HW_GPU, "method={}, argument={}, is_last_call={}", method, method_argument, is_last_call); LOG_DEBUG(HW_GPU, "method={}, argument={}, is_last_call={}", method, method_argument, is_last_call);
} }
/// Write multiple values to the register identified by method. /// Write multiple values to the register identified by method.
void CallMultiMethod(u32 method, const u32* base_start, u32 amount, u32 methods_pending) override { void CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) override {
LOG_DEBUG(HW_GPU, "method={}, base_start={}, amount={}, pending={}", method, fmt::ptr(base_start), amount, methods_pending); LOG_DEBUG(HW_GPU, "method={}, base_start={}, amount={}, pending={}", method, fmt::ptr(base_start), amount, methods_pending);
} }
@ -46,7 +44,6 @@ public:
INSERT_PADDING_BYTES_NOINIT(0x48); INSERT_PADDING_BYTES_NOINIT(0x48);
} regs{}; } regs{};
private: private:
void ConsumeSinkImpl() override {} void ConsumeSinkImpl(Core::System& system) override {}
Core::System& system;
}; };
} }

View file

@ -198,22 +198,22 @@ void Puller::CallEngineMethod(DmaPusher& dma_pusher, const MethodCall& method_ca
const EngineID engine = bound_engines[method_call.subchannel]; const EngineID engine = bound_engines[method_call.subchannel];
switch (engine) { switch (engine) {
case EngineID::FERMI_TWOD_A: case EngineID::FERMI_TWOD_A:
dma_pusher.channel_state.payload->fermi_2d.CallMethod(method_call.method, method_call.argument, method_call.IsLastCall()); dma_pusher.channel_state.payload->fermi_2d.CallMethod(dma_pusher.system, method_call.method, method_call.argument, method_call.IsLastCall());
break; break;
case EngineID::MAXWELL_B: case EngineID::MAXWELL_B:
dma_pusher.channel_state.payload->maxwell_3d.CallMethod(method_call.method, method_call.argument, method_call.IsLastCall()); dma_pusher.channel_state.payload->maxwell_3d.CallMethod(dma_pusher.system, method_call.method, method_call.argument, method_call.IsLastCall());
break; break;
case EngineID::KEPLER_COMPUTE_B: case EngineID::KEPLER_COMPUTE_B:
dma_pusher.channel_state.payload->kepler_compute.CallMethod(method_call.method, method_call.argument, method_call.IsLastCall()); dma_pusher.channel_state.payload->kepler_compute.CallMethod(dma_pusher.system, method_call.method, method_call.argument, method_call.IsLastCall());
break; break;
case EngineID::MAXWELL_DMA_COPY_A: case EngineID::MAXWELL_DMA_COPY_A:
dma_pusher.channel_state.payload->maxwell_dma.CallMethod(method_call.method, method_call.argument, method_call.IsLastCall()); dma_pusher.channel_state.payload->maxwell_dma.CallMethod(dma_pusher.system, method_call.method, method_call.argument, method_call.IsLastCall());
break; break;
case EngineID::KEPLER_INLINE_TO_MEMORY_B: case EngineID::KEPLER_INLINE_TO_MEMORY_B:
dma_pusher.channel_state.payload->kepler_memory.CallMethod(method_call.method, method_call.argument, method_call.IsLastCall()); dma_pusher.channel_state.payload->kepler_memory.CallMethod(dma_pusher.system, method_call.method, method_call.argument, method_call.IsLastCall());
break; break;
case EngineID::NV01_TIMER: case EngineID::NV01_TIMER:
dma_pusher.channel_state.payload->nv01_timer.CallMethod(method_call.method, method_call.argument, method_call.IsLastCall()); dma_pusher.channel_state.payload->nv01_timer.CallMethod(dma_pusher.system, method_call.method, method_call.argument, method_call.IsLastCall());
break; break;
default: default:
UNIMPLEMENTED_MSG("Unimplemented engine"); UNIMPLEMENTED_MSG("Unimplemented engine");
@ -226,22 +226,22 @@ void Puller::CallEngineMultiMethod(DmaPusher& dma_pusher, u32 method, u32 subcha
const EngineID engine = bound_engines[subchannel]; const EngineID engine = bound_engines[subchannel];
switch (engine) { switch (engine) {
case EngineID::FERMI_TWOD_A: case EngineID::FERMI_TWOD_A:
dma_pusher.channel_state.payload->fermi_2d.CallMultiMethod(method, base_start, amount, methods_pending); dma_pusher.channel_state.payload->fermi_2d.CallMultiMethod(dma_pusher.system, method, base_start, amount, methods_pending);
break; break;
case EngineID::MAXWELL_B: case EngineID::MAXWELL_B:
dma_pusher.channel_state.payload->maxwell_3d.CallMultiMethod(method, base_start, amount, methods_pending); dma_pusher.channel_state.payload->maxwell_3d.CallMultiMethod(dma_pusher.system, method, base_start, amount, methods_pending);
break; break;
case EngineID::KEPLER_COMPUTE_B: case EngineID::KEPLER_COMPUTE_B:
dma_pusher.channel_state.payload->kepler_compute.CallMultiMethod(method, base_start, amount, methods_pending); dma_pusher.channel_state.payload->kepler_compute.CallMultiMethod(dma_pusher.system, method, base_start, amount, methods_pending);
break; break;
case EngineID::MAXWELL_DMA_COPY_A: case EngineID::MAXWELL_DMA_COPY_A:
dma_pusher.channel_state.payload->maxwell_dma.CallMultiMethod(method, base_start, amount, methods_pending); dma_pusher.channel_state.payload->maxwell_dma.CallMultiMethod(dma_pusher.system, method, base_start, amount, methods_pending);
break; break;
case EngineID::KEPLER_INLINE_TO_MEMORY_B: case EngineID::KEPLER_INLINE_TO_MEMORY_B:
dma_pusher.channel_state.payload->kepler_memory.CallMultiMethod(method, base_start, amount, methods_pending); dma_pusher.channel_state.payload->kepler_memory.CallMultiMethod(dma_pusher.system, method, base_start, amount, methods_pending);
break; break;
case EngineID::NV01_TIMER: case EngineID::NV01_TIMER:
dma_pusher.channel_state.payload->nv01_timer.CallMultiMethod(method, base_start, amount, methods_pending); dma_pusher.channel_state.payload->nv01_timer.CallMultiMethod(dma_pusher.system, method, base_start, amount, methods_pending);
break; break;
default: default:
UNIMPLEMENTED_MSG("Unimplemented engine"); UNIMPLEMENTED_MSG("Unimplemented engine");

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later