From b75e81af5e11cb09eae405d51c40489401794912 Mon Sep 17 00:00:00 2001 From: lizzie Date: Fri, 6 Mar 2026 15:05:39 +0100 Subject: [PATCH] [video_core/engines] implement stub NV01 timer, inline other channel engines (#3640) Signed-off-by: lizzie Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3640 Reviewed-by: CamilleLaVey Reviewed-by: DraVee Co-authored-by: lizzie Co-committed-by: lizzie --- src/video_core/control/channel_state.cpp | 15 ++++--- src/video_core/control/channel_state.h | 44 +++++++++---------- src/video_core/engines/engine_interface.h | 3 +- src/video_core/engines/maxwell_3d.h | 2 +- src/video_core/engines/nv01_timer.h | 52 +++++++++++++++++++++++ src/video_core/engines/puller.cpp | 42 +++++++++--------- src/video_core/engines/puller.h | 4 ++ 7 files changed, 109 insertions(+), 53 deletions(-) create mode 100644 src/video_core/engines/nv01_timer.h diff --git a/src/video_core/control/channel_state.cpp b/src/video_core/control/channel_state.cpp index 2539997d53..d07c7e2a83 100644 --- a/src/video_core/control/channel_state.cpp +++ b/src/video_core/control/channel_state.cpp @@ -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-License-Identifier: GPL-3.0-or-later @@ -19,12 +22,12 @@ ChannelState::ChannelState(s32 bind_id_) : bind_id{bind_id_}, initialized{} {} void ChannelState::Init(Core::System& system, GPU& gpu, u64 program_id_) { ASSERT(memory_manager); program_id = program_id_; - dma_pusher = std::make_unique(system, gpu, *memory_manager, *this); - maxwell_3d = std::make_unique(system, *memory_manager); - fermi_2d = std::make_unique(*memory_manager); - kepler_compute = std::make_unique(system, *memory_manager); - maxwell_dma = std::make_unique(system, *memory_manager); - kepler_memory = std::make_unique(system, *memory_manager); + dma_pusher.emplace(system, gpu, *memory_manager, *this); + maxwell_3d.emplace(system, *memory_manager); + fermi_2d.emplace(*memory_manager); + kepler_compute.emplace(system, *memory_manager); + maxwell_dma.emplace(system, *memory_manager); + kepler_memory.emplace(system, *memory_manager); initialized = true; } diff --git a/src/video_core/control/channel_state.h b/src/video_core/control/channel_state.h index b385f4939f..2984d2e09e 100644 --- a/src/video_core/control/channel_state.h +++ b/src/video_core/control/channel_state.h @@ -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-License-Identifier: GPL-3.0-or-later @@ -6,6 +9,12 @@ #include #include "common/common_types.h" +#include "video_core/engines/fermi_2d.h" +#include "video_core/engines/kepler_memory.h" +#include "video_core/engines/kepler_compute.h" +#include "video_core/engines/maxwell_3d.h" +#include "video_core/engines/maxwell_dma.h" +#include "video_core/dma_pusher.h" namespace Core { class System; @@ -18,49 +27,34 @@ 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 { explicit 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, u64 program_id); void BindRasterizer(VideoCore::RasterizerInterface* rasterizer); - s32 bind_id = -1; - u64 program_id = 0; /// 3D engine - std::unique_ptr maxwell_3d; + std::optional maxwell_3d; /// 2D engine - std::unique_ptr fermi_2d; + std::optional fermi_2d; /// Compute engine - std::unique_ptr kepler_compute; + std::optional kepler_compute; /// DMA engine - std::unique_ptr maxwell_dma; + std::optional maxwell_dma; /// Inline memory engine - std::unique_ptr kepler_memory; - + std::optional kepler_memory; + /// NV01 Timer + std::optional nv01_timer; + std::optional dma_pusher; std::shared_ptr memory_manager; - std::unique_ptr dma_pusher; - + s32 bind_id = -1; + u64 program_id = 0; bool initialized{}; }; diff --git a/src/video_core/engines/engine_interface.h b/src/video_core/engines/engine_interface.h index e271ecab59..bf3bd66aca 100644 --- a/src/video_core/engines/engine_interface.h +++ b/src/video_core/engines/engine_interface.h @@ -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-FileCopyrightText: Copyright 2020 yuzu Emulator Project @@ -15,6 +15,7 @@ namespace Tegra::Engines { enum class EngineTypes : u32 { + Nv01Timer, KeplerCompute, Maxwell3D, Fermi2D, diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 52546e4279..b73082b7ef 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h @@ -2258,7 +2258,7 @@ public: /// Returns whether the vertex array specified by index is supposed to be /// accessed per instance or not. bool IsInstancingEnabled(std::size_t index) const { - return is_instanced[index]; + return bool(is_instanced[index]); //FUCK YOU MSVC } }; diff --git a/src/video_core/engines/nv01_timer.h b/src/video_core/engines/nv01_timer.h new file mode 100644 index 0000000000..a8e60f9f53 --- /dev/null +++ b/src/video_core/engines/nv01_timer.h @@ -0,0 +1,52 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include +#include "common/bit_field.h" +#include "common/common_funcs.h" +#include "common/common_types.h" +#include "common/logging/log.h" +#include "video_core/engines/engine_interface.h" +#include "video_core/engines/engine_upload.h" + +namespace Core { +class System; +} + +namespace Tegra { +class MemoryManager; +} + +namespace Tegra::Engines { +class Nv01Timer final : public EngineInterface { +public: + explicit Nv01Timer(Core::System& system_, MemoryManager& memory_manager) + : system{system_} + {} + ~Nv01Timer() override; + + /// Write the value to the register identified by method. + void CallMethod(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); + } + + /// Write multiple values to the register identified by method. + void CallMultiMethod(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); + } + + struct Regs { + // No fucking idea + INSERT_PADDING_BYTES_NOINIT(0x48); + } regs{}; +private: + void ConsumeSinkImpl() override {} + Core::System& system; +}; +} diff --git a/src/video_core/engines/puller.cpp b/src/video_core/engines/puller.cpp index 8dd34c04ab..b5b4e5d7fa 100644 --- a/src/video_core/engines/puller.cpp +++ b/src/video_core/engines/puller.cpp @@ -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-License-Identifier: GPL-3.0-or-later @@ -34,24 +37,22 @@ void Puller::ProcessBindMethod(const MethodCall& method_call) { bound_engines[method_call.subchannel] = engine_id; switch (engine_id) { case EngineID::FERMI_TWOD_A: - dma_pusher.BindSubchannel(channel_state.fermi_2d.get(), method_call.subchannel, - EngineTypes::Fermi2D); + dma_pusher.BindSubchannel(&*channel_state.fermi_2d, method_call.subchannel, EngineTypes::Fermi2D); break; case EngineID::MAXWELL_B: - dma_pusher.BindSubchannel(channel_state.maxwell_3d.get(), method_call.subchannel, - EngineTypes::Maxwell3D); + dma_pusher.BindSubchannel(&*channel_state.maxwell_3d, method_call.subchannel, EngineTypes::Maxwell3D); break; case EngineID::KEPLER_COMPUTE_B: - dma_pusher.BindSubchannel(channel_state.kepler_compute.get(), method_call.subchannel, - EngineTypes::KeplerCompute); + dma_pusher.BindSubchannel(&*channel_state.kepler_compute, method_call.subchannel, EngineTypes::KeplerCompute); break; case EngineID::MAXWELL_DMA_COPY_A: - dma_pusher.BindSubchannel(channel_state.maxwell_dma.get(), method_call.subchannel, - EngineTypes::MaxwellDMA); + dma_pusher.BindSubchannel(&*channel_state.maxwell_dma, method_call.subchannel, EngineTypes::MaxwellDMA); break; case EngineID::KEPLER_INLINE_TO_MEMORY_B: - dma_pusher.BindSubchannel(channel_state.kepler_memory.get(), method_call.subchannel, - EngineTypes::KeplerMemory); + dma_pusher.BindSubchannel(&*channel_state.kepler_memory, method_call.subchannel, EngineTypes::KeplerMemory); + break; + case EngineID::NV01_TIMER: + dma_pusher.BindSubchannel(&*channel_state.nv01_timer, method_call.subchannel, EngineTypes::Nv01Timer); break; default: UNIMPLEMENTED_MSG("Unimplemented engine {:04X}", engine_id); @@ -209,24 +210,22 @@ void Puller::CallEngineMethod(const MethodCall& method_call) { switch (engine) { case EngineID::FERMI_TWOD_A: - channel_state.fermi_2d->CallMethod(method_call.method, method_call.argument, - method_call.IsLastCall()); + channel_state.fermi_2d->CallMethod(method_call.method, method_call.argument, method_call.IsLastCall()); break; case EngineID::MAXWELL_B: - channel_state.maxwell_3d->CallMethod(method_call.method, method_call.argument, - method_call.IsLastCall()); + channel_state.maxwell_3d->CallMethod(method_call.method, method_call.argument, method_call.IsLastCall()); break; case EngineID::KEPLER_COMPUTE_B: - channel_state.kepler_compute->CallMethod(method_call.method, method_call.argument, - method_call.IsLastCall()); + channel_state.kepler_compute->CallMethod(method_call.method, method_call.argument, method_call.IsLastCall()); break; case EngineID::MAXWELL_DMA_COPY_A: - channel_state.maxwell_dma->CallMethod(method_call.method, method_call.argument, - method_call.IsLastCall()); + channel_state.maxwell_dma->CallMethod(method_call.method, method_call.argument, method_call.IsLastCall()); break; case EngineID::KEPLER_INLINE_TO_MEMORY_B: - channel_state.kepler_memory->CallMethod(method_call.method, method_call.argument, - method_call.IsLastCall()); + channel_state.kepler_memory->CallMethod(method_call.method, method_call.argument, method_call.IsLastCall()); + break; + case EngineID::NV01_TIMER: + channel_state.nv01_timer->CallMethod(method_call.method, method_call.argument, method_call.IsLastCall()); break; default: UNIMPLEMENTED_MSG("Unimplemented engine"); @@ -255,6 +254,9 @@ void Puller::CallEngineMultiMethod(u32 method, u32 subchannel, const u32* base_s case EngineID::KEPLER_INLINE_TO_MEMORY_B: channel_state.kepler_memory->CallMultiMethod(method, base_start, amount, methods_pending); break; + case EngineID::NV01_TIMER: + channel_state.nv01_timer->CallMultiMethod(method, base_start, amount, methods_pending); + break; default: UNIMPLEMENTED_MSG("Unimplemented engine"); break; diff --git a/src/video_core/engines/puller.h b/src/video_core/engines/puller.h index d4175ee945..fe5102e3ed 100644 --- a/src/video_core/engines/puller.h +++ b/src/video_core/engines/puller.h @@ -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-License-Identifier: GPL-3.0-or-later @@ -20,6 +23,7 @@ class MemoryManager; class DmaPusher; enum class EngineID { + NV01_TIMER = 0x0004, FERMI_TWOD_A = 0x902D, // 2D Engine MAXWELL_B = 0xB197, // 3D Engine KEPLER_COMPUTE_B = 0xB1C0,