diff --git a/.gitignore b/.gitignore index 75e728babe..67bdd8adf4 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ # Build directory /[Bb]uild*/ doc-build/ +out/ AppDir/ uruntime diff --git a/src/audio_core/audio_core.cpp b/src/audio_core/audio_core.cpp index 234c831ac0..fcaab2b320 100644 --- a/src/audio_core/audio_core.cpp +++ b/src/audio_core/audio_core.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -11,11 +8,10 @@ namespace AudioCore { -AudioCore::AudioCore(Core::System& system) { - audio_manager.emplace(); +AudioCore::AudioCore(Core::System& system) : audio_manager{std::make_unique()} { CreateSinks(); // Must be created after the sinks - adsp.emplace(system, *output_sink); + adsp = std::make_unique(system, *output_sink); } AudioCore ::~AudioCore() { diff --git a/src/audio_core/audio_core.h b/src/audio_core/audio_core.h index ababd780b1..e4e27fc661 100644 --- a/src/audio_core/audio_core.h +++ b/src/audio_core/audio_core.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -18,7 +15,10 @@ class System; namespace AudioCore { -/// @brief Main audio class, stored inside the core, and holding the audio manager, all sinks, and the ADSP. +class AudioManager; +/** + * Main audio class, stored inside the core, and holding the audio manager, all sinks, and the ADSP. + */ class AudioCore { public: explicit AudioCore(Core::System& system); @@ -50,22 +50,27 @@ public: */ Sink::Sink& GetInputSink(); - /// @brief Get the ADSP. - /// @return Ref to the ADSP. + /** + * Get the ADSP. + * + * @return Ref to the ADSP. + */ ADSP::ADSP& ADSP(); private: - /// @brief Create the sinks on startup. + /** + * Create the sinks on startup. + */ void CreateSinks(); /// Main audio manager for audio in/out - std::optional audio_manager; + std::unique_ptr audio_manager; /// Sink used for audio renderer and audio out std::unique_ptr output_sink; /// Sink used for audio input std::unique_ptr input_sink; /// The ADSP in the sysmodule - std::optional adsp; + std::unique_ptr adsp; }; } // namespace AudioCore diff --git a/src/audio_core/audio_in_manager.cpp b/src/audio_core/audio_in_manager.cpp index 6b528e9db0..63b064922a 100644 --- a/src/audio_core/audio_in_manager.cpp +++ b/src/audio_core/audio_in_manager.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -44,7 +41,8 @@ void Manager::ReleaseSessionId(const size_t session_id) { Result Manager::LinkToManager() { std::scoped_lock l{mutex}; if (!linked_to_manager) { - system.AudioCore().GetAudioManager().SetInManager(std::bind(&Manager::BufferReleaseAndRegister, this)); + AudioManager& manager{system.AudioCore().GetAudioManager()}; + manager.SetInManager(std::bind(&Manager::BufferReleaseAndRegister, this)); linked_to_manager = true; } diff --git a/src/audio_core/audio_manager.cpp b/src/audio_core/audio_manager.cpp index 93142a53fb..10b56f2140 100644 --- a/src/audio_core/audio_manager.cpp +++ b/src/audio_core/audio_manager.cpp @@ -1,77 +1,81 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include "audio_core/audio_manager.h" -#include "common/thread.h" #include "core/core.h" #include "core/hle/service/audio/errors.h" namespace AudioCore { AudioManager::AudioManager() { - thread = std::jthread([this](std::stop_token stop_token) { - Common::SetCurrentThreadName("AudioManager"); - std::unique_lock l{events.GetAudioEventLock()}; - events.ClearEvents(); - while (!stop_token.stop_requested()) { - const auto timed_out{events.Wait(l, std::chrono::seconds(2))}; - if (events.CheckAudioEventSet(Event::Type::Max)) { - break; - } - for (size_t i = 0; i < buffer_events.size(); i++) { - const auto event_type = Event::Type(i); - if (events.CheckAudioEventSet(event_type) || timed_out) { - if (buffer_events[i]) { - buffer_events[i](); - } - } - events.SetAudioEvent(event_type, false); - } - } - }); + thread = std::jthread([this]() { ThreadFunc(); }); } void AudioManager::Shutdown() { + running = false; events.SetAudioEvent(Event::Type::Max, true); - if (thread.joinable()) { - thread.request_stop(); - thread.join(); - } + thread.join(); } Result AudioManager::SetOutManager(BufferEventFunc buffer_func) { - if (thread.joinable()) { - std::scoped_lock l{lock}; - const auto index{events.GetManagerIndex(Event::Type::AudioOutManager)}; - if (buffer_events[index] == nullptr) { - buffer_events[index] = std::move(buffer_func); - needs_update = true; - events.SetAudioEvent(Event::Type::AudioOutManager, true); - } - return ResultSuccess; + if (!running) { + return Service::Audio::ResultOperationFailed; } - return Service::Audio::ResultOperationFailed; + + std::scoped_lock l{lock}; + + const auto index{events.GetManagerIndex(Event::Type::AudioOutManager)}; + if (buffer_events[index] == nullptr) { + buffer_events[index] = std::move(buffer_func); + needs_update = true; + events.SetAudioEvent(Event::Type::AudioOutManager, true); + } + return ResultSuccess; } Result AudioManager::SetInManager(BufferEventFunc buffer_func) { - if (thread.joinable()) { - std::scoped_lock l{lock}; - const auto index{events.GetManagerIndex(Event::Type::AudioInManager)}; - if (buffer_events[index] == nullptr) { - buffer_events[index] = std::move(buffer_func); - needs_update = true; - events.SetAudioEvent(Event::Type::AudioInManager, true); - } - return ResultSuccess; + if (!running) { + return Service::Audio::ResultOperationFailed; } - return Service::Audio::ResultOperationFailed; + + std::scoped_lock l{lock}; + + const auto index{events.GetManagerIndex(Event::Type::AudioInManager)}; + if (buffer_events[index] == nullptr) { + buffer_events[index] = std::move(buffer_func); + needs_update = true; + events.SetAudioEvent(Event::Type::AudioInManager, true); + } + return ResultSuccess; } void AudioManager::SetEvent(const Event::Type type, const bool signalled) { events.SetAudioEvent(type, signalled); } +void AudioManager::ThreadFunc() { + std::unique_lock l{events.GetAudioEventLock()}; + events.ClearEvents(); + running = true; + + while (running) { + const auto timed_out{events.Wait(l, std::chrono::seconds(2))}; + + if (events.CheckAudioEventSet(Event::Type::Max)) { + break; + } + + for (size_t i = 0; i < buffer_events.size(); i++) { + const auto event_type = static_cast(i); + + if (events.CheckAudioEventSet(event_type) || timed_out) { + if (buffer_events[i]) { + buffer_events[i](); + } + } + events.SetAudioEvent(event_type, false); + } + } +} + } // namespace AudioCore diff --git a/src/audio_core/audio_manager.h b/src/audio_core/audio_manager.h index 0194aa16db..02270242ac 100644 --- a/src/audio_core/audio_manager.h +++ b/src/audio_core/audio_manager.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -69,6 +66,13 @@ public: void SetEvent(Event::Type type, bool signalled); private: + /** + * Main thread, waiting on a manager signal and calling the registered function. + */ + void ThreadFunc(); + + /// Is the main thread running? + std::atomic running{}; /// Unused bool needs_update{}; /// Events to be set and signalled diff --git a/src/audio_core/audio_out_manager.cpp b/src/audio_core/audio_out_manager.cpp index 569df8d1e0..316ea7c817 100644 --- a/src/audio_core/audio_out_manager.cpp +++ b/src/audio_core/audio_out_manager.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -43,7 +40,8 @@ void Manager::ReleaseSessionId(const size_t session_id) { Result Manager::LinkToManager() { std::scoped_lock l{mutex}; if (!linked_to_manager) { - system.AudioCore().GetAudioManager().SetOutManager(std::bind(&Manager::BufferReleaseAndRegister, this)); + AudioManager& manager{system.AudioCore().GetAudioManager()}; + manager.SetOutManager(std::bind(&Manager::BufferReleaseAndRegister, this)); linked_to_manager = true; } diff --git a/src/audio_core/device/device_session.cpp b/src/audio_core/device/device_session.cpp index 2e9da7876f..2a1ae1bb3f 100644 --- a/src/audio_core/device/device_session.cpp +++ b/src/audio_core/device/device_session.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -42,7 +39,7 @@ Result DeviceSession::Initialize(std::string_view name_, SampleFormat sample_for channel_count = channel_count_; session_id = session_id_; handle = handle_; - handle->Open(system.Kernel()); + handle->Open(); applet_resource_user_id = applet_resource_user_id_; if (type == Sink::StreamType::In) { @@ -63,7 +60,7 @@ void DeviceSession::Finalize() { } if (handle) { - handle->Close(system.Kernel()); + handle->Close(); handle = nullptr; } } diff --git a/src/audio_core/in/audio_in_system.cpp b/src/audio_core/in/audio_in_system.cpp index f71a2df6be..ec1f565736 100644 --- a/src/audio_core/in/audio_in_system.cpp +++ b/src/audio_core/in/audio_in_system.cpp @@ -122,7 +122,7 @@ Result System::Stop() { session->SetVolume(0.0f); session->ClearBuffers(); if (buffers.ReleaseBuffers(system.CoreTiming(), *session, true)) { - buffer_event->Signal(system.Kernel()); + buffer_event->Signal(); } state = State::Stopped; } @@ -164,7 +164,7 @@ void System::ReleaseBuffers() { if (signal) { // Signal if any buffer was released, or if none are registered, we need more. - buffer_event->Signal(system.Kernel()); + buffer_event->Signal(); } } @@ -181,7 +181,7 @@ bool System::FlushAudioInBuffers() { buffers.FlushBuffers(buffers_released); if (buffers_released > 0) { - buffer_event->Signal(system.Kernel()); + buffer_event->Signal(); } return true; } diff --git a/src/audio_core/out/audio_out_system.cpp b/src/audio_core/out/audio_out_system.cpp index 46f30f19c6..dcb0d0694e 100644 --- a/src/audio_core/out/audio_out_system.cpp +++ b/src/audio_core/out/audio_out_system.cpp @@ -121,7 +121,7 @@ Result System::Stop() { session->SetVolume(0.0f); session->ClearBuffers(); if (buffers.ReleaseBuffers(system.CoreTiming(), *session, true)) { - buffer_event->Signal(system.Kernel()); + buffer_event->Signal(); } state = State::Stopped; } @@ -162,7 +162,7 @@ void System::ReleaseBuffers() { bool signal{buffers.ReleaseBuffers(system.CoreTiming(), *session, false)}; if (signal) { // Signal if any buffer was released, or if none are registered, we need more. - buffer_event->Signal(system.Kernel()); + buffer_event->Signal(); } } @@ -179,7 +179,7 @@ bool System::FlushAudioOutBuffers() { buffers.FlushBuffers(buffers_released); if (buffers_released > 0) { - buffer_event->Signal(system.Kernel()); + buffer_event->Signal(); } return true; } diff --git a/src/audio_core/renderer/system.cpp b/src/audio_core/renderer/system.cpp index b7675ff5de..2053ec6dd4 100644 --- a/src/audio_core/renderer/system.cpp +++ b/src/audio_core/renderer/system.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project @@ -540,7 +540,7 @@ Result System::Update(std::span input, std::span performance, std: return result; } - adsp_rendered_event->Clear(core.Kernel()); + adsp_rendered_event->Clear(); num_times_updated++; const auto end_time{core.CoreTiming().GetGlobalTimeNs().count()}; @@ -624,7 +624,7 @@ void System::SendCommandToDsp() { reset_command_buffers = false; command_buffer_size = command_size; if (remaining_command_count == 0) { - adsp_rendered_event->Signal(core.Kernel()); + adsp_rendered_event->Signal(); } } else { audio_renderer.ClearRemainCommandCount(session_id); diff --git a/src/core/core.cpp b/src/core/core.cpp index 33fece39f6..e730b808e0 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -108,7 +108,7 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, struct System::Impl { explicit Impl(System& system) - : kernel{system}, fs_controller{system}, hid_core{system.Kernel()}, cpu_manager{system}, + : kernel{system}, fs_controller{system}, hid_core{}, cpu_manager{system}, reporter{system}, applet_manager{system}, frontend_applets{system}, profile_manager{} {} u64 program_id; @@ -271,7 +271,7 @@ struct System::Impl { SystemResultStatus SetupForApplicationProcess(System& system, Frontend::EmuWindow& emu_window) { host1x_core.emplace(system); - VideoCore::CreateGPU(gpu_core, emu_window, system); + gpu_core = VideoCore::CreateGPU(emu_window, system); if (!gpu_core) return SystemResultStatus::ErrorVideoCore; @@ -347,7 +347,7 @@ struct System::Impl { // Register with applet manager // All threads are started, begin main process execution, now that we're in the clear - applet_manager.CreateAndInsertByFrontendAppletParameters(std::make_unique(*std::move(process)), params); + applet_manager.CreateAndInsertByFrontendAppletParameters(std::move(process), params); if (Settings::values.gamecard_inserted) { if (Settings::values.gamecard_current_game) { @@ -391,8 +391,10 @@ struct System::Impl { is_powered_on = false; exit_locked = false; exit_requested = false; - if (gpu_core) + + if (gpu_core != nullptr) { gpu_core->NotifyShutdown(); + } stop_event.request_stop(); core_timing.SyncPause(false); @@ -476,7 +478,6 @@ struct System::Impl { std::optional cheat_engine; std::optional memory_freezer; std::optional renderdoc_api; - std::optional gpu_core; std::array gpu_dirty_memory_managers; std::vector> user_channel; @@ -491,6 +492,7 @@ struct System::Impl { std::unique_ptr content_provider; /// AppLoader used to load the current executing application std::unique_ptr app_loader; + std::unique_ptr gpu_core; std::stop_source stop_event; mutable std::mutex suspend_guard; @@ -923,7 +925,7 @@ void System::PushGeneralChannelData(std::vector&& data) { const bool was_empty = impl->general_channel.empty(); impl->general_channel.push_back(std::move(data)); if (was_empty) { - impl->general_channel_event->Signal(impl->kernel); + impl->general_channel_event->Signal(); } } @@ -935,7 +937,7 @@ bool System::TryPopGeneralChannel(std::vector& out_data) { out_data = std::move(impl->general_channel.back()); impl->general_channel.pop_back(); if (impl->general_channel.empty()) { - impl->general_channel_event->Clear(impl->kernel); + impl->general_channel_event->Clear(); } return true; } diff --git a/src/core/core.h b/src/core/core.h index 93f7b057f7..012533c1fa 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -438,6 +438,7 @@ public: /// Applies any changes to settings to this core instance. void ApplySettings(); +private: struct Impl; std::unique_ptr impl; }; diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp index 7194fa5022..10fdcdf8a2 100644 --- a/src/core/cpu_manager.cpp +++ b/src/core/cpu_manager.cpp @@ -25,11 +25,9 @@ CpuManager::~CpuManager() = default; void CpuManager::Initialize() { num_cores = is_multicore ? Core::Hardware::NUM_CPU_CORES : 1; - gpu_barrier.emplace(num_cores + 1); + gpu_barrier = std::make_unique(num_cores + 1); for (std::size_t core = 0; core < num_cores; core++) - core_data[core].host_thread = std::jthread([this, core](std::stop_token token) { - RunThread(token, core); - }); + core_data[core].host_thread = std::jthread([this, core](std::stop_token token) { RunThread(token, core); }); } void CpuManager::Shutdown() { @@ -41,61 +39,69 @@ void CpuManager::Shutdown() { } } -void CpuManager::GuestThreadFunction(Kernel::KernelCore& kernel) { +void CpuManager::GuestThreadFunction() { if (is_multicore) { - MultiCoreRunGuestThread(kernel); + MultiCoreRunGuestThread(); } else { - SingleCoreRunGuestThread(kernel); + SingleCoreRunGuestThread(); } } -void CpuManager::IdleThreadFunction(Kernel::KernelCore& kernel) { +void CpuManager::IdleThreadFunction() { if (is_multicore) { - MultiCoreRunIdleThread(kernel); + MultiCoreRunIdleThread(); } else { - SingleCoreRunIdleThread(kernel); + SingleCoreRunIdleThread(); } } -void CpuManager::ShutdownThreadFunction(Kernel::KernelCore& kernel) { - ShutdownThread(kernel); +void CpuManager::ShutdownThreadFunction() { + ShutdownThread(); } -void CpuManager::HandleInterrupt(Kernel::KernelCore& kernel) { +void CpuManager::HandleInterrupt() { + auto& kernel = system.Kernel(); auto core_index = kernel.CurrentPhysicalCoreIndex(); - Kernel::KInterruptManager::HandleInterrupt(kernel, s32(core_index)); + + Kernel::KInterruptManager::HandleInterrupt(kernel, static_cast(core_index)); } /////////////////////////////////////////////////////////////////////////////// /// MultiCore /// /////////////////////////////////////////////////////////////////////////////// -void CpuManager::MultiCoreRunGuestThread(Kernel::KernelCore& kernel) { +void CpuManager::MultiCoreRunGuestThread() { // Similar to UserModeThreadStarter in HOS + auto& kernel = system.Kernel(); auto* thread = Kernel::GetCurrentThreadPointer(kernel); - kernel.CurrentScheduler()->OnThreadStart(kernel); + kernel.CurrentScheduler()->OnThreadStart(); while (true) { auto* physical_core = &kernel.CurrentPhysicalCore(); while (!physical_core->IsInterrupted()) { - physical_core->RunThread(kernel, thread); + physical_core->RunThread(thread); physical_core = &kernel.CurrentPhysicalCore(); } - HandleInterrupt(kernel); + + HandleInterrupt(); } } -void CpuManager::MultiCoreRunIdleThread(Kernel::KernelCore& kernel) { +void CpuManager::MultiCoreRunIdleThread() { // Not accurate to HOS. Remove this entire method when singlecore is removed. // See notes in KScheduler::ScheduleImpl for more information about why this // is inaccurate. - kernel.CurrentScheduler()->OnThreadStart(kernel); + + auto& kernel = system.Kernel(); + kernel.CurrentScheduler()->OnThreadStart(); + while (true) { auto& physical_core = kernel.CurrentPhysicalCore(); if (!physical_core.IsInterrupted()) { physical_core.Idle(); } - HandleInterrupt(kernel); + + HandleInterrupt(); } } @@ -103,14 +109,15 @@ void CpuManager::MultiCoreRunIdleThread(Kernel::KernelCore& kernel) { /// SingleCore /// /////////////////////////////////////////////////////////////////////////////// -void CpuManager::SingleCoreRunGuestThread(Kernel::KernelCore& kernel) { +void CpuManager::SingleCoreRunGuestThread() { + auto& kernel = system.Kernel(); auto* thread = Kernel::GetCurrentThreadPointer(kernel); - kernel.CurrentScheduler()->OnThreadStart(kernel); + kernel.CurrentScheduler()->OnThreadStart(); while (true) { auto* physical_core = &kernel.CurrentPhysicalCore(); if (!physical_core->IsInterrupted()) { - physical_core->RunThread(kernel, thread); + physical_core->RunThread(thread); physical_core = &kernel.CurrentPhysicalCore(); } @@ -118,22 +125,26 @@ void CpuManager::SingleCoreRunGuestThread(Kernel::KernelCore& kernel) { system.CoreTiming().Advance(); kernel.SetIsPhantomModeForSingleCore(false); - PreemptSingleCore(kernel); - HandleInterrupt(kernel); + PreemptSingleCore(); + HandleInterrupt(); } } -void CpuManager::SingleCoreRunIdleThread(Kernel::KernelCore& kernel) { - kernel.CurrentScheduler()->OnThreadStart(kernel); +void CpuManager::SingleCoreRunIdleThread() { + auto& kernel = system.Kernel(); + kernel.CurrentScheduler()->OnThreadStart(); + while (true) { - PreemptSingleCore(kernel, false); + PreemptSingleCore(false); system.CoreTiming().AddTicks(1000U); idle_count++; - HandleInterrupt(kernel); + HandleInterrupt(); } } -void CpuManager::PreemptSingleCore(Kernel::KernelCore& kernel, bool from_running_environment) { +void CpuManager::PreemptSingleCore(bool from_running_environment) { + auto& kernel = system.Kernel(); + if (idle_count >= 4 || from_running_environment) { if (!from_running_environment) { system.CoreTiming().Idle(); @@ -145,7 +156,7 @@ void CpuManager::PreemptSingleCore(Kernel::KernelCore& kernel, bool from_running } current_core.store((current_core + 1) % Core::Hardware::NUM_CPU_CORES); system.CoreTiming().ResetTicks(); - kernel.Scheduler(current_core).PreemptSingleCore(kernel); + kernel.Scheduler(current_core).PreemptSingleCore(); // We've now been scheduled again, and we may have exchanged schedulers. // Reload the scheduler in case it's different. @@ -154,16 +165,20 @@ void CpuManager::PreemptSingleCore(Kernel::KernelCore& kernel, bool from_running } } -void CpuManager::GuestActivate(Kernel::KernelCore& kernel) { +void CpuManager::GuestActivate() { // Similar to the HorizonKernelMain callback in HOS + auto& kernel = system.Kernel(); auto* scheduler = kernel.CurrentScheduler(); - scheduler->Activate(kernel); + + scheduler->Activate(); UNREACHABLE(); } -void CpuManager::ShutdownThread(Kernel::KernelCore& kernel) { +void CpuManager::ShutdownThread() { + auto& kernel = system.Kernel(); auto* thread = kernel.GetCurrentEmuThread(); auto core = is_multicore ? kernel.CurrentPhysicalCoreIndex() : 0; + Common::Fiber::YieldTo(thread->GetHostContext(), *core_data[core].host_context); UNREACHABLE(); } diff --git a/src/core/cpu_manager.h b/src/core/cpu_manager.h index 5e97f51bfb..a249dc5f76 100644 --- a/src/core/cpu_manager.h +++ b/src/core/cpu_manager.h @@ -1,6 +1,3 @@ -// 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 @@ -17,10 +14,6 @@ #include "common/thread.h" #include "core/hardware_properties.h" -namespace Kernel { -class KernelCore; -} - namespace Common { class Event; class Fiber; @@ -58,55 +51,57 @@ public: void Initialize(); void Shutdown(); - std::function GetGuestActivateFunc(Kernel::KernelCore& kernel) { - return [this, &kernel] { GuestActivate(kernel); }; + std::function GetGuestActivateFunc() { + return [this] { GuestActivate(); }; } - std::function GetGuestThreadFunc(Kernel::KernelCore& kernel) { - return [this, &kernel] { GuestThreadFunction(kernel); }; + std::function GetGuestThreadFunc() { + return [this] { GuestThreadFunction(); }; } - std::function GetIdleThreadStartFunc(Kernel::KernelCore& kernel) { - return [this, &kernel] { IdleThreadFunction(kernel); }; + std::function GetIdleThreadStartFunc() { + return [this] { IdleThreadFunction(); }; } - std::function GetShutdownThreadStartFunc(Kernel::KernelCore& kernel) { - return [this, &kernel] { ShutdownThreadFunction(kernel); }; + std::function GetShutdownThreadStartFunc() { + return [this] { ShutdownThreadFunction(); }; } - void PreemptSingleCore(Kernel::KernelCore& kernel, bool from_running_environment = true); + void PreemptSingleCore(bool from_running_environment = true); std::size_t CurrentCore() const { return current_core.load(); } private: - void GuestThreadFunction(Kernel::KernelCore& kernel); - void IdleThreadFunction(Kernel::KernelCore& kernel); - void ShutdownThreadFunction(Kernel::KernelCore& kernel); + void GuestThreadFunction(); + void IdleThreadFunction(); + void ShutdownThreadFunction(); - void MultiCoreRunGuestThread(Kernel::KernelCore& kernel); - void MultiCoreRunIdleThread(Kernel::KernelCore& kernel); + void MultiCoreRunGuestThread(); + void MultiCoreRunIdleThread(); - void SingleCoreRunGuestThread(Kernel::KernelCore& kernel); - void SingleCoreRunIdleThread(Kernel::KernelCore& kernel); + void SingleCoreRunGuestThread(); + void SingleCoreRunIdleThread(); - void GuestActivate(Kernel::KernelCore& kernel); - void HandleInterrupt(Kernel::KernelCore& kernel); - void ShutdownThread(Kernel::KernelCore& kernel); + void GuestActivate(); + void HandleInterrupt(); + void ShutdownThread(); void RunThread(std::stop_token stop_token, std::size_t core); - static constexpr std::size_t max_cycle_runs = 5; - - std::optional gpu_barrier{}; struct CoreData { std::shared_ptr host_context; std::jthread host_thread; }; + + std::unique_ptr gpu_barrier{}; std::array core_data{}; - Core::System& system; + + bool is_async_gpu{}; + bool is_multicore{}; std::atomic current_core{}; std::size_t idle_count{}; std::size_t num_cores{}; - bool is_async_gpu{}; - bool is_multicore{}; + static constexpr std::size_t max_cycle_runs = 5; + + System& system; }; } // namespace Core diff --git a/src/core/debugger/debugger.cpp b/src/core/debugger/debugger.cpp index d1c767721b..f90e78f959 100644 --- a/src/core/debugger/debugger.cpp +++ b/src/core/debugger/debugger.cpp @@ -81,10 +81,7 @@ namespace Core { class DebuggerImpl : public DebuggerBackend { public: - explicit DebuggerImpl(Core::System& system_, u16 port) - : system{system_} - , debug_process{system_.Kernel()} - { + explicit DebuggerImpl(Core::System& system_, u16 port) : system{system_} { InitializeServer(port); } @@ -124,7 +121,7 @@ public: } void SetActiveThread(Kernel::KThread* thread) override { - state->active_thread = {system.Kernel(), thread}; + state->active_thread = thread; } Kernel::KThread* GetActiveThread() override { @@ -171,7 +168,14 @@ private: frontend = std::make_unique(*this, system, debug_process.GetPointerUnsafe()); // Set the new state. This will tear down any existing state. - state.emplace(std::move(peer), io_context, system.Kernel()); + state = ConnectionState{ + .client_socket{std::move(peer)}, + .signal_pipe{io_context}, + .info{}, + .active_thread{}, + .client_data{}, + .pipe_data{}, + }; // Set up the client signals for new data. AsyncReceiveInto(state->signal_pipe, state->pipe_data, [&](auto d) { PipeData(d); }); @@ -200,7 +204,7 @@ private: PauseEmulation(); // Notify the client. - state->active_thread = {system.Kernel(), state->info.thread}; + state->active_thread = state->info.thread; UpdateActiveThread(); if (state->info.type == SignalType::Watchpoint) { @@ -254,7 +258,7 @@ private: auto* gdb = static_cast(frontend.get()); MarkResumed([this, threads = std::move(gdb->resume_threads)] { state->active_thread->SetStepState(Kernel::StepState::StepPending); - state->active_thread->Resume(system.Kernel(), Kernel::SuspendType::Debug); + state->active_thread->Resume(Kernel::SuspendType::Debug); ResumeThreads(threads, state->active_thread.GetPointerUnsafe()); }); break; @@ -277,7 +281,7 @@ private: // Put all threads to sleep on next scheduler round. for (auto& thread : ThreadList()) { - thread.RequestSuspend(system.Kernel(), Kernel::SuspendType::Debug); + thread.RequestSuspend(Kernel::SuspendType::Debug); } } @@ -292,7 +296,7 @@ private: } thread.SetStepState(Kernel::StepState::NotStepping); - thread.Resume(system.Kernel(), Kernel::SuspendType::Debug); + thread.Resume(Kernel::SuspendType::Debug); } } @@ -308,7 +312,7 @@ private: } thread->SetStepState(Kernel::StepState::NotStepping); - thread->Resume(system.Kernel(), Kernel::SuspendType::Debug); + thread->Resume(Kernel::SuspendType::Debug); } } @@ -328,7 +332,7 @@ private: return; } } - state->active_thread = {system.Kernel(), std::addressof(threads.front())}; + state->active_thread = std::addressof(threads.front()); } private: @@ -350,20 +354,13 @@ private: std::mutex connection_lock; struct ConnectionState { + boost::asio::ip::tcp::socket client_socket; #ifdef USE_BOOST_v1 - using async_pipe = boost::process::v1::async_pipe; + boost::process::v1::async_pipe signal_pipe; #else - using async_pipe = boost::process::async_pipe; + boost::process::async_pipe signal_pipe; #endif - ConnectionState(boost::asio::ip::tcp::socket&& client_socket_, async_pipe signal_pipe_, Kernel::KernelCore& kernel) - : client_socket{std::move(client_socket_)} - , signal_pipe{signal_pipe_} - , active_thread{kernel, nullptr} - {} - - boost::asio::ip::tcp::socket client_socket; - async_pipe signal_pipe; SignalInfo info; Kernel::KScopedAutoObject active_thread; std::array client_data; diff --git a/src/core/debugger/gdbstub.cpp b/src/core/debugger/gdbstub.cpp index 44ddf11c39..5d61c819f8 100644 --- a/src/core/debugger/gdbstub.cpp +++ b/src/core/debugger/gdbstub.cpp @@ -323,13 +323,13 @@ void GDBStub::HandleBreakpointInsert(std::string_view command) { success = true; break; case BreakpointType::WriteWatch: - success = debug_process->InsertWatchpoint(system.Kernel(), addr, size, Kernel::DebugWatchpointType::Write); + success = debug_process->InsertWatchpoint(addr, size, Kernel::DebugWatchpointType::Write); break; case BreakpointType::ReadWatch: - success = debug_process->InsertWatchpoint(system.Kernel(), addr, size, Kernel::DebugWatchpointType::Read); + success = debug_process->InsertWatchpoint(addr, size, Kernel::DebugWatchpointType::Read); break; case BreakpointType::AccessWatch: - success = debug_process->InsertWatchpoint(system.Kernel(), addr, size, Kernel::DebugWatchpointType::ReadOrWrite); + success = debug_process->InsertWatchpoint(addr, size, Kernel::DebugWatchpointType::ReadOrWrite); break; case BreakpointType::Hardware: default: @@ -368,13 +368,13 @@ void GDBStub::HandleBreakpointRemove(std::string_view sv) { break; } case BreakpointType::WriteWatch: - success = debug_process->RemoveWatchpoint(system.Kernel(), addr, size, Kernel::DebugWatchpointType::Write); + success = debug_process->RemoveWatchpoint(addr, size, Kernel::DebugWatchpointType::Write); break; case BreakpointType::ReadWatch: - success = debug_process->RemoveWatchpoint(system.Kernel(), addr, size, Kernel::DebugWatchpointType::Read); + success = debug_process->RemoveWatchpoint(addr, size, Kernel::DebugWatchpointType::Read); break; case BreakpointType::AccessWatch: - success = debug_process->RemoveWatchpoint(system.Kernel(), addr, size, Kernel::DebugWatchpointType::ReadOrWrite); + success = debug_process->RemoveWatchpoint(addr, size, Kernel::DebugWatchpointType::ReadOrWrite); break; case BreakpointType::Hardware: default: diff --git a/src/core/hle/kernel/global_scheduler_context.cpp b/src/core/hle/kernel/global_scheduler_context.cpp index 6d1cd030e0..855a8226ef 100644 --- a/src/core/hle/kernel/global_scheduler_context.cpp +++ b/src/core/hle/kernel/global_scheduler_context.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project @@ -17,8 +17,7 @@ namespace Kernel { GlobalSchedulerContext::GlobalSchedulerContext(KernelCore& kernel) - : m_scheduler_lock{kernel} -{} + : m_kernel{kernel}, m_scheduler_lock{kernel} {} GlobalSchedulerContext::~GlobalSchedulerContext() = default; @@ -38,7 +37,7 @@ void GlobalSchedulerContext::RemoveThread(KThread* thread) noexcept { /// and then does some core rebalancing. Preemption priorities can be found /// in the array 'preemption_priorities'. /// @note This operation happens every 10ms. -void GlobalSchedulerContext::PreemptThreads(KernelCore& kernel) noexcept { +void GlobalSchedulerContext::PreemptThreads() noexcept { // The priority levels at which the global scheduler preempts threads every 10 ms. They are // ordered from Core 0 to Core 3. static constexpr std::array per_core{ @@ -47,9 +46,9 @@ void GlobalSchedulerContext::PreemptThreads(KernelCore& kernel) noexcept { 59, 63, }; - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); for (u32 core_id = 0; core_id < per_core.size(); core_id++) - KScheduler::RotateScheduledQueue(kernel, core_id, per_core[core_id]); + KScheduler::RotateScheduledQueue(m_kernel, core_id, per_core[core_id]); } /// @brief Returns true if the global scheduler lock is acquired @@ -70,11 +69,11 @@ void GlobalSchedulerContext::UnregisterDummyThreadForWakeup(KThread* thread) noe } } -void GlobalSchedulerContext::WakeupWaitingDummyThreads(KernelCore& kernel) noexcept { +void GlobalSchedulerContext::WakeupWaitingDummyThreads() noexcept { ASSERT(this->IsLocked()); if (m_woken_dummy_threads.size() > 0) { for (auto* thread : m_woken_dummy_threads) - thread->DummyThreadEndWait(kernel); + thread->DummyThreadEndWait(); m_woken_dummy_threads.clear(); } } diff --git a/src/core/hle/kernel/global_scheduler_context.h b/src/core/hle/kernel/global_scheduler_context.h index dd53477d2d..64aee86af8 100644 --- a/src/core/hle/kernel/global_scheduler_context.h +++ b/src/core/hle/kernel/global_scheduler_context.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project @@ -50,16 +50,17 @@ public: } void AddThread(KThread* thread) noexcept; void RemoveThread(KThread* thread) noexcept; - void PreemptThreads(KernelCore& kernel) noexcept; + void PreemptThreads() noexcept; bool IsLocked() const noexcept; void UnregisterDummyThreadForWakeup(KThread* thread) noexcept; void RegisterDummyThreadForWakeup(KThread* thread) noexcept; - void WakeupWaitingDummyThreads(KernelCore& kernel) noexcept; + void WakeupWaitingDummyThreads() noexcept; private: friend class KScopedSchedulerLock; friend class KScopedSchedulerLockAndSleep; + KernelCore& m_kernel; std::atomic_bool m_scheduler_update_needed{}; KSchedulerPriorityQueue m_priority_queue; LockType m_scheduler_lock; diff --git a/src/core/hle/kernel/init/init_slab_setup.cpp b/src/core/hle/kernel/init/init_slab_setup.cpp index 5dd8afaf96..a0e20bbbb4 100644 --- a/src/core/hle/kernel/init/init_slab_setup.cpp +++ b/src/core/hle/kernel/init/init_slab_setup.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -284,7 +281,7 @@ void KPageBufferSlabHeap::Initialize(Core::System& system) { // Reserve memory from the system resource limit. ASSERT( - kernel.GetSystemResourceLimit()->Reserve(kernel, LimitableResource::PhysicalMemoryMax, slab_size)); + kernel.GetSystemResourceLimit()->Reserve(LimitableResource::PhysicalMemoryMax, slab_size)); // Allocate memory for the slab. constexpr auto AllocateOption = KMemoryManager::EncodeOption( diff --git a/src/core/hle/kernel/k_address_arbiter.cpp b/src/core/hle/kernel/k_address_arbiter.cpp index 02634f8721..48889253dc 100644 --- a/src/core/hle/kernel/k_address_arbiter.cpp +++ b/src/core/hle/kernel/k_address_arbiter.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -19,9 +16,8 @@ namespace Kernel { -KAddressArbiter::KAddressArbiter(Core::System& system_) - : system{system_} -{} +KAddressArbiter::KAddressArbiter(Core::System& system) + : m_system{system}, m_kernel{system.Kernel()} {} KAddressArbiter::~KAddressArbiter() = default; namespace { @@ -116,7 +112,7 @@ public: explicit ThreadQueueImplForKAddressArbiter(KernelCore& kernel, KAddressArbiter::ThreadTree* t) : KThreadQueue(kernel), m_tree(t) {} - void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { + void CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { // If the thread is waiting on an address arbiter, remove it from the tree. if (waiting_thread->IsWaitingForAddressArbiter()) { m_tree->erase(m_tree->iterator_to(*waiting_thread)); @@ -124,7 +120,7 @@ public: } // Invoke the base cancel wait handler. - KThreadQueue::CancelWait(kernel, waiting_thread, wait_result, cancel_timer_task); + KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); } private: @@ -137,14 +133,14 @@ Result KAddressArbiter::Signal(uint64_t addr, s32 count) { // Perform signaling. s32 num_waiters{}; { - KScopedSchedulerLock sl(system.Kernel()); + KScopedSchedulerLock sl(m_kernel); auto it = m_tree.nfind_key({addr, -1}); while ((it != m_tree.end()) && (count <= 0 || num_waiters < count) && (it->GetAddressArbiterKey() == addr)) { // End the thread's wait. KThread* target_thread = std::addressof(*it); - target_thread->EndWait(system.Kernel(), ResultSuccess); + target_thread->EndWait(ResultSuccess); ASSERT(target_thread->IsWaitingForAddressArbiter()); target_thread->ClearAddressArbiter(); @@ -160,11 +156,11 @@ Result KAddressArbiter::SignalAndIncrementIfEqual(uint64_t addr, s32 value, s32 // Perform signaling. s32 num_waiters{}; { - KScopedSchedulerLock sl(system.Kernel()); + KScopedSchedulerLock sl(m_kernel); // Check the userspace value. s32 user_value{}; - R_UNLESS(UpdateIfEqual(system.Kernel(), std::addressof(user_value), addr, value, value + 1), + R_UNLESS(UpdateIfEqual(m_kernel, std::addressof(user_value), addr, value, value + 1), ResultInvalidCurrentMemory); R_UNLESS(user_value == value, ResultInvalidState); @@ -173,7 +169,7 @@ Result KAddressArbiter::SignalAndIncrementIfEqual(uint64_t addr, s32 value, s32 (it->GetAddressArbiterKey() == addr)) { // End the thread's wait. KThread* target_thread = std::addressof(*it); - target_thread->EndWait(system.Kernel(), ResultSuccess); + target_thread->EndWait(ResultSuccess); ASSERT(target_thread->IsWaitingForAddressArbiter()); target_thread->ClearAddressArbiter(); @@ -189,7 +185,7 @@ Result KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(uint64_t addr, s32 // Perform signaling. s32 num_waiters{}; { - KScopedSchedulerLock sl(system.Kernel()); + KScopedSchedulerLock sl(m_kernel); auto it = m_tree.nfind_key({addr, -1}); // Determine the updated value. @@ -224,9 +220,9 @@ Result KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(uint64_t addr, s32 s32 user_value{}; bool succeeded{}; if (value != new_value) { - succeeded = UpdateIfEqual(system.Kernel(), std::addressof(user_value), addr, value, new_value); + succeeded = UpdateIfEqual(m_kernel, std::addressof(user_value), addr, value, new_value); } else { - succeeded = ReadFromUser(system.Kernel(), std::addressof(user_value), addr); + succeeded = ReadFromUser(m_kernel, std::addressof(user_value), addr); } R_UNLESS(succeeded, ResultInvalidCurrentMemory); @@ -236,7 +232,7 @@ Result KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(uint64_t addr, s32 (it->GetAddressArbiterKey() == addr)) { // End the thread's wait. KThread* target_thread = std::addressof(*it); - target_thread->EndWait(system.Kernel(), ResultSuccess); + target_thread->EndWait(ResultSuccess); ASSERT(target_thread->IsWaitingForAddressArbiter()); target_thread->ClearAddressArbiter(); @@ -250,12 +246,12 @@ Result KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(uint64_t addr, s32 Result KAddressArbiter::WaitIfLessThan(uint64_t addr, s32 value, bool decrement, s64 timeout) { // Prepare to wait. - KThread* cur_thread = GetCurrentThreadPointer(system.Kernel()); + KThread* cur_thread = GetCurrentThreadPointer(m_kernel); KHardwareTimer* timer{}; - ThreadQueueImplForKAddressArbiter wait_queue(system.Kernel(), std::addressof(m_tree)); + ThreadQueueImplForKAddressArbiter wait_queue(m_kernel, std::addressof(m_tree)); { - KScopedSchedulerLockAndSleep slp{system.Kernel(), std::addressof(timer), cur_thread, timeout}; + KScopedSchedulerLockAndSleep slp{m_kernel, std::addressof(timer), cur_thread, timeout}; // Check that the thread isn't terminating. if (cur_thread->IsTerminationRequested()) { @@ -267,9 +263,9 @@ Result KAddressArbiter::WaitIfLessThan(uint64_t addr, s32 value, bool decrement, s32 user_value{}; bool succeeded{}; if (decrement) { - succeeded = DecrementIfLessThan(system.Kernel(), std::addressof(user_value), addr, value); + succeeded = DecrementIfLessThan(m_kernel, std::addressof(user_value), addr, value); } else { - succeeded = ReadFromUser(system.Kernel(), std::addressof(user_value), addr); + succeeded = ReadFromUser(m_kernel, std::addressof(user_value), addr); } if (!succeeded) { @@ -295,7 +291,7 @@ Result KAddressArbiter::WaitIfLessThan(uint64_t addr, s32 value, bool decrement, // Wait for the thread to finish. wait_queue.SetHardwareTimer(timer); - cur_thread->BeginWait(system.Kernel(), std::addressof(wait_queue)); + cur_thread->BeginWait(std::addressof(wait_queue)); cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); } @@ -305,12 +301,12 @@ Result KAddressArbiter::WaitIfLessThan(uint64_t addr, s32 value, bool decrement, Result KAddressArbiter::WaitIfEqual(uint64_t addr, s32 value, s64 timeout) { // Prepare to wait. - KThread* cur_thread = GetCurrentThreadPointer(system.Kernel()); + KThread* cur_thread = GetCurrentThreadPointer(m_kernel); KHardwareTimer* timer{}; - ThreadQueueImplForKAddressArbiter wait_queue(system.Kernel(), std::addressof(m_tree)); + ThreadQueueImplForKAddressArbiter wait_queue(m_kernel, std::addressof(m_tree)); { - KScopedSchedulerLockAndSleep slp{system.Kernel(), std::addressof(timer), cur_thread, timeout}; + KScopedSchedulerLockAndSleep slp{m_kernel, std::addressof(timer), cur_thread, timeout}; // Check that the thread isn't terminating. if (cur_thread->IsTerminationRequested()) { @@ -320,7 +316,7 @@ Result KAddressArbiter::WaitIfEqual(uint64_t addr, s32 value, s64 timeout) { // Read the value from userspace. s32 user_value{}; - if (!ReadFromUser(system.Kernel(), std::addressof(user_value), addr)) { + if (!ReadFromUser(m_kernel, std::addressof(user_value), addr)) { slp.CancelSleep(); R_THROW(ResultInvalidCurrentMemory); } @@ -343,7 +339,7 @@ Result KAddressArbiter::WaitIfEqual(uint64_t addr, s32 value, s64 timeout) { // Wait for the thread to finish. wait_queue.SetHardwareTimer(timer); - cur_thread->BeginWait(system.Kernel(), std::addressof(wait_queue)); + cur_thread->BeginWait(std::addressof(wait_queue)); cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); } diff --git a/src/core/hle/kernel/k_address_arbiter.h b/src/core/hle/kernel/k_address_arbiter.h index b3afe19476..3b70e1ab28 100644 --- a/src/core/hle/kernel/k_address_arbiter.h +++ b/src/core/hle/kernel/k_address_arbiter.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -63,7 +60,8 @@ private: private: ThreadTree m_tree; - Core::System& system; + Core::System& m_system; + KernelCore& m_kernel; }; } // namespace Kernel diff --git a/src/core/hle/kernel/k_auto_object.cpp b/src/core/hle/kernel/k_auto_object.cpp index 14d1c4624d..a7a46d29bb 100644 --- a/src/core/hle/kernel/k_auto_object.cpp +++ b/src/core/hle/kernel/k_auto_object.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project @@ -15,8 +15,8 @@ KAutoObject* KAutoObject::Create(KAutoObject* obj) { return obj; } -void KAutoObject::RegisterWithKernel(KernelCore& kernel) { - kernel.RegisterKernelObject(this); +void KAutoObject::RegisterWithKernel() { + m_kernel.RegisterKernelObject(this); } void KAutoObject::UnregisterWithKernel(KernelCore& kernel, KAutoObject* self) { diff --git a/src/core/hle/kernel/k_auto_object.h b/src/core/hle/kernel/k_auto_object.h index 392b9c9f1d..5e8c0030ce 100644 --- a/src/core/hle/kernel/k_auto_object.h +++ b/src/core/hle/kernel/k_auto_object.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project @@ -87,21 +87,21 @@ private: KERNEL_AUTOOBJECT_TRAITS_IMPL(KAutoObject, KAutoObject, const); public: - explicit KAutoObject(KernelCore& kernel) { + explicit KAutoObject(KernelCore& kernel) : m_kernel(kernel) { m_class_token = GetStaticTypeObj().GetClassToken(); - RegisterWithKernel(kernel); + RegisterWithKernel(); } virtual ~KAutoObject() = default; static KAutoObject* Create(KAutoObject* ptr); // Destroy is responsible for destroying the auto object's resources when ref_count hits zero. - virtual void Destroy(KernelCore& kernel) { + virtual void Destroy() { UNIMPLEMENTED(); } // Finalize is responsible for cleaning up resource, but does not destroy the object. - virtual void Finalize(KernelCore& kernel) {} + virtual void Finalize() {} virtual KProcess* GetOwner() const { return nullptr; @@ -123,50 +123,67 @@ public: Derived DynamicCast() { static_assert(std::is_pointer_v); using DerivedType = std::remove_pointer_t; - if (this->IsDerivedFrom(DerivedType::GetStaticTypeObj())) - return Derived(this); - return nullptr; + + if (this->IsDerivedFrom(DerivedType::GetStaticTypeObj())) { + return static_cast(this); + } else { + return nullptr; + } } template const Derived DynamicCast() const { static_assert(std::is_pointer_v); using DerivedType = std::remove_pointer_t; - if (this->IsDerivedFrom(DerivedType::GetStaticTypeObj())) - return Derived(this); - return nullptr; + + if (this->IsDerivedFrom(DerivedType::GetStaticTypeObj())) { + return static_cast(this); + } else { + return nullptr; + } } - bool Open(KernelCore& kernel) { + bool Open() { // Atomically increment the reference count, only if it's positive. u32 cur_ref_count = m_ref_count.load(std::memory_order_acquire); do { - if (cur_ref_count == 0) + if (cur_ref_count == 0) { return false; + } ASSERT(cur_ref_count < cur_ref_count + 1); - } while (!m_ref_count.compare_exchange_weak(cur_ref_count, cur_ref_count + 1, std::memory_order_relaxed)); + } while (!m_ref_count.compare_exchange_weak(cur_ref_count, cur_ref_count + 1, + std::memory_order_relaxed)); + return true; } - void Close(KernelCore& kernel) { + void Close() { // Atomically decrement the reference count, not allowing it to become negative. u32 cur_ref_count = m_ref_count.load(std::memory_order_acquire); do { - if (cur_ref_count == 0) + if (cur_ref_count == 0) { return; + } ASSERT(cur_ref_count > 0); - } while (!m_ref_count.compare_exchange_weak(cur_ref_count, cur_ref_count - 1, std::memory_order_acq_rel)); + } while (!m_ref_count.compare_exchange_weak(cur_ref_count, cur_ref_count - 1, + std::memory_order_acq_rel)); + // If ref count hits 1, destroy the object. if (cur_ref_count == 1) { - this->Destroy(kernel); + KernelCore& kernel = m_kernel; + this->Destroy(); KAutoObject::UnregisterWithKernel(kernel, this); } } private: - void RegisterWithKernel(KernelCore& kernel); + void RegisterWithKernel(); static void UnregisterWithKernel(KernelCore& kernel, KAutoObject* self); +protected: + KernelCore& m_kernel; + +private: std::atomic m_ref_count{}; ClassTokenType m_class_token{}; }; @@ -208,22 +225,17 @@ class KScopedAutoObject { public: YUZU_NON_COPYABLE(KScopedAutoObject); - constexpr KScopedAutoObject(KernelCore& kernel_) - : kernel{kernel_} - {} + constexpr KScopedAutoObject() = default; - constexpr KScopedAutoObject(KernelCore& kernel_, T* o) - : kernel{kernel_} - , m_obj(o) - { + constexpr KScopedAutoObject(T* o) : m_obj(o) { if (m_obj != nullptr) { - m_obj->Open(kernel); + m_obj->Open(); } } ~KScopedAutoObject() { if (m_obj != nullptr) { - m_obj->Close(kernel); + m_obj->Close(); } m_obj = nullptr; } @@ -241,7 +253,7 @@ public: if (rhs.m_obj != nullptr) { derived = rhs.m_obj->template DynamicCast(); if (derived == nullptr) { - rhs.m_obj->Close(rhs.kernel); + rhs.m_obj->Close(); } } @@ -262,16 +274,8 @@ public: return *m_obj; } - constexpr void SetObject(T* o) { - if (m_obj) - m_obj->Close(kernel); - m_obj = o; - if (m_obj) - m_obj->Open(kernel); - } - constexpr void Reset(T* o) { - KScopedAutoObject(kernel, o).Swap(*this); + KScopedAutoObject(o).Swap(*this); } constexpr T* GetPointerUnsafe() { @@ -300,7 +304,6 @@ private: friend class KScopedAutoObject; private: - KernelCore& kernel; T* m_obj{}; private: diff --git a/src/core/hle/kernel/k_client_port.cpp b/src/core/hle/kernel/k_client_port.cpp index d13995988c..68cea978a0 100644 --- a/src/core/hle/kernel/k_client_port.cpp +++ b/src/core/hle/kernel/k_client_port.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: 2021 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -18,7 +15,7 @@ namespace Kernel { KClientPort::KClientPort(KernelCore& kernel) : KSynchronizationObject{kernel} {} KClientPort::~KClientPort() = default; -void KClientPort::Initialize(KernelCore& kernel, KPort* parent, s32 max_sessions) { +void KClientPort::Initialize(KPort* parent, s32 max_sessions) { // Set member variables. m_num_sessions = 0; m_peak_sessions = 0; @@ -26,48 +23,48 @@ void KClientPort::Initialize(KernelCore& kernel, KPort* parent, s32 max_sessions m_max_sessions = max_sessions; } -void KClientPort::OnSessionFinalized(KernelCore& kernel) { - KScopedSchedulerLock sl{kernel}; +void KClientPort::OnSessionFinalized() { + KScopedSchedulerLock sl{m_kernel}; if (const auto prev = m_num_sessions--; prev == m_max_sessions) { - this->NotifyAvailable(kernel); + this->NotifyAvailable(); } } -void KClientPort::OnServerClosed(KernelCore& kernel) {} +void KClientPort::OnServerClosed() {} -bool KClientPort::IsLight(KernelCore& kernel) const { +bool KClientPort::IsLight() const { return this->GetParent()->IsLight(); } -bool KClientPort::IsServerClosed(KernelCore& kernel) const { - return this->GetParent()->IsServerClosed(kernel); +bool KClientPort::IsServerClosed() const { + return this->GetParent()->IsServerClosed(); } -void KClientPort::Destroy(KernelCore& kernel) { +void KClientPort::Destroy() { // Note with our parent that we're closed. - m_parent->OnClientClosed(kernel); + m_parent->OnClientClosed(); // Close our reference to our parent. - m_parent->Close(kernel); + m_parent->Close(); } -bool KClientPort::IsSignaled(KernelCore& kernel) const { +bool KClientPort::IsSignaled() const { return m_num_sessions.load() < m_max_sessions; } -Result KClientPort::CreateSession(KernelCore& kernel, KClientSession** out) { +Result KClientPort::CreateSession(KClientSession** out) { // Declare the session we're going to allocate. KSession* session{}; // Reserve a new session from the resource limit. - KScopedResourceReservation session_reservation(kernel, GetCurrentProcessPointer(kernel), + KScopedResourceReservation session_reservation(GetCurrentProcessPointer(m_kernel), LimitableResource::SessionCountMax); R_UNLESS(session_reservation.Succeeded(), ResultLimitReached); // Allocate a session normally. // TODO: Dynamic resource limits - session = KSession::Create(kernel); + session = KSession::Create(m_kernel); // Check that we successfully created a session. R_UNLESS(session != nullptr, ResultOutOfResource); @@ -75,7 +72,7 @@ Result KClientPort::CreateSession(KernelCore& kernel, KClientSession** out) { // Update the session counts. { ON_RESULT_FAILURE { - session->Close(kernel); + session->Close(); }; // Atomically increment the number of sessions. @@ -103,37 +100,38 @@ Result KClientPort::CreateSession(KernelCore& kernel, KClientSession** out) { } // Initialize the session. - session->Initialize(kernel, this, m_parent->GetName()); + session->Initialize(this, m_parent->GetName()); // Commit the session reservation. session_reservation.Commit(); // Register the session. - KSession::Register(kernel, session); + KSession::Register(m_kernel, session); ON_RESULT_FAILURE { - session->GetClientSession().Close(kernel); - session->GetServerSession().Close(kernel); + session->GetClientSession().Close(); + session->GetServerSession().Close(); }; // Enqueue the session with our parent. - R_TRY(m_parent->EnqueueSession(kernel, std::addressof(session->GetServerSession()))); + R_TRY(m_parent->EnqueueSession(std::addressof(session->GetServerSession()))); // We succeeded, so set the output. *out = std::addressof(session->GetClientSession()); R_SUCCEED(); } -Result KClientPort::CreateLightSession(KernelCore& kernel, KLightClientSession** out) { +Result KClientPort::CreateLightSession(KLightClientSession** out) { // Declare the session we're going to allocate. KLightSession* session{}; // Reserve a new session from the resource limit. - KScopedResourceReservation session_reservation(kernel, GetCurrentProcessPointer(kernel), Svc::LimitableResource::SessionCountMax); + KScopedResourceReservation session_reservation(GetCurrentProcessPointer(m_kernel), + Svc::LimitableResource::SessionCountMax); R_UNLESS(session_reservation.Succeeded(), ResultLimitReached); // Allocate a session normally. // TODO: Dynamic resource limits - session = KLightSession::Create(kernel); + session = KLightSession::Create(m_kernel); // Check that we successfully created a session. R_UNLESS(session != nullptr, ResultOutOfResource); @@ -141,7 +139,7 @@ Result KClientPort::CreateLightSession(KernelCore& kernel, KLightClientSession** // Update the session counts. { ON_RESULT_FAILURE { - session->Close(kernel); + session->Close(); }; // Atomically increment the number of sessions. @@ -169,20 +167,20 @@ Result KClientPort::CreateLightSession(KernelCore& kernel, KLightClientSession** } // Initialize the session. - session->Initialize(kernel, this, m_parent->GetName()); + session->Initialize(this, m_parent->GetName()); // Commit the session reservation. session_reservation.Commit(); // Register the session. - KLightSession::Register(kernel, session); + KLightSession::Register(m_kernel, session); ON_RESULT_FAILURE { - session->GetClientSession().Close(kernel); - session->GetServerSession().Close(kernel); + session->GetClientSession().Close(); + session->GetServerSession().Close(); }; // Enqueue the session with our parent. - R_TRY(m_parent->EnqueueSession(kernel, std::addressof(session->GetServerSession()))); + R_TRY(m_parent->EnqueueSession(std::addressof(session->GetServerSession()))); // We succeeded, so set the output. *out = std::addressof(session->GetClientSession()); diff --git a/src/core/hle/kernel/k_client_port.h b/src/core/hle/kernel/k_client_port.h index 3e48eeaa00..28b3326081 100644 --- a/src/core/hle/kernel/k_client_port.h +++ b/src/core/hle/kernel/k_client_port.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: 2016 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -26,9 +23,9 @@ public: explicit KClientPort(KernelCore& kernel); ~KClientPort() override; - void Initialize(KernelCore& kernel, KPort* parent, s32 max_sessions); - void OnSessionFinalized(KernelCore& kernel); - void OnServerClosed(KernelCore& kernel); + void Initialize(KPort* parent, s32 max_sessions); + void OnSessionFinalized(); + void OnServerClosed(); const KPort* GetParent() const { return m_parent; @@ -47,15 +44,15 @@ public: return m_max_sessions; } - bool IsLight(KernelCore& kernel) const; - bool IsServerClosed(KernelCore& kernel) const; + bool IsLight() const; + bool IsServerClosed() const; // Overridden virtual functions. - void Destroy(KernelCore& kernel) override; - bool IsSignaled(KernelCore& kernel) const override; + void Destroy() override; + bool IsSignaled() const override; - Result CreateSession(KernelCore& kernel, KClientSession** out); - Result CreateLightSession(KernelCore& kernel, KLightClientSession** out); + Result CreateSession(KClientSession** out); + Result CreateLightSession(KLightClientSession** out); private: std::atomic m_num_sessions{}; diff --git a/src/core/hle/kernel/k_client_session.cpp b/src/core/hle/kernel/k_client_session.cpp index 95cb9896b9..3e01e3b67f 100644 --- a/src/core/hle/kernel/k_client_session.cpp +++ b/src/core/hle/kernel/k_client_session.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -16,41 +13,41 @@ namespace Kernel { KClientSession::KClientSession(KernelCore& kernel) : KAutoObject{kernel} {} KClientSession::~KClientSession() = default; -void KClientSession::Destroy(KernelCore& kernel) { - m_parent->OnClientClosed(kernel); - m_parent->Close(kernel); +void KClientSession::Destroy() { + m_parent->OnClientClosed(); + m_parent->Close(); } void KClientSession::OnServerClosed() {} -Result KClientSession::SendSyncRequest(KernelCore& kernel, uintptr_t address, size_t size) { +Result KClientSession::SendSyncRequest(uintptr_t address, size_t size) { // Create a session request. - KSessionRequest* request = KSessionRequest::Create(kernel); + KSessionRequest* request = KSessionRequest::Create(m_kernel); R_UNLESS(request != nullptr, ResultOutOfResource); SCOPE_EXIT { - request->Close(kernel); + request->Close(); }; // Initialize the request. - request->Initialize(kernel, nullptr, address, size); + request->Initialize(nullptr, address, size); // Send the request. - R_RETURN(m_parent->OnRequest(kernel, request)); + R_RETURN(m_parent->OnRequest(request)); } -Result KClientSession::SendAsyncRequest(KernelCore& kernel, KEvent* event, uintptr_t address, size_t size) { +Result KClientSession::SendAsyncRequest(KEvent* event, uintptr_t address, size_t size) { // Create a session request. - KSessionRequest* request = KSessionRequest::Create(kernel); + KSessionRequest* request = KSessionRequest::Create(m_kernel); R_UNLESS(request != nullptr, ResultOutOfResource); SCOPE_EXIT { - request->Close(kernel); + request->Close(); }; // Initialize the request. - request->Initialize(kernel, event, address, size); + request->Initialize(event, address, size); // Send the request. - R_RETURN(m_parent->OnRequest(kernel, request)); + R_RETURN(m_parent->OnRequest(request)); } } // namespace Kernel diff --git a/src/core/hle/kernel/k_client_session.h b/src/core/hle/kernel/k_client_session.h index 876c3fc789..a39213e17f 100644 --- a/src/core/hle/kernel/k_client_session.h +++ b/src/core/hle/kernel/k_client_session.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -29,14 +26,14 @@ public: m_parent = parent; } - void Destroy(KernelCore& kernel) override; + void Destroy() override; KSession* GetParent() const { return m_parent; } - Result SendSyncRequest(KernelCore& kernel, uintptr_t address, size_t size); - Result SendAsyncRequest(KernelCore& kernel, KEvent* event, uintptr_t address, size_t size); + Result SendSyncRequest(uintptr_t address, size_t size); + Result SendAsyncRequest(KEvent* event, uintptr_t address, size_t size); void OnServerClosed(); diff --git a/src/core/hle/kernel/k_code_memory.cpp b/src/core/hle/kernel/k_code_memory.cpp index aa8edce832..7454be55c9 100644 --- a/src/core/hle/kernel/k_code_memory.cpp +++ b/src/core/hle/kernel/k_code_memory.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -22,15 +19,16 @@ namespace Kernel { KCodeMemory::KCodeMemory(KernelCore& kernel) : KAutoObjectWithSlabHeapAndContainer{kernel}, m_lock(kernel) {} -Result KCodeMemory::Initialize(KernelCore& kernel, Core::DeviceMemory& device_memory, KProcessAddress addr, size_t size) { +Result KCodeMemory::Initialize(Core::DeviceMemory& device_memory, KProcessAddress addr, + size_t size) { // Set members. - m_owner = GetCurrentProcessPointer(kernel); + m_owner = GetCurrentProcessPointer(m_kernel); // Get the owner page table. auto& page_table = m_owner->GetPageTable(); // Construct the page group. - m_page_group.emplace(kernel, page_table.GetBlockInfoManager()); + m_page_group.emplace(m_kernel, page_table.GetBlockInfoManager()); // Lock the memory. R_TRY(page_table.LockForCodeMemory(std::addressof(*m_page_group), addr, size)) @@ -41,7 +39,7 @@ Result KCodeMemory::Initialize(KernelCore& kernel, Core::DeviceMemory& device_me } // Set remaining tracking members. - m_owner->Open(kernel); + m_owner->Open(); m_address = addr; m_is_initialized = true; m_is_owner_mapped = false; @@ -51,7 +49,7 @@ Result KCodeMemory::Initialize(KernelCore& kernel, Core::DeviceMemory& device_me R_SUCCEED(); } -void KCodeMemory::Finalize(KernelCore& kernel) { +void KCodeMemory::Finalize() { // Unlock. if (!m_is_mapped && !m_is_owner_mapped) { const size_t size = m_page_group->GetNumPages() * PageSize; @@ -59,14 +57,14 @@ void KCodeMemory::Finalize(KernelCore& kernel) { } // Close the page group. - m_page_group->Close(kernel); + m_page_group->Close(); m_page_group->Finalize(); // Close our reference to our owner. - m_owner->Close(kernel); + m_owner->Close(); } -Result KCodeMemory::Map(KernelCore& kernel, KProcessAddress address, size_t size) { +Result KCodeMemory::Map(KProcessAddress address, size_t size) { // Validate the size. R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); @@ -77,7 +75,7 @@ Result KCodeMemory::Map(KernelCore& kernel, KProcessAddress address, size_t size R_UNLESS(!m_is_mapped, ResultInvalidState); // Map the memory. - R_TRY(GetCurrentProcess(kernel).GetPageTable().MapPageGroup( + R_TRY(GetCurrentProcess(m_kernel).GetPageTable().MapPageGroup( address, *m_page_group, KMemoryState::CodeOut, KMemoryPermission::UserReadWrite)); // Mark ourselves as mapped. @@ -86,7 +84,7 @@ Result KCodeMemory::Map(KernelCore& kernel, KProcessAddress address, size_t size R_SUCCEED(); } -Result KCodeMemory::Unmap(KernelCore& kernel, KProcessAddress address, size_t size) { +Result KCodeMemory::Unmap(KProcessAddress address, size_t size) { // Validate the size. R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); @@ -94,7 +92,7 @@ Result KCodeMemory::Unmap(KernelCore& kernel, KProcessAddress address, size_t si KScopedLightLock lk(m_lock); // Unmap the memory. - R_TRY(GetCurrentProcess(kernel).GetPageTable().UnmapPageGroup(address, *m_page_group, + R_TRY(GetCurrentProcess(m_kernel).GetPageTable().UnmapPageGroup(address, *m_page_group, KMemoryState::CodeOut)); // Mark ourselves as unmapped. @@ -103,7 +101,7 @@ Result KCodeMemory::Unmap(KernelCore& kernel, KProcessAddress address, size_t si R_SUCCEED(); } -Result KCodeMemory::MapToOwner(KernelCore& kernel, KProcessAddress address, size_t size, Svc::MemoryPermission perm) { +Result KCodeMemory::MapToOwner(KProcessAddress address, size_t size, Svc::MemoryPermission perm) { // Validate the size. R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); @@ -137,7 +135,7 @@ Result KCodeMemory::MapToOwner(KernelCore& kernel, KProcessAddress address, size R_SUCCEED(); } -Result KCodeMemory::UnmapFromOwner(KernelCore& kernel, KProcessAddress address, size_t size) { +Result KCodeMemory::UnmapFromOwner(KProcessAddress address, size_t size) { // Validate the size. R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); diff --git a/src/core/hle/kernel/k_code_memory.h b/src/core/hle/kernel/k_code_memory.h index 4f3aab6b4f..26fe6b3dc6 100644 --- a/src/core/hle/kernel/k_code_memory.h +++ b/src/core/hle/kernel/k_code_memory.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -34,18 +31,18 @@ class KCodeMemory final public: explicit KCodeMemory(KernelCore& kernel); - Result Initialize(KernelCore& kernel, Core::DeviceMemory& device_memory, KProcessAddress address, size_t size); - void Finalize(KernelCore& kernel) override; + Result Initialize(Core::DeviceMemory& device_memory, KProcessAddress address, size_t size); + void Finalize() override; - Result Map(KernelCore& kernel, KProcessAddress address, size_t size); - Result Unmap(KernelCore& kernel, KProcessAddress address, size_t size); - Result MapToOwner(KernelCore& kernel, KProcessAddress address, size_t size, Svc::MemoryPermission perm); - Result UnmapFromOwner(KernelCore& kernel, KProcessAddress address, size_t size); + Result Map(KProcessAddress address, size_t size); + Result Unmap(KProcessAddress address, size_t size); + Result MapToOwner(KProcessAddress address, size_t size, Svc::MemoryPermission perm); + Result UnmapFromOwner(KProcessAddress address, size_t size); bool IsInitialized() const override { return m_is_initialized; } - static void PostDestroy(KernelCore& kernel, uintptr_t arg) {} + static void PostDestroy(uintptr_t arg) {} KProcess* GetOwner() const override { return m_owner; diff --git a/src/core/hle/kernel/k_condition_variable.cpp b/src/core/hle/kernel/k_condition_variable.cpp index 3cf8b28e17..1a7431df07 100644 --- a/src/core/hle/kernel/k_condition_variable.cpp +++ b/src/core/hle/kernel/k_condition_variable.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project @@ -66,15 +66,14 @@ bool UpdateLockAtomic(KernelCore& kernel, u32* out, KProcessAddress address, u32 class ThreadQueueImplForKConditionVariableWaitForAddress final : public KThreadQueue { public: explicit ThreadQueueImplForKConditionVariableWaitForAddress(KernelCore& kernel) - : KThreadQueue(kernel) - {} + : KThreadQueue(kernel) {} - virtual void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { + void CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { // Remove the thread as a waiter from its owner. - waiting_thread->GetLockOwner(kernel)->RemoveWaiter(kernel, waiting_thread); + waiting_thread->GetLockOwner()->RemoveWaiter(waiting_thread); // Invoke the base cancel wait handler. - KThreadQueue::CancelWait(kernel, waiting_thread, wait_result, cancel_timer_task); + KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); } }; @@ -83,15 +82,14 @@ private: KConditionVariable::ThreadTree* m_tree; public: - explicit ThreadQueueImplForKConditionVariableWaitConditionVariable(KernelCore& kernel, KConditionVariable::ThreadTree* t) - : KThreadQueue(kernel) - , m_tree(t) - {} + explicit ThreadQueueImplForKConditionVariableWaitConditionVariable( + KernelCore& kernel, KConditionVariable::ThreadTree* t) + : KThreadQueue(kernel), m_tree(t) {} - void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { + void CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { // Remove the thread as a waiter from its owner. - if (KThread* owner = waiting_thread->GetLockOwner(kernel); owner != nullptr) { - owner->RemoveWaiter(kernel, waiting_thread); + if (KThread* owner = waiting_thread->GetLockOwner(); owner != nullptr) { + owner->RemoveWaiter(waiting_thread); } // If the thread is waiting on a condvar, remove it from the tree. @@ -101,15 +99,14 @@ public: } // Invoke the base cancel wait handler. - KThreadQueue::CancelWait(kernel, waiting_thread, wait_result, cancel_timer_task); + KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); } }; } // namespace KConditionVariable::KConditionVariable(Core::System& system) - : m_system{system} -{} + : m_system{system}, m_kernel{system.Kernel()} {} KConditionVariable::~KConditionVariable() = default; @@ -122,7 +119,8 @@ Result KConditionVariable::SignalToAddress(KernelCore& kernel, KProcessAddress a // Remove waiter thread. bool has_waiters{}; - KThread* const next_owner_thread = owner_thread->RemoveUserWaiterByKey(kernel, std::addressof(has_waiters), addr); + KThread* const next_owner_thread = + owner_thread->RemoveUserWaiterByKey(std::addressof(has_waiters), addr); // Determine the next tag. u32 next_value{}; @@ -146,14 +144,15 @@ Result KConditionVariable::SignalToAddress(KernelCore& kernel, KProcessAddress a // If necessary, signal the next owner thread. if (next_owner_thread != nullptr) { - next_owner_thread->EndWait(kernel, result); + next_owner_thread->EndWait(result); } R_RETURN(result); } } -Result KConditionVariable::WaitForAddress(KernelCore& kernel, Handle handle, KProcessAddress addr, u32 value) { +Result KConditionVariable::WaitForAddress(KernelCore& kernel, Handle handle, KProcessAddress addr, + u32 value) { KThread* cur_thread = GetCurrentThreadPointer(kernel); ThreadQueueImplForKConditionVariableWaitForAddress wait_queue(kernel); @@ -174,30 +173,30 @@ Result KConditionVariable::WaitForAddress(KernelCore& kernel, Handle handle, KPr // Get the lock owner thread. owner_thread = GetCurrentProcess(kernel) - .GetHandleTable() - .GetObjectWithoutPseudoHandle(kernel, handle) - .ReleasePointerUnsafe(); + .GetHandleTable() + .GetObjectWithoutPseudoHandle(handle) + .ReleasePointerUnsafe(); R_UNLESS(owner_thread != nullptr, ResultInvalidHandle); // Update the lock. cur_thread->SetUserAddressKey(addr, value); - owner_thread->AddWaiter(kernel, cur_thread); + owner_thread->AddWaiter(cur_thread); // Begin waiting. - cur_thread->BeginWait(kernel, std::addressof(wait_queue)); + cur_thread->BeginWait(std::addressof(wait_queue)); cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::ConditionVar); } // Close our reference to the owner thread, now that the wait is over. - owner_thread->Close(kernel); + owner_thread->Close(); // Get the wait result. R_RETURN(cur_thread->GetWaitResult()); } -void KConditionVariable::SignalImpl(KernelCore& kernel, KThread* thread) { +void KConditionVariable::SignalImpl(KThread* thread) { // Check pre-conditions. - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); // Update the tag. KProcessAddress address = thread->GetAddressKey(); @@ -212,33 +211,35 @@ void KConditionVariable::SignalImpl(KernelCore& kernel, KThread* thread) { // TODO(bunnei): We should call CanAccessAtomic(..) here. can_access = true; if (can_access) { - UpdateLockAtomic(kernel, std::addressof(prev_tag), address, own_tag, Svc::HandleWaitMask); + UpdateLockAtomic(m_kernel, std::addressof(prev_tag), address, own_tag, + Svc::HandleWaitMask); } } if (can_access) { if (prev_tag == Svc::InvalidHandle) { // If nobody held the lock previously, we're all good. - thread->EndWait(kernel, ResultSuccess); + thread->EndWait(ResultSuccess); } else { // Get the previous owner. - KThread* owner_thread = GetCurrentProcess(kernel) - .GetHandleTable() - .GetObjectWithoutPseudoHandle(kernel, Handle(prev_tag & ~Svc::HandleWaitMask)) - .ReleasePointerUnsafe(); + KThread* owner_thread = GetCurrentProcess(m_kernel) + .GetHandleTable() + .GetObjectWithoutPseudoHandle( + static_cast(prev_tag & ~Svc::HandleWaitMask)) + .ReleasePointerUnsafe(); if (owner_thread) { // Add the thread as a waiter on the owner. - owner_thread->AddWaiter(kernel, thread); - owner_thread->Close(kernel); + owner_thread->AddWaiter(thread); + owner_thread->Close(); } else { // The lock was tagged with a thread that doesn't exist. - thread->EndWait(kernel, ResultInvalidState); + thread->EndWait(ResultInvalidState); } } } else { // If the address wasn't accessible, note so. - thread->EndWait(kernel, ResultInvalidCurrentMemory); + thread->EndWait(ResultInvalidCurrentMemory); } } @@ -246,16 +247,17 @@ void KConditionVariable::Signal(u64 cv_key, s32 count) { // Perform signaling. s32 num_waiters{}; { - KScopedSchedulerLock sl(m_system.Kernel()); + KScopedSchedulerLock sl(m_kernel); auto it = m_tree.nfind_key({cv_key, -1}); - while ((it != m_tree.end()) && (count <= 0 || num_waiters < count) && (it->GetConditionVariableKey() == cv_key)) { + while ((it != m_tree.end()) && (count <= 0 || num_waiters < count) && + (it->GetConditionVariableKey() == cv_key)) { KThread* target_thread = std::addressof(*it); it = m_tree.erase(it); target_thread->ClearConditionVariable(); - this->SignalImpl(m_system.Kernel(), target_thread); + this->SignalImpl(target_thread); ++num_waiters; } @@ -263,20 +265,20 @@ void KConditionVariable::Signal(u64 cv_key, s32 count) { // If we have no waiters, clear the has waiter flag. if (it == m_tree.end() || it->GetConditionVariableKey() != cv_key) { constexpr u32 HasNoWaiterFlag = 0; - WriteToUser(m_system.Kernel(), cv_key, HasNoWaiterFlag); + WriteToUser(m_kernel, cv_key, HasNoWaiterFlag); } } } Result KConditionVariable::Wait(KProcessAddress addr, u64 key, u32 value, s64 timeout) { // Prepare to wait. - KThread* cur_thread = GetCurrentThreadPointer(m_system.Kernel()); + KThread* cur_thread = GetCurrentThreadPointer(m_kernel); KHardwareTimer* timer{}; - ThreadQueueImplForKConditionVariableWaitConditionVariable wait_queue(m_system.Kernel(), + ThreadQueueImplForKConditionVariableWaitConditionVariable wait_queue(m_kernel, std::addressof(m_tree)); { - KScopedSchedulerLockAndSleep slp(m_system.Kernel(), std::addressof(timer), cur_thread, timeout); + KScopedSchedulerLockAndSleep slp(m_kernel, std::addressof(timer), cur_thread, timeout); // Check that the thread isn't terminating. if (cur_thread->IsTerminationRequested()) { @@ -289,7 +291,7 @@ Result KConditionVariable::Wait(KProcessAddress addr, u64 key, u32 value, s64 ti // Remove waiter thread. bool has_waiters{}; KThread* next_owner_thread = - cur_thread->RemoveUserWaiterByKey(m_system.Kernel(), std::addressof(has_waiters), addr); + cur_thread->RemoveUserWaiterByKey(std::addressof(has_waiters), addr); // Update for the next owner thread. u32 next_value{}; @@ -301,18 +303,18 @@ Result KConditionVariable::Wait(KProcessAddress addr, u64 key, u32 value, s64 ti } // Wake up the next owner. - next_owner_thread->EndWait(m_system.Kernel(), ResultSuccess); + next_owner_thread->EndWait(ResultSuccess); } // Write to the cv key. { constexpr u32 HasWaiterFlag = 1; - WriteToUser(m_system.Kernel(), key, HasWaiterFlag); + WriteToUser(m_kernel, key, HasWaiterFlag); std::atomic_thread_fence(std::memory_order_seq_cst); } // Write the value to userspace. - if (!WriteToUser(m_system.Kernel(), addr, next_value)) { + if (!WriteToUser(m_kernel, addr, next_value)) { slp.CancelSleep(); R_THROW(ResultInvalidCurrentMemory); } @@ -327,7 +329,7 @@ Result KConditionVariable::Wait(KProcessAddress addr, u64 key, u32 value, s64 ti // Begin waiting. wait_queue.SetHardwareTimer(timer); - cur_thread->BeginWait(m_system.Kernel(), std::addressof(wait_queue)); + cur_thread->BeginWait(std::addressof(wait_queue)); cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::ConditionVar); } diff --git a/src/core/hle/kernel/k_condition_variable.h b/src/core/hle/kernel/k_condition_variable.h index ca80de8837..2620c8e39e 100644 --- a/src/core/hle/kernel/k_condition_variable.h +++ b/src/core/hle/kernel/k_condition_variable.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -29,17 +26,19 @@ public: // Arbitration. static Result SignalToAddress(KernelCore& kernel, KProcessAddress addr); - static Result WaitForAddress(KernelCore& kernel, Handle handle, KProcessAddress addr, u32 value); + static Result WaitForAddress(KernelCore& kernel, Handle handle, KProcessAddress addr, + u32 value); // Condition variable. void Signal(u64 cv_key, s32 count); Result Wait(KProcessAddress addr, u64 key, u32 value, s64 timeout); private: - void SignalImpl(KernelCore& kernel, KThread* thread); + void SignalImpl(KThread* thread); private: Core::System& m_system; + KernelCore& m_kernel; ThreadTree m_tree{}; }; diff --git a/src/core/hle/kernel/k_debug.h b/src/core/hle/kernel/k_debug.h index 92ff70df74..2290e3bcab 100644 --- a/src/core/hle/kernel/k_debug.h +++ b/src/core/hle/kernel/k_debug.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -17,7 +14,7 @@ class KDebug final : public KAutoObjectWithSlabHeapAndContainerOpen(kernel); + m_owner->Open(); } // Mark initialized. m_initialized = true; } -void KEvent::Finalize(KernelCore& kernel) { - KAutoObjectWithSlabHeapAndContainer::Finalize(kernel); +void KEvent::Finalize() { + KAutoObjectWithSlabHeapAndContainer::Finalize(); } -Result KEvent::Signal(KernelCore& kernel) { - KScopedSchedulerLock sl{kernel}; +Result KEvent::Signal() { + KScopedSchedulerLock sl{m_kernel}; R_SUCCEED_IF(m_readable_event_destroyed); - return m_readable_event.Signal(kernel); + return m_readable_event.Signal(); } -Result KEvent::Clear(KernelCore& kernel) { - KScopedSchedulerLock sl{kernel}; +Result KEvent::Clear() { + KScopedSchedulerLock sl{m_kernel}; R_SUCCEED_IF(m_readable_event_destroyed); - return m_readable_event.Clear(kernel); + return m_readable_event.Clear(); } -void KEvent::PostDestroy(KernelCore& kernel, uintptr_t arg) { +void KEvent::PostDestroy(uintptr_t arg) { // Release the event count resource the owner process holds. KProcess* owner = reinterpret_cast(arg); if (owner != nullptr) { - owner->GetResourceLimit()->Release(kernel, LimitableResource::EventCountMax, 1); - owner->Close(kernel); + owner->GetResourceLimit()->Release(LimitableResource::EventCountMax, 1); + owner->Close(); } } diff --git a/src/core/hle/kernel/k_event.h b/src/core/hle/kernel/k_event.h index 75b03efa69..f522b0a84c 100644 --- a/src/core/hle/kernel/k_event.h +++ b/src/core/hle/kernel/k_event.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -22,9 +19,9 @@ public: explicit KEvent(KernelCore& kernel); ~KEvent() override; - void Initialize(KernelCore& kernel, KProcess* owner); + void Initialize(KProcess* owner); - void Finalize(KernelCore& kernel) override; + void Finalize() override; bool IsInitialized() const override { return m_initialized; @@ -42,10 +39,10 @@ public: return m_readable_event; } - static void PostDestroy(KernelCore& kernel, uintptr_t arg); + static void PostDestroy(uintptr_t arg); - Result Signal(KernelCore& kernel); - Result Clear(KernelCore& kernel); + Result Signal(); + Result Clear(); void OnReadableEventDestroyed() { m_readable_event_destroyed = true; diff --git a/src/core/hle/kernel/k_handle_table.cpp b/src/core/hle/kernel/k_handle_table.cpp index 91d805fa79..04ca235344 100644 --- a/src/core/hle/kernel/k_handle_table.cpp +++ b/src/core/hle/kernel/k_handle_table.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project @@ -6,27 +6,28 @@ #include "core/hle/kernel/k_handle_table.h" #include "core/hle/kernel/k_process.h" -#include "core/hle/kernel/kernel.h" namespace Kernel { -void KHandleTable::Finalize(KernelCore& kernel) { +void KHandleTable::Finalize() { // Get the table and clear our record of it. u16 saved_table_size = 0; { - KScopedDisableDispatch dd{kernel}; + KScopedDisableDispatch dd{m_kernel}; KScopedSpinLock lk(m_lock); std::swap(m_table_size, saved_table_size); } // Close and free all entries. - for (size_t i = 0; i < saved_table_size; i++) - if (KAutoObject* obj = m_objects[i]; obj != nullptr) - obj->Close(kernel); + for (size_t i = 0; i < saved_table_size; i++) { + if (KAutoObject* obj = m_objects[i]; obj != nullptr) { + obj->Close(); + } + } } -bool KHandleTable::Remove(KernelCore& kernel, Handle handle) { +bool KHandleTable::Remove(Handle handle) { // Don't allow removal of a pseudo-handle. if (Svc::IsPseudoHandle(handle)) [[unlikely]] { return false; @@ -41,7 +42,7 @@ bool KHandleTable::Remove(KernelCore& kernel, Handle handle) { // Find the object and free the entry. KAutoObject* obj = nullptr; { - KScopedDisableDispatch dd{kernel}; + KScopedDisableDispatch dd{m_kernel}; KScopedSpinLock lk(m_lock); if (this->IsValidHandle(handle)) [[likely]] { @@ -55,13 +56,13 @@ bool KHandleTable::Remove(KernelCore& kernel, Handle handle) { } // Close the object. - kernel.UnregisterInUseObject(obj); - obj->Close(kernel); + m_kernel.UnregisterInUseObject(obj); + obj->Close(); return true; } -Result KHandleTable::Add(KernelCore& kernel, Handle* out_handle, KAutoObject* obj) { - KScopedDisableDispatch dd{kernel}; +Result KHandleTable::Add(Handle* out_handle, KAutoObject* obj) { + KScopedDisableDispatch dd{m_kernel}; KScopedSpinLock lk(m_lock); // Never exceed our capacity. @@ -75,7 +76,7 @@ Result KHandleTable::Add(KernelCore& kernel, Handle* out_handle, KAutoObject* ob m_entry_infos[index].linear_id = linear_id; m_objects[index] = obj; - obj->Open(kernel); + obj->Open(); *out_handle = EncodeHandle(static_cast(index), linear_id); } @@ -83,22 +84,24 @@ Result KHandleTable::Add(KernelCore& kernel, Handle* out_handle, KAutoObject* ob R_SUCCEED(); } -KScopedAutoObject KHandleTable::GetObjectForIpc(KernelCore& kernel, Handle handle, KThread* cur_thread) const { +KScopedAutoObject KHandleTable::GetObjectForIpc(Handle handle, + KThread* cur_thread) const { // Handle pseudo-handles. ASSERT(cur_thread != nullptr); if (handle == Svc::PseudoHandle::CurrentProcess) { auto* const cur_process = cur_thread->GetOwnerProcess(); ASSERT(cur_process != nullptr); - return {kernel, cur_process}; + return cur_process; } if (handle == Svc::PseudoHandle::CurrentThread) { - return {kernel, cur_thread}; + return cur_thread; } - return GetObjectForIpcWithoutPseudoHandle(kernel, handle); + + return GetObjectForIpcWithoutPseudoHandle(handle); } -Result KHandleTable::Reserve(KernelCore& kernel, Handle* out_handle) { - KScopedDisableDispatch dd{kernel}; +Result KHandleTable::Reserve(Handle* out_handle) { + KScopedDisableDispatch dd{m_kernel}; KScopedSpinLock lk(m_lock); // Never exceed our capacity. @@ -108,8 +111,8 @@ Result KHandleTable::Reserve(KernelCore& kernel, Handle* out_handle) { R_SUCCEED(); } -void KHandleTable::Unreserve(KernelCore& kernel, Handle handle) { - KScopedDisableDispatch dd{kernel}; +void KHandleTable::Unreserve(Handle handle) { + KScopedDisableDispatch dd{m_kernel}; KScopedSpinLock lk(m_lock); // Unpack the handle. @@ -127,8 +130,8 @@ void KHandleTable::Unreserve(KernelCore& kernel, Handle handle) { } } -void KHandleTable::Register(KernelCore& kernel, Handle handle, KAutoObject* obj) { - KScopedDisableDispatch dd{kernel}; +void KHandleTable::Register(Handle handle, KAutoObject* obj) { + KScopedDisableDispatch dd{m_kernel}; KScopedSpinLock lk(m_lock); // Unpack the handle. @@ -146,7 +149,7 @@ void KHandleTable::Register(KernelCore& kernel, Handle handle, KAutoObject* obj) m_entry_infos[index].linear_id = static_cast(linear_id); m_objects[index] = obj; - obj->Open(kernel); + obj->Open(); } } diff --git a/src/core/hle/kernel/k_handle_table.h b/src/core/hle/kernel/k_handle_table.h index 0704fd56ef..731a5284dc 100644 --- a/src/core/hle/kernel/k_handle_table.h +++ b/src/core/hle/kernel/k_handle_table.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project @@ -31,14 +31,14 @@ public: static constexpr size_t MaxTableSize = 1024; public: - explicit KHandleTable(KernelCore& kernel) {} + explicit KHandleTable(KernelCore& kernel) : m_kernel(kernel) {} - Result Initialize(KernelCore& kernel, s32 size) { + Result Initialize(s32 size) { // Check that the table size is valid. R_UNLESS(size <= static_cast(MaxTableSize), ResultOutOfMemory); // Lock. - KScopedDisableDispatch dd{kernel}; + KScopedDisableDispatch dd{m_kernel}; KScopedSpinLock lk(m_lock); // Initialize all fields. @@ -68,72 +68,76 @@ public: return m_max_count; } - void Finalize(KernelCore& kernel); - bool Remove(KernelCore& kernel, Handle handle); + void Finalize(); + bool Remove(Handle handle); template - KScopedAutoObject GetObjectWithoutPseudoHandle(KernelCore& kernel, Handle handle) const { + KScopedAutoObject GetObjectWithoutPseudoHandle(Handle handle) const { // Lock and look up in table. - KScopedDisableDispatch dd{kernel}; + KScopedDisableDispatch dd{m_kernel}; KScopedSpinLock lk(m_lock); if constexpr (std::is_same_v) { - return {kernel, this->GetObjectImpl(handle)}; + return this->GetObjectImpl(handle); } else { if (auto* obj = this->GetObjectImpl(handle); obj != nullptr) [[likely]] { - return {kernel, obj->DynamicCast()}; + return obj->DynamicCast(); } else { - return {kernel, nullptr}; + return nullptr; } } } template - KScopedAutoObject GetObject(KernelCore& kernel, Handle handle) const { + KScopedAutoObject GetObject(Handle handle) const { // Handle pseudo-handles. if constexpr (std::derived_from) { if (handle == Svc::PseudoHandle::CurrentProcess) { - auto* const cur_process = GetCurrentProcessPointer(kernel); + auto* const cur_process = GetCurrentProcessPointer(m_kernel); ASSERT(cur_process != nullptr); - return {kernel, cur_process}; + return cur_process; } } else if constexpr (std::derived_from) { if (handle == Svc::PseudoHandle::CurrentThread) { - auto* const cur_thread = GetCurrentThreadPointer(kernel); + auto* const cur_thread = GetCurrentThreadPointer(m_kernel); ASSERT(cur_thread != nullptr); - return {kernel, cur_thread}; + return cur_thread; } } - return this->template GetObjectWithoutPseudoHandle(kernel, handle); + + return this->template GetObjectWithoutPseudoHandle(handle); } - KScopedAutoObject GetObjectForIpcWithoutPseudoHandle(KernelCore& kernel, Handle handle) const { + KScopedAutoObject GetObjectForIpcWithoutPseudoHandle(Handle handle) const { // Lock and look up in table. - KScopedDisableDispatch dd{kernel}; - KScopedSpinLock lk(m_lock); - return {kernel, this->GetObjectImpl(handle)}; - } - KScopedAutoObject GetObjectForIpc(KernelCore& kernel, Handle handle, KThread* cur_thread) const; - KScopedAutoObject GetObjectByIndex(KernelCore& kernel, Handle* out_handle, size_t index) const { - KScopedDisableDispatch dd{kernel}; + KScopedDisableDispatch dd{m_kernel}; KScopedSpinLock lk(m_lock); - return {kernel, this->GetObjectByIndexImpl(out_handle, index)}; + return this->GetObjectImpl(handle); } - Result Reserve(KernelCore& kernel, Handle* out_handle); - void Unreserve(KernelCore& kernel, Handle handle); + KScopedAutoObject GetObjectForIpc(Handle handle, KThread* cur_thread) const; - Result Add(KernelCore& kernel, Handle* out_handle, KAutoObject* obj); - void Register(KernelCore& kernel, Handle handle, KAutoObject* obj); + KScopedAutoObject GetObjectByIndex(Handle* out_handle, size_t index) const { + KScopedDisableDispatch dd{m_kernel}; + KScopedSpinLock lk(m_lock); + + return this->GetObjectByIndexImpl(out_handle, index); + } + + Result Reserve(Handle* out_handle); + void Unreserve(Handle handle); + + Result Add(Handle* out_handle, KAutoObject* obj); + void Register(Handle handle, KAutoObject* obj); template - bool GetMultipleObjects(KernelCore& kernel, T** out, const Handle* handles, size_t num_handles) const { + bool GetMultipleObjects(T** out, const Handle* handles, size_t num_handles) const { // Try to convert and open all the handles. size_t num_opened; { // Lock the table. - KScopedDisableDispatch dd{kernel}; + KScopedDisableDispatch dd{m_kernel}; KScopedSpinLock lk(m_lock); for (num_opened = 0; num_opened < num_handles; num_opened++) { // Get the current handle. @@ -146,14 +150,14 @@ public: } // Cast the current object to the desired type. - T* cur_thread = cur_object->DynamicCast(); - if (cur_thread == nullptr) [[unlikely]] { + T* cur_t = cur_object->DynamicCast(); + if (cur_t == nullptr) [[unlikely]] { break; } // Open a reference to the current object. - cur_thread->Open(kernel); - out[num_opened] = cur_thread; + cur_t->Open(); + out[num_opened] = cur_t; } } @@ -164,7 +168,7 @@ public: // If we didn't convert entry object, close the ones we opened. for (size_t i = 0; i < num_opened; i++) { - out[i]->Close(kernel); + out[i]->Close(); } return false; @@ -173,9 +177,13 @@ public: private: s32 AllocateEntry() { ASSERT(m_count < m_table_size); + const auto index = m_free_head_index; + m_free_head_index = m_entry_infos[index].GetNextFreeIndex(); + m_max_count = (std::max)(m_max_count, ++m_count); + return index; } @@ -294,6 +302,7 @@ private: }; private: + KernelCore& m_kernel; std::array m_entry_infos{}; std::array m_objects{}; mutable KSpinLock m_lock; diff --git a/src/core/hle/kernel/k_hardware_timer_base.h b/src/core/hle/kernel/k_hardware_timer_base.h index 75a4a54763..6318b35bdd 100644 --- a/src/core/hle/kernel/k_hardware_timer_base.h +++ b/src/core/hle/kernel/k_hardware_timer_base.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -48,7 +45,7 @@ protected: this->RemoveTaskFromTree(task); // Handle the task. - task->OnTimer(m_kernel); + task->OnTimer(); } } diff --git a/src/core/hle/kernel/k_interrupt_manager.cpp b/src/core/hle/kernel/k_interrupt_manager.cpp index 9bd182fd9b..22d79569a5 100644 --- a/src/core/hle/kernel/k_interrupt_manager.cpp +++ b/src/core/hle/kernel/k_interrupt_manager.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -21,19 +18,19 @@ void HandleInterrupt(KernelCore& kernel, s32 core_id) { if (auto* process = GetCurrentProcessPointer(kernel); process) { // If the user disable count is set, we may need to pin the current thread. - if (current_thread.GetUserDisableCount(kernel) && !process->GetPinnedThread(core_id)) { + if (current_thread.GetUserDisableCount() && !process->GetPinnedThread(core_id)) { KScopedSchedulerLock sl{kernel}; // Pin the current thread. - process->PinCurrentThread(kernel); + process->PinCurrentThread(); // Set the interrupt flag for the thread. - GetCurrentThread(kernel).SetInterruptFlag(kernel); + GetCurrentThread(kernel).SetInterruptFlag(); } } // Request interrupt scheduling. - kernel.CurrentScheduler()->RequestScheduleOnInterrupt(kernel); + kernel.CurrentScheduler()->RequestScheduleOnInterrupt(); } void SendInterProcessorInterrupt(KernelCore& kernel, u64 core_mask) { diff --git a/src/core/hle/kernel/k_light_client_session.cpp b/src/core/hle/kernel/k_light_client_session.cpp index 23f77deffd..8ce3e1ae49 100644 --- a/src/core/hle/kernel/k_light_client_session.cpp +++ b/src/core/hle/kernel/k_light_client_session.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -14,21 +11,21 @@ KLightClientSession::KLightClientSession(KernelCore& kernel) : KAutoObject(kerne KLightClientSession::~KLightClientSession() = default; -void KLightClientSession::Destroy(KernelCore& kernel) { - m_parent->OnClientClosed(kernel); +void KLightClientSession::Destroy() { + m_parent->OnClientClosed(); } -void KLightClientSession::OnServerClosed(KernelCore& kernel) {} +void KLightClientSession::OnServerClosed() {} -Result KLightClientSession::SendSyncRequest(KernelCore& kernel, u32* data) { +Result KLightClientSession::SendSyncRequest(u32* data) { // Get the request thread. - KThread* cur_thread = GetCurrentThreadPointer(kernel); + KThread* cur_thread = GetCurrentThreadPointer(m_kernel); // Set the light data. cur_thread->SetLightSessionData(data); // Send the request. - R_RETURN(m_parent->OnRequest(kernel, cur_thread)); + R_RETURN(m_parent->OnRequest(cur_thread)); } } // namespace Kernel diff --git a/src/core/hle/kernel/k_light_client_session.h b/src/core/hle/kernel/k_light_client_session.h index c0f48c295e..881a15cbda 100644 --- a/src/core/hle/kernel/k_light_client_session.h +++ b/src/core/hle/kernel/k_light_client_session.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -25,15 +22,15 @@ public: m_parent = parent; } - virtual void Destroy(KernelCore& kernel) override; + virtual void Destroy() override; const KLightSession* GetParent() const { return m_parent; } - Result SendSyncRequest(KernelCore& kernel, u32* data); + Result SendSyncRequest(u32* data); - void OnServerClosed(KernelCore& kernel); + void OnServerClosed(); private: KLightSession* m_parent; diff --git a/src/core/hle/kernel/k_light_condition_variable.cpp b/src/core/hle/kernel/k_light_condition_variable.cpp index 2c873162fb..6d5a815aab 100644 --- a/src/core/hle/kernel/k_light_condition_variable.cpp +++ b/src/core/hle/kernel/k_light_condition_variable.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -16,13 +13,11 @@ namespace { class ThreadQueueImplForKLightConditionVariable final : public KThreadQueue { public: - ThreadQueueImplForKLightConditionVariable(KernelCore& kernel, KThread::WaiterList* wl, bool term) - : KThreadQueue(kernel) - , m_wait_list(wl) - , m_allow_terminating_thread(term) - {} + ThreadQueueImplForKLightConditionVariable(KernelCore& kernel, KThread::WaiterList* wl, + bool term) + : KThreadQueue(kernel), m_wait_list(wl), m_allow_terminating_thread(term) {} - virtual void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { + void CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { // Only process waits if we're allowed to. if (ResultTerminationRequested == wait_result && m_allow_terminating_thread) { return; @@ -32,7 +27,7 @@ public: m_wait_list->erase(m_wait_list->iterator_to(*waiting_thread)); // Invoke the base cancel wait handler. - KThreadQueue::CancelWait(kernel, waiting_thread, wait_result, cancel_timer_task); + KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); } private: @@ -66,7 +61,7 @@ void KLightConditionVariable::Wait(KLightLock* lock, s64 timeout, bool allow_ter // Begin waiting. wait_queue.SetHardwareTimer(timer); - owner->BeginWait(m_kernel, std::addressof(wait_queue)); + owner->BeginWait(std::addressof(wait_queue)); } // Re-acquire the lock. @@ -78,7 +73,7 @@ void KLightConditionVariable::Broadcast() { // Signal all threads. for (auto it = m_wait_list.begin(); it != m_wait_list.end(); it = m_wait_list.erase(it)) { - it->EndWait(m_kernel, ResultSuccess); + it->EndWait(ResultSuccess); } } diff --git a/src/core/hle/kernel/k_light_lock.cpp b/src/core/hle/kernel/k_light_lock.cpp index 614e056d13..e87ee8b652 100644 --- a/src/core/hle/kernel/k_light_lock.cpp +++ b/src/core/hle/kernel/k_light_lock.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -18,25 +15,29 @@ class ThreadQueueImplForKLightLock final : public KThreadQueue { public: explicit ThreadQueueImplForKLightLock(KernelCore& kernel) : KThreadQueue(kernel) {} - void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { + void CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { // Remove the thread as a waiter from its owner. - if (KThread* owner = waiting_thread->GetLockOwner(kernel); owner != nullptr) { - owner->RemoveWaiter(kernel, waiting_thread); + if (KThread* owner = waiting_thread->GetLockOwner(); owner != nullptr) { + owner->RemoveWaiter(waiting_thread); } // Invoke the base cancel wait handler. - KThreadQueue::CancelWait(kernel, waiting_thread, wait_result, cancel_timer_task); + KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); } }; } // namespace void KLightLock::Lock() { - const uintptr_t cur_thread = uintptr_t(GetCurrentThreadPointer(m_kernel)); + const uintptr_t cur_thread = reinterpret_cast(GetCurrentThreadPointer(m_kernel)); + while (true) { uintptr_t old_tag = m_tag.load(std::memory_order_relaxed); - while (!m_tag.compare_exchange_weak(old_tag, (old_tag == 0) ? cur_thread : (old_tag | 1), std::memory_order_acquire)) - ; + + while (!m_tag.compare_exchange_weak(old_tag, (old_tag == 0) ? cur_thread : (old_tag | 1), + std::memory_order_acquire)) { + } + if (old_tag == 0 || this->LockSlowPath(old_tag | 1, cur_thread)) { break; } @@ -68,13 +69,13 @@ bool KLightLock::LockSlowPath(uintptr_t _owner, uintptr_t _cur_thread) { // Add the current thread as a waiter on the owner. KThread* owner_thread = reinterpret_cast(_owner & ~1ULL); cur_thread->SetKernelAddressKey(reinterpret_cast(std::addressof(m_tag))); - owner_thread->AddWaiter(m_kernel, cur_thread); + owner_thread->AddWaiter(cur_thread); // Begin waiting to hold the lock. - cur_thread->BeginWait(m_kernel, std::addressof(wait_queue)); + cur_thread->BeginWait(std::addressof(wait_queue)); if (owner_thread->IsSuspended()) { - owner_thread->ContinueIfHasKernelWaiters(m_kernel); + owner_thread->ContinueIfHasKernelWaiters(); } } @@ -90,25 +91,26 @@ void KLightLock::UnlockSlowPath(uintptr_t _cur_thread) { // Get the next owner. bool has_waiters; - KThread* next_owner = owner_thread->RemoveKernelWaiterByKey(m_kernel, - std::addressof(has_waiters), uintptr_t(std::addressof(m_tag))); + KThread* next_owner = owner_thread->RemoveKernelWaiterByKey( + std::addressof(has_waiters), reinterpret_cast(std::addressof(m_tag))); // Pass the lock to the next owner. uintptr_t next_tag = 0; if (next_owner != nullptr) { - next_tag = uintptr_t(next_owner) | uintptr_t(has_waiters); + next_tag = + reinterpret_cast(next_owner) | static_cast(has_waiters); - next_owner->EndWait(m_kernel, ResultSuccess); + next_owner->EndWait(ResultSuccess); if (next_owner->IsSuspended()) { - next_owner->ContinueIfHasKernelWaiters(m_kernel); + next_owner->ContinueIfHasKernelWaiters(); } } // We may have unsuspended in the process of acquiring the lock, so we'll re-suspend now if // so. if (owner_thread->IsSuspended()) { - owner_thread->TrySuspend(m_kernel); + owner_thread->TrySuspend(); } // Write the new tag value. @@ -117,7 +119,8 @@ void KLightLock::UnlockSlowPath(uintptr_t _cur_thread) { } bool KLightLock::IsLockedByCurrentThread() const { - return (m_tag.load() | 1ULL) == (uintptr_t(GetCurrentThreadPointer(m_kernel)) | 1ULL); + return (m_tag.load() | 1ULL) == + (reinterpret_cast(GetCurrentThreadPointer(m_kernel)) | 1ULL); } } // namespace Kernel diff --git a/src/core/hle/kernel/k_light_server_session.cpp b/src/core/hle/kernel/k_light_server_session.cpp index 6344f418ed..a4d2b11231 100644 --- a/src/core/hle/kernel/k_light_server_session.cpp +++ b/src/core/hle/kernel/k_light_server_session.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -24,20 +24,21 @@ public: ThreadQueueImplForKLightServerSessionRequest(KernelCore& kernel, KThread::WaiterList* wl) : KThreadQueue(kernel), m_wait_list(wl) {} - virtual void EndWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result) override { + virtual void EndWait(KThread* waiting_thread, Result wait_result) override { // Remove the thread from our wait list. m_wait_list->erase(m_wait_list->iterator_to(*waiting_thread)); // Invoke the base end wait handler. - KThreadQueue::EndWait(kernel, waiting_thread, wait_result); + KThreadQueue::EndWait(waiting_thread, wait_result); } - virtual void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { + virtual void CancelWait(KThread* waiting_thread, Result wait_result, + bool cancel_timer_task) override { // Remove the thread from our wait list. m_wait_list->erase(m_wait_list->iterator_to(*waiting_thread)); // Invoke the base cancel wait handler. - KThreadQueue::CancelWait(kernel, waiting_thread, wait_result, cancel_timer_task); + KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); } }; @@ -47,11 +48,9 @@ private: public: ThreadQueueImplForKLightServerSessionReceive(KernelCore& kernel, KThread** st) - : KThreadQueue(kernel) - , m_server_thread(st) - {} + : KThreadQueue(kernel), m_server_thread(st) {} - virtual void EndWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result) override { + virtual void EndWait(KThread* waiting_thread, Result wait_result) override { // Clear the server thread. *m_server_thread = nullptr; @@ -59,10 +58,11 @@ public: waiting_thread->ClearCancellable(); // Invoke the base end wait handler. - KThreadQueue::EndWait(kernel, waiting_thread, wait_result); + KThreadQueue::EndWait(waiting_thread, wait_result); } - virtual void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { + virtual void CancelWait(KThread* waiting_thread, Result wait_result, + bool cancel_timer_task) override { // Clear the server thread. *m_server_thread = nullptr; @@ -70,7 +70,7 @@ public: waiting_thread->ClearCancellable(); // Invoke the base cancel wait handler. - KThreadQueue::CancelWait(kernel, waiting_thread, wait_result, cancel_timer_task); + KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); } }; @@ -79,21 +79,24 @@ public: KLightServerSession::KLightServerSession(KernelCore& kernel) : KAutoObject(kernel) {} KLightServerSession::~KLightServerSession() = default; -void KLightServerSession::Destroy(KernelCore& kernel) { - this->CleanupRequests(kernel); - m_parent->OnServerClosed(kernel); +void KLightServerSession::Destroy() { + this->CleanupRequests(); + + m_parent->OnServerClosed(); } -void KLightServerSession::OnClientClosed(KernelCore& kernel) { - this->CleanupRequests(kernel); +void KLightServerSession::OnClientClosed() { + this->CleanupRequests(); } -Result KLightServerSession::OnRequest(KernelCore& kernel, KThread* request_thread) { - ThreadQueueImplForKLightServerSessionRequest wait_queue(kernel, std::addressof(m_request_list)); +Result KLightServerSession::OnRequest(KThread* request_thread) { + ThreadQueueImplForKLightServerSessionRequest wait_queue(m_kernel, + std::addressof(m_request_list)); + // Send the request. { // Lock the scheduler. - KScopedSchedulerLock sl(kernel); + KScopedSchedulerLock sl(m_kernel); // Check that the server isn't closed. R_UNLESS(!m_parent->IsServerClosed(), ResultSessionClosed); @@ -106,11 +109,11 @@ Result KLightServerSession::OnRequest(KernelCore& kernel, KThread* request_threa // Begin waiting on the request. request_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); - request_thread->BeginWait(kernel, std::addressof(wait_queue)); + request_thread->BeginWait(std::addressof(wait_queue)); // If we have a server thread, end its wait. if (m_server_thread != nullptr) { - m_server_thread->EndWait(kernel, ResultSuccess); + m_server_thread->EndWait(ResultSuccess); } } @@ -120,13 +123,13 @@ Result KLightServerSession::OnRequest(KernelCore& kernel, KThread* request_threa R_RETURN(request_thread->GetWaitResult()); } -Result KLightServerSession::ReplyAndReceive(KernelCore& kernel, u32* data) { +Result KLightServerSession::ReplyAndReceive(u32* data) { // Set the server context. - GetCurrentThread(kernel).SetLightSessionData(data); + GetCurrentThread(m_kernel).SetLightSessionData(data); // Reply, if we need to. if (data[0] & KLightSession::ReplyFlag) { - KScopedSchedulerLock sl(kernel); + KScopedSchedulerLock sl(m_kernel); // Check that we're open. R_UNLESS(!m_parent->IsClientClosed(), ResultSessionClosed); @@ -136,16 +139,17 @@ Result KLightServerSession::ReplyAndReceive(KernelCore& kernel, u32* data) { R_UNLESS(m_current_request != nullptr, ResultInvalidState); // Check that the server thread id is correct. - R_UNLESS(m_server_thread_id == GetCurrentThread(kernel).GetId(), ResultInvalidState); + R_UNLESS(m_server_thread_id == GetCurrentThread(m_kernel).GetId(), ResultInvalidState); // If we can reply, do so. if (!m_current_request->IsTerminationRequested()) { - std::memcpy(m_current_request->GetLightSessionData(), GetCurrentThread(kernel).GetLightSessionData(), KLightSession::DataSize); - m_current_request->EndWait(kernel, ResultSuccess); + std::memcpy(m_current_request->GetLightSessionData(), + GetCurrentThread(m_kernel).GetLightSessionData(), KLightSession::DataSize); + m_current_request->EndWait(ResultSuccess); } // Close our current request. - m_current_request->Close(kernel); + m_current_request->Close(); // Clear our current request. m_current_request = nullptr; @@ -153,13 +157,14 @@ Result KLightServerSession::ReplyAndReceive(KernelCore& kernel, u32* data) { } // Create the wait queue for our receive. - ThreadQueueImplForKLightServerSessionReceive wait_queue(kernel, std::addressof(m_server_thread)); + ThreadQueueImplForKLightServerSessionReceive wait_queue(m_kernel, + std::addressof(m_server_thread)); // Receive. while (true) { // Try to receive a request. { - KScopedSchedulerLock sl(kernel); + KScopedSchedulerLock sl(m_kernel); // Check that we aren't already receiving. R_UNLESS(m_server_thread == nullptr, ResultInvalidState); @@ -170,19 +175,20 @@ Result KLightServerSession::ReplyAndReceive(KernelCore& kernel, u32* data) { R_UNLESS(!m_parent->IsServerClosed(), ResultSessionClosed); // Check that we're not terminating. - R_UNLESS(!GetCurrentThread(kernel).IsTerminationRequested(), ResultTerminationRequested); + R_UNLESS(!GetCurrentThread(m_kernel).IsTerminationRequested(), + ResultTerminationRequested); // If we have a request available, use it. if (auto head = m_request_list.begin(); head != m_request_list.end()) { // Set our current request. m_current_request = std::addressof(*head); - m_current_request->Open(kernel); + m_current_request->Open(); // Set our server thread id. - m_server_thread_id = GetCurrentThread(kernel).GetId(); + m_server_thread_id = GetCurrentThread(m_kernel).GetId(); // Copy the client request data. - std::memcpy(GetCurrentThread(kernel).GetLightSessionData(), + std::memcpy(GetCurrentThread(m_kernel).GetLightSessionData(), m_current_request->GetLightSessionData(), KLightSession::DataSize); // We successfully received. @@ -192,51 +198,51 @@ Result KLightServerSession::ReplyAndReceive(KernelCore& kernel, u32* data) { // We need to wait for a request to come in. // Check if we were cancelled. - if (GetCurrentThread(kernel).IsWaitCancelled()) { - GetCurrentThread(kernel).ClearWaitCancelled(); + if (GetCurrentThread(m_kernel).IsWaitCancelled()) { + GetCurrentThread(m_kernel).ClearWaitCancelled(); R_THROW(ResultCancelled); } // Mark ourselves as cancellable. - GetCurrentThread(kernel).SetCancellable(); + GetCurrentThread(m_kernel).SetCancellable(); // Wait for a request to come in. - m_server_thread = GetCurrentThreadPointer(kernel); - GetCurrentThread(kernel).SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); - GetCurrentThread(kernel).BeginWait(kernel, std::addressof(wait_queue)); + m_server_thread = GetCurrentThreadPointer(m_kernel); + GetCurrentThread(m_kernel).SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); + GetCurrentThread(m_kernel).BeginWait(std::addressof(wait_queue)); } // We waited to receive a request; if our wait failed, return the failing result. - R_TRY(GetCurrentThread(kernel).GetWaitResult()); + R_TRY(GetCurrentThread(m_kernel).GetWaitResult()); } } -void KLightServerSession::CleanupRequests(KernelCore& kernel) { +void KLightServerSession::CleanupRequests() { // Cleanup all pending requests. { - KScopedSchedulerLock sl(kernel); + KScopedSchedulerLock sl(m_kernel); // Handle the current request. if (m_current_request != nullptr) { // Reply to the current request. if (!m_current_request->IsTerminationRequested()) { - m_current_request->EndWait(kernel, ResultSessionClosed); + m_current_request->EndWait(ResultSessionClosed); } // Clear our current request. - m_current_request->Close(kernel); + m_current_request->Close(); m_current_request = nullptr; m_server_thread_id = InvalidThreadId; } // Reply to all other requests. for (auto& thread : m_request_list) { - thread.EndWait(kernel, ResultSessionClosed); + thread.EndWait(ResultSessionClosed); } // Wait up our server thread, if we have one. if (m_server_thread != nullptr) { - m_server_thread->EndWait(kernel, ResultSessionClosed); + m_server_thread->EndWait(ResultSessionClosed); } } } diff --git a/src/core/hle/kernel/k_light_server_session.h b/src/core/hle/kernel/k_light_server_session.h index 5849a41c7b..67db3f76ca 100644 --- a/src/core/hle/kernel/k_light_server_session.h +++ b/src/core/hle/kernel/k_light_server_session.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -34,19 +34,19 @@ public: m_parent = parent; } - virtual void Destroy(KernelCore& kernel) override; + virtual void Destroy() override; constexpr const KLightSession* GetParent() const { return m_parent; } - Result OnRequest(KernelCore& kernel, KThread* request_thread); - Result ReplyAndReceive(KernelCore& kernel, u32* data); + Result OnRequest(KThread* request_thread); + Result ReplyAndReceive(u32* data); - void OnClientClosed(KernelCore& kernel); + void OnClientClosed(); private: - void CleanupRequests(KernelCore& kernel); + void CleanupRequests(); }; } // namespace Kernel diff --git a/src/core/hle/kernel/k_light_session.cpp b/src/core/hle/kernel/k_light_session.cpp index add72d404b..d8b1e69582 100644 --- a/src/core/hle/kernel/k_light_session.cpp +++ b/src/core/hle/kernel/k_light_session.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -13,18 +10,15 @@ namespace Kernel { KLightSession::KLightSession(KernelCore& kernel) - : KAutoObjectWithSlabHeapAndContainer(kernel) - , m_server(kernel) - , m_client(kernel) -{} + : KAutoObjectWithSlabHeapAndContainer(kernel), m_server(kernel), m_client(kernel) {} KLightSession::~KLightSession() = default; -void KLightSession::Initialize(KernelCore& kernel, KClientPort* client_port, uintptr_t name) { +void KLightSession::Initialize(KClientPort* client_port, uintptr_t name) { // Increment reference count. // Because reference count is one on creation, this will result // in a reference count of two. Thus, when both server and client are closed // this object will be destroyed. - this->Open(kernel); + this->Open(); // Create our sub sessions. KAutoObject::Create(std::addressof(m_server)); @@ -39,47 +33,49 @@ void KLightSession::Initialize(KernelCore& kernel, KClientPort* client_port, uin m_name = name; // Set our owner process. - m_process = GetCurrentProcessPointer(kernel); - m_process->Open(kernel); + m_process = GetCurrentProcessPointer(m_kernel); + m_process->Open(); // Set our port. m_port = client_port; if (m_port != nullptr) { - m_port->Open(kernel); + m_port->Open(); } // Mark initialized. m_initialized = true; } -void KLightSession::Finalize(KernelCore& kernel) { +void KLightSession::Finalize() { if (m_port != nullptr) { - m_port->OnSessionFinalized(kernel); - m_port->Close(kernel); + m_port->OnSessionFinalized(); + m_port->Close(); } } -void KLightSession::OnServerClosed(KernelCore& kernel) { +void KLightSession::OnServerClosed() { if (m_state == State::Normal) { m_state = State::ServerClosed; - m_client.OnServerClosed(kernel); + m_client.OnServerClosed(); } - this->Close(kernel); + + this->Close(); } -void KLightSession::OnClientClosed(KernelCore& kernel) { +void KLightSession::OnClientClosed() { if (m_state == State::Normal) { m_state = State::ClientClosed; - m_server.OnClientClosed(kernel); + m_server.OnClientClosed(); } - this->Close(kernel); + + this->Close(); } -void KLightSession::PostDestroy(KernelCore& kernel, uintptr_t arg) { +void KLightSession::PostDestroy(uintptr_t arg) { // Release the session count resource the owner process holds. KProcess* owner = reinterpret_cast(arg); - owner->ReleaseResource(kernel, Svc::LimitableResource::SessionCountMax, 1); - owner->Close(kernel); + owner->ReleaseResource(Svc::LimitableResource::SessionCountMax, 1); + owner->Close(); } } // namespace Kernel diff --git a/src/core/hle/kernel/k_light_session.h b/src/core/hle/kernel/k_light_session.h index 5bbb942b35..f78d8e6899 100644 --- a/src/core/hle/kernel/k_light_session.h +++ b/src/core/hle/kernel/k_light_session.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -46,20 +43,20 @@ public: explicit KLightSession(KernelCore& kernel); ~KLightSession(); - void Initialize(KernelCore& kernel, KClientPort* client_port, uintptr_t name); - void Finalize(KernelCore& kernel) override; + void Initialize(KClientPort* client_port, uintptr_t name); + void Finalize() override; bool IsInitialized() const override { return m_initialized; } uintptr_t GetPostDestroyArgument() const override { - return uintptr_t(m_process); + return reinterpret_cast(m_process); } - static void PostDestroy(KernelCore& kernel, uintptr_t arg); + static void PostDestroy(uintptr_t arg); - void OnServerClosed(KernelCore& kernel); - void OnClientClosed(KernelCore& kernel); + void OnServerClosed(); + void OnClientClosed(); bool IsServerClosed() const { return m_state != State::Normal; @@ -68,8 +65,8 @@ public: return m_state != State::Normal; } - Result OnRequest(KernelCore& kernel, KThread* request_thread) { - R_RETURN(m_server.OnRequest(kernel, request_thread)); + Result OnRequest(KThread* request_thread) { + R_RETURN(m_server.OnRequest(request_thread)); } KLightClientSession& GetClientSession() { diff --git a/src/core/hle/kernel/k_object_name.cpp b/src/core/hle/kernel/k_object_name.cpp index da0b04b450..df3a1c4c56 100644 --- a/src/core/hle/kernel/k_object_name.cpp +++ b/src/core/hle/kernel/k_object_name.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -11,14 +8,14 @@ namespace Kernel { KObjectNameGlobalData::KObjectNameGlobalData(KernelCore& kernel) : m_object_list_lock{kernel} {} KObjectNameGlobalData::~KObjectNameGlobalData() = default; -void KObjectName::Initialize(KernelCore& kernel, KAutoObject* obj, const char* name) { +void KObjectName::Initialize(KAutoObject* obj, const char* name) { // Set member variables. m_object = obj; std::strncpy(m_name.data(), name, sizeof(m_name) - 1); m_name[sizeof(m_name) - 1] = '\x00'; // Open a reference to the object we hold. - m_object->Open(kernel); + m_object->Open(); } bool KObjectName::MatchesName(const char* name) const { @@ -31,7 +28,7 @@ Result KObjectName::NewFromName(KernelCore& kernel, KAutoObject* obj, const char R_UNLESS(new_name != nullptr, ResultOutOfResource); // Initialize the new name. - new_name->Initialize(kernel, obj, name); + new_name->Initialize(obj, name); // Check if there's an existing name. { @@ -50,7 +47,7 @@ Result KObjectName::NewFromName(KernelCore& kernel, KAutoObject* obj, const char } // The object already exists, which is an error condition. Perform cleanup. - obj->Close(kernel); + obj->Close(); KObjectName::Free(kernel, new_name); R_THROW(ResultInvalidState); } @@ -66,7 +63,7 @@ Result KObjectName::Delete(KernelCore& kernel, KAutoObject* obj, const char* com for (auto& name : gd.GetObjectList()) { if (name.MatchesName(compare_name) && obj == name.GetObject()) { // We found a match, clean up its resources. - obj->Close(kernel); + obj->Close(); gd.GetObjectList().erase(gd.GetObjectList().iterator_to(name)); KObjectName::Free(kernel, std::addressof(name)); R_SUCCEED(); @@ -92,12 +89,14 @@ KScopedAutoObject KObjectName::FindImpl(KernelCore& kernel, const c KObjectNameGlobalData& gd{kernel.ObjectNameGlobalData()}; // Try to find a matching object in the global list. - for (const auto& name : gd.GetObjectList()) - if (name.MatchesName(compare_name)) - return {kernel, name.GetObject()}; + for (const auto& name : gd.GetObjectList()) { + if (name.MatchesName(compare_name)) { + return name.GetObject(); + } + } // There's no matching entry in the list. - return {kernel, nullptr}; + return nullptr; } } // namespace Kernel diff --git a/src/core/hle/kernel/k_object_name.h b/src/core/hle/kernel/k_object_name.h index 2ae9edcf51..a8876fe370 100644 --- a/src/core/hle/kernel/k_object_name.h +++ b/src/core/hle/kernel/k_object_name.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -44,7 +41,7 @@ public: R_UNLESS(derived != nullptr, ResultNotFound); // Check that the object is closed. - R_UNLESS(derived->IsServerClosed(kernel), ResultInvalidState); + R_UNLESS(derived->IsServerClosed(), ResultInvalidState); R_RETURN(Delete(kernel, obj.GetPointerUnsafe(), name)); } @@ -52,13 +49,13 @@ public: template requires(std::derived_from) static KScopedAutoObject Find(KernelCore& kernel, const char* name) { - return {kernel, static_cast(Find(kernel, name).GetPointerUnsafe())}; + return Find(kernel, name); } private: static KScopedAutoObject FindImpl(KernelCore& kernel, const char* name); - void Initialize(KernelCore& kernel, KAutoObject* obj, const char* name); + void Initialize(KAutoObject* obj, const char* name); bool MatchesName(const char* name) const; KAutoObject* GetObject() const { diff --git a/src/core/hle/kernel/k_page_group.cpp b/src/core/hle/kernel/k_page_group.cpp index ed7f219718..d8c644a336 100644 --- a/src/core/hle/kernel/k_page_group.cpp +++ b/src/core/hle/kernel/k_page_group.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -24,8 +21,8 @@ void KPageGroup::Finalize() { m_last_block = nullptr; } -void KPageGroup::CloseAndReset(KernelCore& kernel) { - auto& mm = kernel.MemoryManager(); +void KPageGroup::CloseAndReset() { + auto& mm = m_kernel.MemoryManager(); KBlockInfo* cur = m_first_block; while (cur != nullptr) { @@ -79,22 +76,28 @@ Result KPageGroup::AddBlock(KPhysicalAddress addr, size_t num_pages) { R_SUCCEED(); } -void KPageGroup::Open(KernelCore& kernel) const { - auto& mm = kernel.MemoryManager(); - for (const auto& it : *this) +void KPageGroup::Open() const { + auto& mm = m_kernel.MemoryManager(); + + for (const auto& it : *this) { mm.Open(it.GetAddress(), it.GetNumPages()); + } } -void KPageGroup::OpenFirst(KernelCore& kernel) const { - auto& mm = kernel.MemoryManager(); - for (const auto& it : *this) +void KPageGroup::OpenFirst() const { + auto& mm = m_kernel.MemoryManager(); + + for (const auto& it : *this) { mm.OpenFirst(it.GetAddress(), it.GetNumPages()); + } } -void KPageGroup::Close(KernelCore& kernel) const { - auto& mm = kernel.MemoryManager(); - for (const auto& it : *this) +void KPageGroup::Close() const { + auto& mm = m_kernel.MemoryManager(); + + for (const auto& it : *this) { mm.Close(it.GetAddress(), it.GetNumPages()); + } } bool KPageGroup::IsEquivalentTo(const KPageGroup& rhs) const { diff --git a/src/core/hle/kernel/k_page_group.h b/src/core/hle/kernel/k_page_group.h index 60a6faa2fd..de9d63a8d2 100644 --- a/src/core/hle/kernel/k_page_group.h +++ b/src/core/hle/kernel/k_page_group.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -142,12 +139,12 @@ public: }; explicit KPageGroup(KernelCore& kernel, KBlockInfoManager* m) - : m_manager{m} {} + : m_kernel{kernel}, m_manager{m} {} ~KPageGroup() { this->Finalize(); } - void CloseAndReset(KernelCore& kernel); + void CloseAndReset(); void Finalize(); Iterator begin() const { @@ -161,9 +158,9 @@ public: } Result AddBlock(KPhysicalAddress addr, size_t num_pages); - void Open(KernelCore& kernel) const; - void OpenFirst(KernelCore& kernel) const; - void Close(KernelCore& kernel) const; + void Open() const; + void OpenFirst() const; + void Close() const; size_t GetNumPages() const; @@ -178,6 +175,7 @@ public: } private: + KernelCore& m_kernel; KBlockInfo* m_first_block{}; KBlockInfo* m_last_block{}; KBlockInfoManager* m_manager{}; @@ -185,24 +183,21 @@ private: class KScopedPageGroup { public: - explicit KScopedPageGroup(KernelCore& kernel, const KPageGroup* gp, bool not_first = true) - : m_kernel{kernel} - , m_pg{gp} - { + explicit KScopedPageGroup(const KPageGroup* gp, bool not_first = true) : m_pg(gp) { if (m_pg) { if (not_first) { - m_pg->Open(kernel); + m_pg->Open(); } else { - m_pg->OpenFirst(kernel); + m_pg->OpenFirst(); } } } - explicit KScopedPageGroup(KernelCore& kernel, const KPageGroup& gp, bool not_first = true) - : KScopedPageGroup(kernel, std::addressof(gp), not_first) {} - + explicit KScopedPageGroup(const KPageGroup& gp, bool not_first = true) + : KScopedPageGroup(std::addressof(gp), not_first) {} ~KScopedPageGroup() { - if (m_pg) - m_pg->Close(m_kernel); + if (m_pg) { + m_pg->Close(); + } } void CancelClose() { @@ -210,7 +205,6 @@ public: } private: - KernelCore& m_kernel; const KPageGroup* m_pg{}; }; diff --git a/src/core/hle/kernel/k_page_table_base.cpp b/src/core/hle/kernel/k_page_table_base.cpp index a727355a9f..3696f9f251 100644 --- a/src/core/hle/kernel/k_page_table_base.cpp +++ b/src/core/hle/kernel/k_page_table_base.cpp @@ -127,22 +127,22 @@ constexpr Common::MemoryPermission ConvertToMemoryPermission(KMemoryPermission p } // namespace -void KPageTableBase::MemoryRange::Open(KernelCore& kernel) { +void KPageTableBase::MemoryRange::Open() { // If the range contains heap pages, open them. if (this->IsHeap()) { - kernel.MemoryManager().Open(this->GetAddress(), this->GetSize() / PageSize); + m_kernel.MemoryManager().Open(this->GetAddress(), this->GetSize() / PageSize); } } -void KPageTableBase::MemoryRange::Close(KernelCore& kernel) { +void KPageTableBase::MemoryRange::Close() { // If the range contains heap pages, close them. if (this->IsHeap()) { - kernel.MemoryManager().Close(this->GetAddress(), this->GetSize() / PageSize); + m_kernel.MemoryManager().Close(this->GetAddress(), this->GetSize() / PageSize); } } KPageTableBase::KPageTableBase(KernelCore& kernel) - : m_system(kernel.System()), m_general_lock(kernel), + : m_kernel(kernel), m_system(kernel.System()), m_general_lock(kernel), m_map_physical_memory_lock(kernel), m_device_map_lock(kernel) {} KPageTableBase::~KPageTableBase() = default; @@ -177,9 +177,9 @@ Result KPageTableBase::InitializeForKernel(bool is_64_bit, KVirtualAddress start m_mapped_ipc_server_memory = 0; m_memory_block_slab_manager = - m_system.Kernel().GetSystemSystemResource().GetMemoryBlockSlabManagerPointer(); - m_block_info_manager = m_system.Kernel().GetSystemSystemResource().GetBlockInfoManagerPointer(); - m_resource_limit = m_system.Kernel().GetSystemResourceLimit(); + m_kernel.GetSystemSystemResource().GetMemoryBlockSlabManagerPointer(); + m_block_info_manager = m_kernel.GetSystemSystemResource().GetBlockInfoManagerPointer(); + m_resource_limit = m_kernel.GetSystemResourceLimit(); m_allocate_option = KMemoryManager::EncodeOption(KMemoryManager::Pool::System, KMemoryManager::Direction::FromFront); @@ -469,11 +469,11 @@ void KPageTableBase::Finalize() { } // Get physical pages. - KPageGroup pg(m_system.Kernel(), m_block_info_manager); + KPageGroup pg(m_kernel, m_block_info_manager); this->MakePageGroup(pg, addr, size / PageSize); // Free the pages. - pg.CloseAndReset(m_system.Kernel()); + pg.CloseAndReset(); }; // Finalize memory blocks. @@ -490,16 +490,16 @@ void KPageTableBase::Finalize() { // Release any insecure mapped memory. if (m_mapped_insecure_memory) { if (auto* const insecure_resource_limit = - KSystemControl::GetInsecureMemoryResourceLimit(m_system.Kernel()); + KSystemControl::GetInsecureMemoryResourceLimit(m_kernel); insecure_resource_limit != nullptr) { - insecure_resource_limit->Release(m_system.Kernel(), Svc::LimitableResource::PhysicalMemoryMax, + insecure_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, m_mapped_insecure_memory); } } // Release any ipc server memory. if (m_mapped_ipc_server_memory) { - m_resource_limit->Release(m_system.Kernel(), Svc::LimitableResource::PhysicalMemoryMax, + m_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, m_mapped_ipc_server_memory); } } @@ -833,7 +833,7 @@ Result KPageTableBase::LockMemoryAndOpen(KPageGroup* out_pg, KPhysicalAddress* o // If we have an output group, open. if (out_pg) { - out_pg->Open(m_system.Kernel()); + out_pg->Open(); } R_SUCCEED(); @@ -1041,7 +1041,7 @@ Result KPageTableBase::MapMemory(KProcessAddress dst_address, KProcessAddress sr const size_t num_pages = size / PageSize; // Create page groups for the memory being unmapped. - KPageGroup pg(m_system.Kernel(), m_block_info_manager); + KPageGroup pg(m_kernel, m_block_info_manager); // Create the page group representing the source. R_TRY(this->MakePageGroup(pg, src_address, num_pages)); @@ -1129,7 +1129,7 @@ Result KPageTableBase::UnmapMemory(KProcessAddress dst_address, KProcessAddress const size_t num_pages = size / PageSize; // Create page groups for the memory being unmapped. - KPageGroup pg(m_system.Kernel(), m_block_info_manager); + KPageGroup pg(m_kernel, m_block_info_manager); // Create the page group representing the destination. R_TRY(this->MakePageGroup(pg, dst_address, num_pages)); @@ -1217,7 +1217,7 @@ Result KPageTableBase::MapCodeMemory(KProcessAddress dst_address, KProcessAddres const size_t num_pages = size / PageSize; // Create page groups for the memory being unmapped. - KPageGroup pg(m_system.Kernel(), m_block_info_manager); + KPageGroup pg(m_kernel, m_block_info_manager); // Create the page group representing the source. R_TRY(this->MakePageGroup(pg, src_address, num_pages)); @@ -1312,7 +1312,7 @@ Result KPageTableBase::UnmapCodeMemory(KProcessAddress dst_address, KProcessAddr bool reprotected_pages = false; SCOPE_EXIT { if (reprotected_pages && any_code_pages) { - InvalidateInstructionCache(m_system.Kernel(), this, dst_address, size); + InvalidateInstructionCache(m_kernel, this, dst_address, size); } }; @@ -1322,7 +1322,7 @@ Result KPageTableBase::UnmapCodeMemory(KProcessAddress dst_address, KProcessAddr const size_t num_pages = size / PageSize; // Create page groups for the memory being unmapped. - KPageGroup pg(m_system.Kernel(), m_block_info_manager); + KPageGroup pg(m_kernel, m_block_info_manager); // Create the page group representing the destination. R_TRY(this->MakePageGroup(pg, dst_address, num_pages)); @@ -1383,19 +1383,19 @@ Result KPageTableBase::UnmapCodeMemory(KProcessAddress dst_address, KProcessAddr Result KPageTableBase::MapInsecureMemory(KProcessAddress address, size_t size) { // Get the insecure memory resource limit and pool. - auto* const insecure_resource_limit = KSystemControl::GetInsecureMemoryResourceLimit(m_system.Kernel()); + auto* const insecure_resource_limit = KSystemControl::GetInsecureMemoryResourceLimit(m_kernel); const auto insecure_pool = static_cast(KSystemControl::GetInsecureMemoryPool()); // Reserve the insecure memory. // NOTE: ResultOutOfMemory is returned here instead of the usual LimitReached. - KScopedResourceReservation memory_reservation(m_system.Kernel(), insecure_resource_limit, + KScopedResourceReservation memory_reservation(insecure_resource_limit, Svc::LimitableResource::PhysicalMemoryMax, size); R_UNLESS(memory_reservation.Succeeded(), ResultOutOfMemory); // Allocate pages for the insecure memory. - KPageGroup pg(m_system.Kernel(), m_block_info_manager); - R_TRY(m_system.Kernel().MemoryManager().AllocateAndOpen( + KPageGroup pg(m_kernel, m_block_info_manager); + R_TRY(m_kernel.MemoryManager().AllocateAndOpen( std::addressof(pg), size / PageSize, KMemoryManager::EncodeOption(insecure_pool, KMemoryManager::Direction::FromFront))); @@ -1403,7 +1403,7 @@ Result KPageTableBase::MapInsecureMemory(KProcessAddress address, size_t size) { // If the mapping succeeds, each page will gain an extra reference, otherwise they will be freed // automatically. SCOPE_EXIT { - pg.Close(m_system.Kernel()); + pg.Close(); }; // Clear all the newly allocated pages. @@ -1491,9 +1491,9 @@ Result KPageTableBase::UnmapInsecureMemory(KProcessAddress address, size_t size) // Release the insecure memory from the insecure limit. if (auto* const insecure_resource_limit = - KSystemControl::GetInsecureMemoryResourceLimit(m_system.Kernel()); + KSystemControl::GetInsecureMemoryResourceLimit(m_kernel); insecure_resource_limit != nullptr) { - insecure_resource_limit->Release(m_system.Kernel(), Svc::LimitableResource::PhysicalMemoryMax, size); + insecure_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, size); } R_SUCCEED(); @@ -1603,15 +1603,15 @@ Result KPageTableBase::AllocateAndMapPagesImpl(PageLinkedList* page_list, KProce ASSERT(this->IsLockedByCurrentThread()); // Create a page group to hold the pages we allocate. - KPageGroup pg(m_system.Kernel(), m_block_info_manager); + KPageGroup pg(m_kernel, m_block_info_manager); // Allocate the pages. R_TRY( - m_system.Kernel().MemoryManager().AllocateAndOpen(std::addressof(pg), num_pages, m_allocate_option)); + m_kernel.MemoryManager().AllocateAndOpen(std::addressof(pg), num_pages, m_allocate_option)); // Ensure that the page group is closed when we're done working with it. SCOPE_EXIT { - pg.Close(m_system.Kernel()); + pg.Close(); }; // Clear all pages. @@ -1992,7 +1992,7 @@ Result KPageTableBase::SetProcessMemoryPermission(KProcessAddress addr, size_t s KMemoryAttribute::All, KMemoryAttribute::None)); // Make a new page group for the region. - KPageGroup pg(m_system.Kernel(), m_block_info_manager); + KPageGroup pg(m_kernel, m_block_info_manager); // Determine new perm/state. const KMemoryPermission new_perm = ConvertToKMemoryPermission(svc_perm); @@ -2048,9 +2048,9 @@ Result KPageTableBase::SetProcessMemoryPermission(KProcessAddress addr, size_t s // Ensure cache coherency, if we're setting pages as executable. if (is_x) { for (const auto& block : pg) { - StoreDataCache(GetHeapVirtualPointer(m_system.Kernel(), block.GetAddress()), block.GetSize()); + StoreDataCache(GetHeapVirtualPointer(m_kernel, block.GetAddress()), block.GetSize()); } - InvalidateInstructionCache(m_system.Kernel(), this, addr, size); + InvalidateInstructionCache(m_kernel, this, addr, size); } R_SUCCEED(); @@ -2158,7 +2158,7 @@ Result KPageTableBase::SetHeapSize(KProcessAddress* out, size_t size) { false, unmap_properties, OperationType::Unmap, false)); // Release the memory from the resource limit. - m_resource_limit->Release(m_system.Kernel(), Svc::LimitableResource::PhysicalMemoryMax, + m_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, num_pages * PageSize); // Apply the memory block update. @@ -2188,20 +2188,20 @@ Result KPageTableBase::SetHeapSize(KProcessAddress* out, size_t size) { } // Reserve memory for the heap extension. - KScopedResourceReservation memory_reservation(m_system.Kernel(), + KScopedResourceReservation memory_reservation( m_resource_limit, Svc::LimitableResource::PhysicalMemoryMax, allocation_size); R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); // Allocate pages for the heap extension. - KPageGroup pg(m_system.Kernel(), m_block_info_manager); - R_TRY(m_system.Kernel().MemoryManager().AllocateAndOpen(std::addressof(pg), allocation_size / PageSize, + KPageGroup pg(m_kernel, m_block_info_manager); + R_TRY(m_kernel.MemoryManager().AllocateAndOpen(std::addressof(pg), allocation_size / PageSize, m_allocate_option)); // Close the opened pages when we're done with them. // If the mapping succeeds, each page will gain an extra reference, otherwise they will be freed // automatically. SCOPE_EXIT { - pg.Close(m_system.Kernel()); + pg.Close(); }; // Clear all the newly allocated pages. @@ -2406,7 +2406,7 @@ Result KPageTableBase::MapIoImpl(KProcessAddress* out, PageLinkedList* page_list ASSERT(this->CanContain(region_start, region_size, state)); // Locate the memory region. - const KMemoryRegion* region = KMemoryLayout::Find(m_system.Kernel().MemoryLayout(), phys_addr); + const KMemoryRegion* region = KMemoryLayout::Find(m_kernel.MemoryLayout(), phys_addr); R_UNLESS(region != nullptr, ResultInvalidAddress); ASSERT(region->Contains(GetInteger(phys_addr))); @@ -2640,7 +2640,7 @@ Result KPageTableBase::MapStatic(KPhysicalAddress phys_addr, size_t size, KMemor const size_t region_num_pages = region_size / PageSize; // Locate the memory region. - const KMemoryRegion* region = KMemoryLayout::Find(m_system.Kernel().MemoryLayout(), phys_addr); + const KMemoryRegion* region = KMemoryLayout::Find(m_kernel.MemoryLayout(), phys_addr); R_UNLESS(region != nullptr, ResultInvalidAddress); ASSERT(region->Contains(GetInteger(phys_addr))); @@ -2707,7 +2707,7 @@ Result KPageTableBase::MapStatic(KPhysicalAddress phys_addr, size_t size, KMemor Result KPageTableBase::MapRegion(KMemoryRegionType region_type, KMemoryPermission perm) { // Get the memory region. const KMemoryRegion* region = - m_system.Kernel().MemoryLayout().GetPhysicalMemoryRegionTree().FindFirstDerived(region_type); + m_kernel.MemoryLayout().GetPhysicalMemoryRegionTree().FindFirstDerived(region_type); R_UNLESS(region != nullptr, ResultOutOfRange); // Check that the region is valid. @@ -3004,7 +3004,7 @@ Result KPageTableBase::MakeAndOpenPageGroup(KPageGroup* out, KProcessAddress add R_TRY(this->MakePageGroup(*out, address, num_pages)); // Open a new reference to the pages in the group. - out->Open(m_system.Kernel()); + out->Open(); R_SUCCEED(); } @@ -3051,7 +3051,7 @@ Result KPageTableBase::InvalidateProcessDataCache(KProcessAddress address, size_ // Invalidate the block. if (cur_size > 0) { // NOTE: Nintendo does not check the result of invalidation. - InvalidateDataCache(GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), cur_size); + InvalidateDataCache(GetLinearMappedVirtualPointer(m_kernel, cur_addr), cur_size); } // Advance. @@ -3075,7 +3075,7 @@ Result KPageTableBase::InvalidateProcessDataCache(KProcessAddress address, size_ // Invalidate the last block. if (cur_size > 0) { // NOTE: Nintendo does not check the result of invalidation. - InvalidateDataCache(GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), cur_size); + InvalidateDataCache(GetLinearMappedVirtualPointer(m_kernel, cur_addr), cur_size); } R_SUCCEED(); @@ -3083,7 +3083,7 @@ Result KPageTableBase::InvalidateProcessDataCache(KProcessAddress address, size_ Result KPageTableBase::InvalidateCurrentProcessDataCache(KProcessAddress address, size_t size) { // Check pre-condition: this is being called on the current process. - ASSERT(this == std::addressof(GetCurrentProcess(m_system.Kernel()).GetPageTable().GetBasePageTable())); + ASSERT(this == std::addressof(GetCurrentProcess(m_kernel).GetPageTable().GetBasePageTable())); // Check that the region is in range. R_UNLESS(this->Contains(address, size), ResultInvalidCurrentMemory); @@ -3144,7 +3144,7 @@ Result KPageTableBase::ReadDebugMemory(KProcessAddress dst_address, KProcessAddr // Copy as much aligned data as we can. if (cur_size >= sizeof(u32)) { const size_t copy_size = Common::AlignDown(cur_size, sizeof(u32)); - const void* copy_src = GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr); + const void* copy_src = GetLinearMappedVirtualPointer(m_kernel, cur_addr); FlushDataCache(copy_src, copy_size); R_UNLESS(dst_memory.WriteBlock(dst_address, copy_src, copy_size), ResultInvalidPointer); @@ -3155,7 +3155,7 @@ Result KPageTableBase::ReadDebugMemory(KProcessAddress dst_address, KProcessAddr // Copy remaining data. if (cur_size > 0) { - const void* copy_src = GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr); + const void* copy_src = GetLinearMappedVirtualPointer(m_kernel, cur_addr); FlushDataCache(copy_src, cur_size); R_UNLESS(dst_memory.WriteBlock(dst_address, copy_src, cur_size), ResultInvalidPointer); } @@ -3240,11 +3240,11 @@ Result KPageTableBase::WriteDebugMemory(KProcessAddress dst_address, KProcessAdd // Copy as much aligned data as we can. if (cur_size >= sizeof(u32)) { const size_t copy_size = Common::AlignDown(cur_size, sizeof(u32)); - void* copy_dst = GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr); + void* copy_dst = GetLinearMappedVirtualPointer(m_kernel, cur_addr); R_UNLESS(src_memory.ReadBlock(src_address, copy_dst, copy_size), ResultInvalidCurrentMemory); - StoreDataCache(GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), copy_size); + StoreDataCache(GetLinearMappedVirtualPointer(m_kernel, cur_addr), copy_size); src_address += copy_size; cur_addr += copy_size; @@ -3253,11 +3253,11 @@ Result KPageTableBase::WriteDebugMemory(KProcessAddress dst_address, KProcessAdd // Copy remaining data. if (cur_size > 0) { - void* copy_dst = GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr); + void* copy_dst = GetLinearMappedVirtualPointer(m_kernel, cur_addr); R_UNLESS(src_memory.ReadBlock(src_address, copy_dst, cur_size), ResultInvalidCurrentMemory); - StoreDataCache(GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), cur_size); + StoreDataCache(GetLinearMappedVirtualPointer(m_kernel, cur_addr), cur_size); } R_SUCCEED(); @@ -3295,7 +3295,7 @@ Result KPageTableBase::WriteDebugMemory(KProcessAddress dst_address, KProcessAdd R_TRY(PerformCopy()); // Invalidate the instruction cache, as this svc allows modifying executable pages. - InvalidateInstructionCache(m_system.Kernel(), this, dst_address, size); + InvalidateInstructionCache(m_kernel, this, dst_address, size); R_SUCCEED(); } @@ -3311,7 +3311,7 @@ Result KPageTableBase::ReadIoMemoryImpl(KProcessAddress dst_addr, KPhysicalAddre const size_t map_size = map_end - map_start; // Get the memory reference to write into. - auto& dst_memory = GetCurrentMemory(m_system.Kernel()); + auto& dst_memory = GetCurrentMemory(m_kernel); // We're going to perform an update, so create a helper. KScopedPageTableUpdater updater(this); @@ -3347,7 +3347,7 @@ Result KPageTableBase::WriteIoMemoryImpl(KPhysicalAddress phys_addr, KProcessAdd const size_t map_size = map_end - map_start; // Get the memory reference to read from. - auto& src_memory = GetCurrentMemory(m_system.Kernel()); + auto& src_memory = GetCurrentMemory(m_kernel); // We're going to perform an update, so create a helper. KScopedPageTableUpdater updater(this); @@ -3379,7 +3379,7 @@ Result KPageTableBase::ReadDebugIoMemory(KProcessAddress dst_address, KProcessAd // We need to lock both this table, and the current process's table, so set up some aliases. KPageTableBase& src_page_table = *this; - KPageTableBase& dst_page_table = GetCurrentProcess(m_system.Kernel()).GetPageTable().GetBasePageTable(); + KPageTableBase& dst_page_table = GetCurrentProcess(m_kernel).GetPageTable().GetBasePageTable(); // Acquire the table locks. KScopedLightLockPair lk(src_page_table.m_general_lock, dst_page_table.m_general_lock); @@ -3421,7 +3421,7 @@ Result KPageTableBase::WriteDebugIoMemory(KProcessAddress dst_address, KProcessA // We need to lock both this table, and the current process's table, so set up some aliases. KPageTableBase& src_page_table = *this; - KPageTableBase& dst_page_table = GetCurrentProcess(m_system.Kernel()).GetPageTable().GetBasePageTable(); + KPageTableBase& dst_page_table = GetCurrentProcess(m_kernel).GetPageTable().GetBasePageTable(); // Acquire the table locks. KScopedLightLockPair lk(src_page_table.m_general_lock, dst_page_table.m_general_lock); @@ -3606,7 +3606,7 @@ Result KPageTableBase::OpenMemoryRangeForMapDeviceAddressSpace(KPageTableBase::M KMemoryAttribute::IpcLocked | KMemoryAttribute::Locked, KMemoryAttribute::None)); // We got the range, so open it. - out->Open(m_system.Kernel()); + out->Open(); R_SUCCEED(); } @@ -3624,7 +3624,7 @@ Result KPageTableBase::OpenMemoryRangeForUnmapDeviceAddressSpace(MemoryRange* ou KMemoryAttribute::DeviceShared | KMemoryAttribute::Locked, KMemoryAttribute::DeviceShared)); // We got the range, so open it. - out->Open(m_system.Kernel()); + out->Open(); R_SUCCEED(); } @@ -3697,7 +3697,7 @@ Result KPageTableBase::OpenMemoryRangeForProcessCacheOperation(MemoryRange* out, KMemoryAttribute::None)); // We got the range, so open it. - out->Open(m_system.Kernel()); + out->Open(); R_SUCCEED(); } @@ -3710,7 +3710,7 @@ Result KPageTableBase::CopyMemoryFromLinearToUser( R_UNLESS(this->Contains(src_addr, size), ResultInvalidCurrentMemory); // Get the destination memory reference. - auto& dst_memory = GetCurrentMemory(m_system.Kernel()); + auto& dst_memory = GetCurrentMemory(m_kernel); // Copy the memory. { @@ -3745,7 +3745,7 @@ Result KPageTableBase::CopyMemoryFromLinearToUser( if (cur_size >= sizeof(u32)) { const size_t copy_size = Common::AlignDown(cur_size, sizeof(u32)); R_UNLESS(dst_memory.WriteBlock(dst_addr, - GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), + GetLinearMappedVirtualPointer(m_kernel, cur_addr), copy_size), ResultInvalidCurrentMemory); @@ -3757,7 +3757,7 @@ Result KPageTableBase::CopyMemoryFromLinearToUser( // Copy remaining data. if (cur_size > 0) { R_UNLESS(dst_memory.WriteBlock( - dst_addr, GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), cur_size), + dst_addr, GetLinearMappedVirtualPointer(m_kernel, cur_addr), cur_size), ResultInvalidCurrentMemory); } @@ -3836,7 +3836,7 @@ Result KPageTableBase::CopyMemoryFromLinearToKernel( R_UNLESS(IsLinearMappedPhysicalAddress(cur_addr), ResultInvalidCurrentMemory); // Copy the data. - std::memcpy(buffer, GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), cur_size); + std::memcpy(buffer, GetLinearMappedVirtualPointer(m_kernel, cur_addr), cur_size); R_SUCCEED(); }; @@ -3884,7 +3884,7 @@ Result KPageTableBase::CopyMemoryFromUserToLinear( R_UNLESS(this->Contains(dst_addr, size), ResultInvalidCurrentMemory); // Get the source memory reference. - auto& src_memory = GetCurrentMemory(m_system.Kernel()); + auto& src_memory = GetCurrentMemory(m_kernel); // Copy the memory. { @@ -3919,7 +3919,7 @@ Result KPageTableBase::CopyMemoryFromUserToLinear( if (cur_size >= sizeof(u32)) { const size_t copy_size = Common::AlignDown(cur_size, sizeof(u32)); R_UNLESS(src_memory.ReadBlock(src_addr, - GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), + GetLinearMappedVirtualPointer(m_kernel, cur_addr), copy_size), ResultInvalidCurrentMemory); src_addr += copy_size; @@ -3930,7 +3930,7 @@ Result KPageTableBase::CopyMemoryFromUserToLinear( // Copy remaining data. if (cur_size > 0) { R_UNLESS(src_memory.ReadBlock( - src_addr, GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), cur_size), + src_addr, GetLinearMappedVirtualPointer(m_kernel, cur_addr), cur_size), ResultInvalidCurrentMemory); } @@ -4011,7 +4011,7 @@ Result KPageTableBase::CopyMemoryFromKernelToLinear(KProcessAddress dst_addr, si R_UNLESS(IsLinearMappedPhysicalAddress(cur_addr), ResultInvalidCurrentMemory); // Copy the data. - std::memcpy(GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), buffer, cur_size); + std::memcpy(GetLinearMappedVirtualPointer(m_kernel, cur_addr), buffer, cur_size); R_SUCCEED(); }; @@ -4162,8 +4162,8 @@ Result KPageTableBase::CopyMemoryFromHeapToHeap( R_UNLESS(IsHeapPhysicalAddress(cur_dst_addr), ResultInvalidCurrentMemory); // Copy the data. - std::memcpy(GetHeapVirtualPointer(m_system.Kernel(), cur_dst_addr), - GetHeapVirtualPointer(m_system.Kernel(), cur_src_addr), cur_copy_size); + std::memcpy(GetHeapVirtualPointer(m_kernel, cur_dst_addr), + GetHeapVirtualPointer(m_kernel, cur_src_addr), cur_copy_size); // Update. cur_src_block_addr = src_next_entry.phys_addr; @@ -4296,8 +4296,8 @@ Result KPageTableBase::CopyMemoryFromHeapToHeapWithoutCheckDestination( R_UNLESS(IsHeapPhysicalAddress(cur_dst_addr), ResultInvalidCurrentMemory); // Copy the data. - std::memcpy(GetHeapVirtualPointer(m_system.Kernel(), cur_dst_addr), - GetHeapVirtualPointer(m_system.Kernel(), cur_src_addr), cur_copy_size); + std::memcpy(GetHeapVirtualPointer(m_kernel, cur_dst_addr), + GetHeapVirtualPointer(m_kernel, cur_src_addr), cur_copy_size); // Update. cur_src_block_addr = src_next_entry.phys_addr; @@ -4493,7 +4493,7 @@ Result KPageTableBase::SetupForIpcServer(KProcessAddress* out_addr, size_t size, // Reserve space for any partial pages we allocate. const size_t unmapped_size = aligned_src_size - mapping_src_size; - KScopedResourceReservation memory_reservation(m_system.Kernel(), + KScopedResourceReservation memory_reservation( m_resource_limit, Svc::LimitableResource::PhysicalMemoryMax, unmapped_size); R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); @@ -4506,10 +4506,10 @@ Result KPageTableBase::SetupForIpcServer(KProcessAddress* out_addr, size_t size, // free on scope exit. SCOPE_EXIT { if (start_partial_page != 0) { - m_system.Kernel().MemoryManager().Close(start_partial_page, 1); + m_kernel.MemoryManager().Close(start_partial_page, 1); } if (end_partial_page != 0) { - m_system.Kernel().MemoryManager().Close(end_partial_page, 1); + m_kernel.MemoryManager().Close(end_partial_page, 1); } }; @@ -4526,7 +4526,7 @@ Result KPageTableBase::SetupForIpcServer(KProcessAddress* out_addr, size_t size, // Allocate the start page as needed. if (aligned_src_start < mapping_src_start) { start_partial_page = - m_system.Kernel().MemoryManager().AllocateAndOpenContinuous(1, 1, m_allocate_option); + m_kernel.MemoryManager().AllocateAndOpenContinuous(1, 1, m_allocate_option); R_UNLESS(start_partial_page != 0, ResultOutOfMemory); } @@ -4534,7 +4534,7 @@ Result KPageTableBase::SetupForIpcServer(KProcessAddress* out_addr, size_t size, if (mapping_src_end < aligned_src_end && (aligned_src_start < mapping_src_end || aligned_src_start == mapping_src_start)) { end_partial_page = - m_system.Kernel().MemoryManager().AllocateAndOpenContinuous(1, 1, m_allocate_option); + m_kernel.MemoryManager().AllocateAndOpenContinuous(1, 1, m_allocate_option); R_UNLESS(end_partial_page != 0, ResultOutOfMemory); } @@ -4560,7 +4560,7 @@ Result KPageTableBase::SetupForIpcServer(KProcessAddress* out_addr, size_t size, // Map the start page, if we have one. if (start_partial_page != 0) { // Ensure the page holds correct data. - u8* const start_partial_virt = GetHeapVirtualPointer(m_system.Kernel(), start_partial_page); + u8* const start_partial_virt = GetHeapVirtualPointer(m_kernel, start_partial_page); if (send) { const size_t partial_offset = src_start - aligned_src_start; size_t copy_size, clear_size; @@ -4574,7 +4574,7 @@ Result KPageTableBase::SetupForIpcServer(KProcessAddress* out_addr, size_t size, std::memset(start_partial_virt, fill_val, partial_offset); std::memcpy(start_partial_virt + partial_offset, - GetHeapVirtualPointer(m_system.Kernel(), cur_block_addr) + partial_offset, + GetHeapVirtualPointer(m_kernel, cur_block_addr) + partial_offset, copy_size); if (clear_size > 0) { std::memset(start_partial_virt + partial_offset + copy_size, fill_val, clear_size); @@ -4663,10 +4663,10 @@ Result KPageTableBase::SetupForIpcServer(KProcessAddress* out_addr, size_t size, // Map the end page, if we have one. if (end_partial_page != 0) { // Ensure the page holds correct data. - u8* const end_partial_virt = GetHeapVirtualPointer(m_system.Kernel(), end_partial_page); + u8* const end_partial_virt = GetHeapVirtualPointer(m_kernel, end_partial_page); if (send) { const size_t copy_size = src_end - mapping_src_end; - std::memcpy(end_partial_virt, GetHeapVirtualPointer(m_system.Kernel(), cur_block_addr), + std::memcpy(end_partial_virt, GetHeapVirtualPointer(m_kernel, cur_block_addr), copy_size); std::memset(end_partial_virt + copy_size, fill_val, PageSize - copy_size); } else { @@ -4799,7 +4799,7 @@ Result KPageTableBase::CleanupForIpcServer(KProcessAddress address, size_t size, const KProcessAddress mapping_start = Common::AlignUp(GetInteger(address), PageSize); const KProcessAddress mapping_end = Common::AlignDown(GetInteger(address) + size, PageSize); const size_t mapping_size = (mapping_start < mapping_end) ? mapping_end - mapping_start : 0; - m_resource_limit->Release(m_system.Kernel(), Svc::LimitableResource::PhysicalMemoryMax, + m_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, aligned_size - mapping_size); R_SUCCEED(); @@ -5168,20 +5168,20 @@ Result KPageTableBase::MapPhysicalMemory(KProcessAddress address, size_t size) { // Allocate and map the memory. { // Reserve the memory from the process resource limit. - KScopedResourceReservation memory_reservation(m_system.Kernel(), + KScopedResourceReservation memory_reservation( m_resource_limit, Svc::LimitableResource::PhysicalMemoryMax, size - mapped_size); R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); // Allocate pages for the new memory. - KPageGroup pg(m_system.Kernel(), m_block_info_manager); - R_TRY(m_system.Kernel().MemoryManager().AllocateForProcess( + KPageGroup pg(m_kernel, m_block_info_manager); + R_TRY(m_kernel.MemoryManager().AllocateForProcess( std::addressof(pg), (size - mapped_size) / PageSize, m_allocate_option, - GetCurrentProcess(m_system.Kernel()).GetId(), m_heap_fill_value)); + GetCurrentProcess(m_kernel).GetId(), m_heap_fill_value)); // If we fail in the next bit (or retry), we need to cleanup the pages. auto pg_guard = SCOPE_GUARD { - pg.OpenFirst(m_system.Kernel()); - pg.Close(m_system.Kernel()); + pg.OpenFirst(); + pg.Close(); }; // Map the memory. @@ -5304,12 +5304,12 @@ Result KPageTableBase::MapPhysicalMemory(KProcessAddress address, size_t size) { } // Release any remaining unmapped memory. - m_system.Kernel().MemoryManager().OpenFirst(pg_phys_addr, pg_pages); - m_system.Kernel().MemoryManager().Close(pg_phys_addr, pg_pages); + m_kernel.MemoryManager().OpenFirst(pg_phys_addr, pg_pages); + m_kernel.MemoryManager().Close(pg_phys_addr, pg_pages); for (++pg_it; pg_it != pg.end(); ++pg_it) { - m_system.Kernel().MemoryManager().OpenFirst(pg_it->GetAddress(), + m_kernel.MemoryManager().OpenFirst(pg_it->GetAddress(), pg_it->GetNumPages()); - m_system.Kernel().MemoryManager().Close(pg_it->GetAddress(), pg_it->GetNumPages()); + m_kernel.MemoryManager().Close(pg_it->GetAddress(), pg_it->GetNumPages()); } }; @@ -5337,11 +5337,11 @@ Result KPageTableBase::MapPhysicalMemory(KProcessAddress address, size_t size) { // While we have pages to map, map them. { // Create a page group for the current mapping range. - KPageGroup cur_pg(m_system.Kernel(), m_block_info_manager); + KPageGroup cur_pg(m_kernel, m_block_info_manager); { ON_RESULT_FAILURE_2 { - cur_pg.OpenFirst(m_system.Kernel()); - cur_pg.Close(m_system.Kernel()); + cur_pg.OpenFirst(); + cur_pg.Close(); }; size_t remain_pages = map_pages; @@ -5541,7 +5541,7 @@ Result KPageTableBase::UnmapPhysicalMemory(KProcessAddress address, size_t size) // Release the memory resource. m_mapped_physical_memory_size -= mapped_size; - m_resource_limit->Release(m_system.Kernel(), Svc::LimitableResource::PhysicalMemoryMax, mapped_size); + m_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, mapped_size); // Update memory blocks. m_memory_block_manager.Update(std::addressof(allocator), address, size / PageSize, @@ -5706,9 +5706,9 @@ Result KPageTableBase::Operate(PageLinkedList* page_list, KProcessAddress virt_a const bool separate_heap = operation == OperationType::UnmapPhysical; // Ensure that any pages we track are closed on exit. - KPageGroup pages_to_close(m_system.Kernel(), this->GetBlockInfoManager()); + KPageGroup pages_to_close(m_kernel, this->GetBlockInfoManager()); SCOPE_EXIT { - pages_to_close.CloseAndReset(m_system.Kernel()); + pages_to_close.CloseAndReset(); }; // Make a page group representing the region to unmap. @@ -5727,7 +5727,7 @@ Result KPageTableBase::Operate(PageLinkedList* page_list, KProcessAddress virt_a // Open references to pages, if we should. if (this->IsHeapPhysicalAddress(phys_addr)) { - m_system.Kernel().MemoryManager().Open(phys_addr, num_pages); + m_kernel.MemoryManager().Open(phys_addr, num_pages); } R_SUCCEED(); @@ -5767,7 +5767,7 @@ Result KPageTableBase::Operate(PageLinkedList* page_list, KProcessAddress virt_a const bool separate_heap = operation == OperationType::MapFirstGroupPhysical; // We want to maintain a new reference to every page in the group. - KScopedPageGroup spg(m_system.Kernel(), page_group, operation == OperationType::MapGroup); + KScopedPageGroup spg(page_group, operation == OperationType::MapGroup); for (const auto& node : page_group) { const size_t size{node.GetNumPages() * PageSize}; diff --git a/src/core/hle/kernel/k_page_table_base.h b/src/core/hle/kernel/k_page_table_base.h index 160e722985..726fad989f 100644 --- a/src/core/hle/kernel/k_page_table_base.h +++ b/src/core/hle/kernel/k_page_table_base.h @@ -61,12 +61,14 @@ public: class MemoryRange { private: - KPhysicalAddress m_address = 0; - size_t m_size = 0; - bool m_heap = false; + KernelCore& m_kernel; + KPhysicalAddress m_address; + size_t m_size; + bool m_heap; public: - explicit MemoryRange() : m_address(0), m_size(0), m_heap(false) {} + explicit MemoryRange(KernelCore& kernel) + : m_kernel(kernel), m_address(0), m_size(0), m_heap(false) {} void Set(KPhysicalAddress address, size_t size, bool heap) { m_address = address; @@ -84,8 +86,8 @@ public: return m_heap; } - void Open(KernelCore& kernel); - void Close(KernelCore& kernel); + void Open(); + void Close(); }; protected: @@ -187,6 +189,7 @@ private: }; private: + KernelCore& m_kernel; Core::System& m_system; KProcessAddress m_address_space_start{}; KProcessAddress m_address_space_end{}; @@ -326,35 +329,35 @@ protected: bool IsLinearMappedPhysicalAddress(KPhysicalAddress phys_addr) { ASSERT(this->IsLockedByCurrentThread()); - return m_system.Kernel().MemoryLayout().IsLinearMappedPhysicalAddress( + return m_kernel.MemoryLayout().IsLinearMappedPhysicalAddress( m_cached_physical_linear_region, phys_addr); } bool IsLinearMappedPhysicalAddress(KPhysicalAddress phys_addr, size_t size) { ASSERT(this->IsLockedByCurrentThread()); - return m_system.Kernel().MemoryLayout().IsLinearMappedPhysicalAddress( + return m_kernel.MemoryLayout().IsLinearMappedPhysicalAddress( m_cached_physical_linear_region, phys_addr, size); } bool IsHeapPhysicalAddress(KPhysicalAddress phys_addr) { ASSERT(this->IsLockedByCurrentThread()); - return m_system.Kernel().MemoryLayout().IsHeapPhysicalAddress(m_cached_physical_heap_region, + return m_kernel.MemoryLayout().IsHeapPhysicalAddress(m_cached_physical_heap_region, phys_addr); } bool IsHeapPhysicalAddress(KPhysicalAddress phys_addr, size_t size) { ASSERT(this->IsLockedByCurrentThread()); - return m_system.Kernel().MemoryLayout().IsHeapPhysicalAddress(m_cached_physical_heap_region, + return m_kernel.MemoryLayout().IsHeapPhysicalAddress(m_cached_physical_heap_region, phys_addr, size); } bool IsHeapPhysicalAddressForFinalize(KPhysicalAddress phys_addr) { ASSERT(!this->IsLockedByCurrentThread()); - return m_system.Kernel().MemoryLayout().IsHeapPhysicalAddress(m_cached_physical_heap_region, + return m_kernel.MemoryLayout().IsHeapPhysicalAddress(m_cached_physical_heap_region, phys_addr); } @@ -741,15 +744,15 @@ public: // Member heap u8* GetHeapVirtualPointer(KPhysicalAddress addr) { - return GetHeapVirtualPointer(m_system.Kernel(), addr); + return GetHeapVirtualPointer(m_kernel, addr); } KPhysicalAddress GetHeapPhysicalAddress(KVirtualAddress addr) { - return GetHeapPhysicalAddress(m_system.Kernel(), addr); + return GetHeapPhysicalAddress(m_kernel, addr); } KVirtualAddress GetHeapVirtualAddress(KPhysicalAddress addr) { - return GetHeapVirtualAddress(m_system.Kernel(), addr); + return GetHeapVirtualAddress(m_kernel, addr); } // TODO: GetPageTableVirtualAddress diff --git a/src/core/hle/kernel/k_port.cpp b/src/core/hle/kernel/k_port.cpp index f64d983e0c..e5f5d8028c 100644 --- a/src/core/hle/kernel/k_port.cpp +++ b/src/core/hle/kernel/k_port.cpp @@ -1,12 +1,8 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include "core/hle/kernel/k_port.h" #include "core/hle/kernel/k_scheduler.h" -#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/svc_results.h" namespace Kernel { @@ -16,15 +12,15 @@ KPort::KPort(KernelCore& kernel) KPort::~KPort() = default; -void KPort::Initialize(KernelCore& kernel, s32 max_sessions, bool is_light, uintptr_t name) { +void KPort::Initialize(s32 max_sessions, bool is_light, uintptr_t name) { // Open a new reference count to the initialized port. - this->Open(kernel); + this->Open(); // Create and initialize our server/client pair. KAutoObject::Create(std::addressof(m_server)); KAutoObject::Create(std::addressof(m_client)); - m_server.Initialize(kernel, this); - m_client.Initialize(kernel, this, max_sessions); + m_server.Initialize(this); + m_client.Initialize(this, max_sessions); // Set our member variables. m_is_light = is_light; @@ -32,38 +28,42 @@ void KPort::Initialize(KernelCore& kernel, s32 max_sessions, bool is_light, uint m_state = State::Normal; } -void KPort::OnClientClosed(KernelCore& kernel) { - KScopedSchedulerLock sl{kernel}; +void KPort::OnClientClosed() { + KScopedSchedulerLock sl{m_kernel}; if (m_state == State::Normal) { m_state = State::ClientClosed; } } -void KPort::OnServerClosed(KernelCore& kernel) { - KScopedSchedulerLock sl{kernel}; +void KPort::OnServerClosed() { + KScopedSchedulerLock sl{m_kernel}; if (m_state == State::Normal) { m_state = State::ServerClosed; } } -bool KPort::IsServerClosed(KernelCore& kernel) const { - KScopedSchedulerLock sl{kernel}; +bool KPort::IsServerClosed() const { + KScopedSchedulerLock sl{m_kernel}; return m_state == State::ServerClosed; } -Result KPort::EnqueueSession(KernelCore& kernel, KServerSession* session) { - KScopedSchedulerLock sl{kernel}; +Result KPort::EnqueueSession(KServerSession* session) { + KScopedSchedulerLock sl{m_kernel}; + R_UNLESS(m_state == State::Normal, ResultPortClosed); - m_server.EnqueueSession(kernel, session); + + m_server.EnqueueSession(session); R_SUCCEED(); } -Result KPort::EnqueueSession(KernelCore& kernel, KLightServerSession* session) { - KScopedSchedulerLock sl{kernel}; +Result KPort::EnqueueSession(KLightServerSession* session) { + KScopedSchedulerLock sl{m_kernel}; + R_UNLESS(m_state == State::Normal, ResultPortClosed); - m_server.EnqueueSession(kernel, session); + + m_server.EnqueueSession(session); R_SUCCEED(); } diff --git a/src/core/hle/kernel/k_port.h b/src/core/hle/kernel/k_port.h index 698f794538..26f5f14eff 100644 --- a/src/core/hle/kernel/k_port.h +++ b/src/core/hle/kernel/k_port.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -26,11 +23,11 @@ public: explicit KPort(KernelCore& kernel); ~KPort() override; - static void PostDestroy(KernelCore& kernel, uintptr_t arg) {} + static void PostDestroy(uintptr_t arg) {} - void Initialize(KernelCore& kernel, s32 max_sessions, bool is_light, uintptr_t name); - void OnClientClosed(KernelCore& kernel); - void OnServerClosed(KernelCore& kernel); + void Initialize(s32 max_sessions, bool is_light, uintptr_t name); + void OnClientClosed(); + void OnServerClosed(); uintptr_t GetName() const { return m_name; @@ -39,10 +36,10 @@ public: return m_is_light; } - bool IsServerClosed(KernelCore& kernel) const; + bool IsServerClosed() const; - Result EnqueueSession(KernelCore& kernel, KServerSession* session); - Result EnqueueSession(KernelCore& kernel, KLightServerSession* session); + Result EnqueueSession(KServerSession* session); + Result EnqueueSession(KLightServerSession* session); KClientPort& GetClientPort() { return m_client; diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index 7308b0ff87..f737a18736 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp @@ -28,7 +28,8 @@ namespace Kernel { namespace { -Result TerminateChildren(KernelCore& kernel, KProcess* process, const KThread* thread_to_not_terminate) { +Result TerminateChildren(KernelCore& kernel, KProcess* process, + const KThread* thread_to_not_terminate) { // Request that all children threads terminate. { KScopedLightLock proc_lk(process->GetListLock()); @@ -40,14 +41,14 @@ Result TerminateChildren(KernelCore& kernel, KProcess* process, const KThread* t // This is valid because the only caller which uses non-nullptr as argument uses // GetCurrentThreadPointer(), but it's still notable because it seems incorrect at // first glance. - process->UnpinCurrentThread(kernel); + process->UnpinCurrentThread(); } auto& thread_list = process->GetThreadList(); for (auto it = thread_list.begin(); it != thread_list.end(); ++it) { if (KThread* thread = std::addressof(*it); thread != thread_to_not_terminate) { if (thread->GetState() != ThreadState::Terminated) { - thread->RequestTerminate(kernel); + thread->RequestTerminate(); } } } @@ -64,7 +65,7 @@ Result TerminateChildren(KernelCore& kernel, KProcess* process, const KThread* t for (auto it = thread_list.begin(); it != thread_list.end(); ++it) { if (KThread* thread = std::addressof(*it); thread != thread_to_not_terminate) { if (thread->GetState() != ThreadState::Terminated) { - if (thread->Open(kernel)) { + if (thread->Open()) { cur_child = thread; break; } @@ -80,10 +81,11 @@ Result TerminateChildren(KernelCore& kernel, KProcess* process, const KThread* t // Terminate and close the thread. SCOPE_EXIT { - cur_child->Close(kernel); + cur_child->Close(); }; - if (const Result terminate_result = cur_child->Terminate(kernel); ResultTerminationRequested == terminate_result) { + if (const Result terminate_result = cur_child->Terminate(); + ResultTerminationRequested == terminate_result) { R_THROW(terminate_result); } } @@ -99,21 +101,21 @@ public: explicit ThreadQueueImplForKProcessEnterUserException(KernelCore& kernel, KThread** t) : KThreadQueue(kernel), m_exception_thread(t) {} - virtual void EndWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result) override { + virtual void EndWait(KThread* waiting_thread, Result wait_result) override { // Set the exception thread. *m_exception_thread = waiting_thread; // Invoke the base end wait handler. - KThreadQueue::EndWait(kernel, waiting_thread, wait_result); + KThreadQueue::EndWait(waiting_thread, wait_result); } - virtual void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, + virtual void CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { // Remove the thread as a waiter on its mutex owner. - waiting_thread->GetLockOwner(kernel)->RemoveWaiter(kernel, waiting_thread); + waiting_thread->GetLockOwner()->RemoveWaiter(waiting_thread); // Invoke the base cancel wait handler. - KThreadQueue::CancelWait(kernel, waiting_thread, wait_result, cancel_timer_task); + KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); } }; @@ -126,12 +128,12 @@ void GenerateRandom(std::span out_random) { } // namespace -void KProcess::Finalize(KernelCore& kernel) { +void KProcess::Finalize() { // Delete the process local region. - this->DeleteThreadLocalRegion(kernel, m_plr_address); + this->DeleteThreadLocalRegion(m_plr_address); // Get the used memory size. - const size_t used_memory_size = this->GetUsedNonSystemUserPhysicalMemorySize(kernel); + const size_t used_memory_size = this->GetUsedNonSystemUserPhysicalMemorySize(); // Finalize the page table. m_page_table.Finalize(); @@ -140,10 +142,10 @@ void KProcess::Finalize(KernelCore& kernel) { if (m_system_resource) { if (m_system_resource->IsSecureResource()) { // Finalize optimized memory. If memory wasn't optimized, this is a no-op. - kernel.MemoryManager().FinalizeOptimizedMemory(this->GetId(), m_memory_pool); + m_kernel.MemoryManager().FinalizeOptimizedMemory(this->GetId(), m_memory_pool); } - m_system_resource->Close(kernel); + m_system_resource->Close(); m_system_resource = nullptr; } @@ -155,12 +157,12 @@ void KProcess::Finalize(KernelCore& kernel) { KSharedMemory* shmem = info->GetSharedMemory(); while (!info->Close()) { - shmem->Close(kernel); + shmem->Close(); } - shmem->Close(kernel); + shmem->Close(); it = m_shared_memory_list.erase(it); - KSharedMemoryInfo::Free(kernel, info); + KSharedMemoryInfo::Free(m_kernel, info); } } @@ -171,8 +173,9 @@ void KProcess::Finalize(KernelCore& kernel) { // Release memory to the resource limit. if (m_resource_limit != nullptr) { ASSERT(used_memory_size >= m_memory_release_hint); - m_resource_limit->Release(kernel, Svc::LimitableResource::PhysicalMemoryMax, used_memory_size, used_memory_size - m_memory_release_hint); - m_resource_limit->Close(kernel); + m_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, used_memory_size, + used_memory_size - m_memory_release_hint); + m_resource_limit->Close(); } // Clear expensive resources, as the destructor is not called for guest objects. @@ -182,14 +185,15 @@ void KProcess::Finalize(KernelCore& kernel) { m_exclusive_monitor.reset(); // Perform inherited finalization. - KSynchronizationObject::Finalize(kernel); + KSynchronizationObject::Finalize(); } -Result KProcess::Initialize(KernelCore& kernel, const Svc::CreateProcessParameter& params, KResourceLimit* res_limit, bool is_real) { +Result KProcess::Initialize(const Svc::CreateProcessParameter& params, KResourceLimit* res_limit, + bool is_real) { // TODO: remove this special case if (is_real) { // Create and clear the process local region. - R_TRY(this->CreateThreadLocalRegion(kernel, std::addressof(m_plr_address))); + R_TRY(this->CreateThreadLocalRegion(std::addressof(m_plr_address))); this->GetMemory().ZeroBlock(m_plr_address, Svc::ThreadLocalRegionSize); } @@ -255,7 +259,7 @@ Result KProcess::Initialize(KernelCore& kernel, const Svc::CreateProcessParamete // Open a reference to our resource limit. m_resource_limit = res_limit; - m_resource_limit->Open(kernel); + m_resource_limit->Open(); // We're initialized! m_is_initialized = true; @@ -263,7 +267,7 @@ Result KProcess::Initialize(KernelCore& kernel, const Svc::CreateProcessParamete R_SUCCEED(); } -Result KProcess::Initialize(KernelCore& kernel, const Svc::CreateProcessParameter& params, const KPageGroup& pg, +Result KProcess::Initialize(const Svc::CreateProcessParameter& params, const KPageGroup& pg, std::span caps, KResourceLimit* res_limit, KMemoryManager::Pool pool, bool immortal) { ASSERT(res_limit != nullptr); @@ -279,33 +283,34 @@ Result KProcess::Initialize(KernelCore& kernel, const Svc::CreateProcessParamete if (const size_t system_resource_num_pages = params.system_resource_num_pages; system_resource_num_pages != 0) { // Create a secure system resource. - KSecureSystemResource* secure_resource = KSecureSystemResource::Create(kernel); + KSecureSystemResource* secure_resource = KSecureSystemResource::Create(m_kernel); R_UNLESS(secure_resource != nullptr, ResultOutOfResource); ON_RESULT_FAILURE { - secure_resource->Close(kernel); + secure_resource->Close(); }; // Initialize the secure resource. - R_TRY(secure_resource->Initialize(kernel, system_resource_num_pages * PageSize, res_limit, m_memory_pool)); + R_TRY(secure_resource->Initialize(system_resource_num_pages * PageSize, res_limit, + m_memory_pool)); // Set our system resource. m_system_resource = secure_resource; } else { // Use the system-wide system resource. const bool is_app = True(params.flags & Svc::CreateProcessFlag::IsApplication); - m_system_resource = std::addressof(is_app ? kernel.GetAppSystemResource() - : kernel.GetSystemSystemResource()); + m_system_resource = std::addressof(is_app ? m_kernel.GetAppSystemResource() + : m_kernel.GetSystemSystemResource()); m_is_default_application_system_resource = is_app; // Open reference to the system resource. - m_system_resource->Open(kernel); + m_system_resource->Open(); } // Ensure we clean up our secure resource, if we fail. ON_RESULT_FAILURE { - m_system_resource->Close(kernel); + m_system_resource->Close(); m_system_resource = nullptr; }; @@ -325,7 +330,7 @@ Result KProcess::Initialize(KernelCore& kernel, const Svc::CreateProcessParamete // Ensure our memory is initialized. m_memory.SetCurrentPageTable(*this); - m_memory.SetGPUDirtyManagers(kernel.System().GetGPUDirtyMemoryManager()); + m_memory.SetGPUDirtyManagers(m_kernel.System().GetGPUDirtyMemoryManager()); // Ensure we can insert the code region. R_UNLESS(m_page_table.CanContain(params.code_address, params.code_num_pages * PageSize, @@ -345,18 +350,18 @@ Result KProcess::Initialize(KernelCore& kernel, const Svc::CreateProcessParamete } // Initialize the process id. - m_process_id = kernel.CreateNewUserProcessID(); + m_process_id = m_kernel.CreateNewUserProcessID(); ASSERT(InitialProcessIdMin <= m_process_id); ASSERT(m_process_id <= InitialProcessIdMax); // Initialize the rest of the process. - R_TRY(this->Initialize(kernel, params, res_limit, true)); + R_TRY(this->Initialize(params, res_limit, true)); // We succeeded! R_SUCCEED(); } -Result KProcess::Initialize(KernelCore& kernel, const Svc::CreateProcessParameter& params, +Result KProcess::Initialize(const Svc::CreateProcessParameter& params, std::span user_caps, KResourceLimit* res_limit, KMemoryManager::Pool pool, KProcessAddress aslr_space_start) { ASSERT(res_limit != nullptr); @@ -373,22 +378,22 @@ Result KProcess::Initialize(KernelCore& kernel, const Svc::CreateProcessParamete const size_t system_resource_size = system_resource_num_pages * PageSize; // Reserve memory for our code resource. - KScopedResourceReservation memory_reservation(kernel, + KScopedResourceReservation memory_reservation( res_limit, Svc::LimitableResource::PhysicalMemoryMax, code_size); R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); // Setup our system resource. if (system_resource_num_pages != 0) { // Create a secure system resource. - KSecureSystemResource* secure_resource = KSecureSystemResource::Create(kernel); + KSecureSystemResource* secure_resource = KSecureSystemResource::Create(m_kernel); R_UNLESS(secure_resource != nullptr, ResultOutOfResource); ON_RESULT_FAILURE { - secure_resource->Close(kernel); + secure_resource->Close(); }; // Initialize the secure resource. - R_TRY(secure_resource->Initialize(kernel, system_resource_size, res_limit, m_memory_pool)); + R_TRY(secure_resource->Initialize(system_resource_size, res_limit, m_memory_pool)); // Set our system resource. m_system_resource = secure_resource; @@ -396,18 +401,18 @@ Result KProcess::Initialize(KernelCore& kernel, const Svc::CreateProcessParamete } else { // Use the system-wide system resource. const bool is_app = True(params.flags & Svc::CreateProcessFlag::IsApplication); - m_system_resource = std::addressof(is_app ? kernel.GetAppSystemResource() - : kernel.GetSystemSystemResource()); + m_system_resource = std::addressof(is_app ? m_kernel.GetAppSystemResource() + : m_kernel.GetSystemSystemResource()); m_is_default_application_system_resource = is_app; // Open reference to the system resource. - m_system_resource->Open(kernel); + m_system_resource->Open(); } // Ensure we clean up our secure resource, if we fail. ON_RESULT_FAILURE { - m_system_resource->Close(kernel); + m_system_resource->Close(); m_system_resource = nullptr; }; @@ -427,7 +432,7 @@ Result KProcess::Initialize(KernelCore& kernel, const Svc::CreateProcessParamete // Ensure our memory is initialized. m_memory.SetCurrentPageTable(*this); - m_memory.SetGPUDirtyManagers(kernel.System().GetGPUDirtyMemoryManager()); + m_memory.SetGPUDirtyManagers(m_kernel.System().GetGPUDirtyMemoryManager()); // Ensure we can insert the code region. R_UNLESS(m_page_table.CanContain(params.code_address, code_size, KMemoryState::Code), @@ -446,99 +451,101 @@ Result KProcess::Initialize(KernelCore& kernel, const Svc::CreateProcessParamete } // Initialize the process id. - m_process_id = kernel.CreateNewUserProcessID(); + m_process_id = m_kernel.CreateNewUserProcessID(); ASSERT(ProcessIdMin <= m_process_id); ASSERT(m_process_id <= ProcessIdMax); // If we should optimize memory allocations, do so. if (m_system_resource->IsSecureResource() && True(params.flags & Svc::CreateProcessFlag::OptimizeMemoryAllocation)) { - R_TRY(kernel.MemoryManager().InitializeOptimizedMemory(m_process_id, pool)); + R_TRY(m_kernel.MemoryManager().InitializeOptimizedMemory(m_process_id, pool)); } // Initialize the rest of the process. - R_TRY(this->Initialize(kernel, params, res_limit, true)); + R_TRY(this->Initialize(params, res_limit, true)); // We succeeded, so commit our memory reservation. memory_reservation.Commit(); R_SUCCEED(); } -void KProcess::DoWorkerTaskImpl(KernelCore& kernel) { +void KProcess::DoWorkerTaskImpl() { // Terminate child threads. - TerminateChildren(kernel, this, nullptr); + TerminateChildren(m_kernel, this, nullptr); // Finalize the handle table, if we're not immortal. if (!m_is_immortal && m_is_handle_table_initialized) { - this->FinalizeHandleTable(kernel); + this->FinalizeHandleTable(); } // Finish termination. - this->FinishTermination(kernel); + this->FinishTermination(); } -Result KProcess::StartTermination(KernelCore& kernel) { +Result KProcess::StartTermination() { // Finalize the handle table when we're done, if the process isn't immortal. SCOPE_EXIT { if (!m_is_immortal) { - this->FinalizeHandleTable(kernel); + this->FinalizeHandleTable(); } }; // Terminate child threads other than the current one. - R_RETURN(TerminateChildren(kernel, this, GetCurrentThreadPointer(kernel))); + R_RETURN(TerminateChildren(m_kernel, this, GetCurrentThreadPointer(m_kernel))); } -void KProcess::FinishTermination(KernelCore& kernel) { +void KProcess::FinishTermination() { // Only allow termination to occur if the process isn't immortal. if (!m_is_immortal) { // Release resource limit hint. if (m_resource_limit != nullptr) { - m_memory_release_hint = this->GetUsedNonSystemUserPhysicalMemorySize(kernel); - m_resource_limit->Release(kernel, Svc::LimitableResource::PhysicalMemoryMax, 0, m_memory_release_hint); + m_memory_release_hint = this->GetUsedNonSystemUserPhysicalMemorySize(); + m_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, 0, + m_memory_release_hint); } // Change state. { - KScopedSchedulerLock sl(kernel); - this->ChangeState(kernel, State::Terminated); + KScopedSchedulerLock sl(m_kernel); + this->ChangeState(State::Terminated); } // Close. - this->Close(kernel); + this->Close(); } } -void KProcess::Exit(KernelCore& kernel) { +void KProcess::Exit() { // Determine whether we need to start terminating bool needs_terminate = false; { KScopedLightLock lk(m_state_lock); - KScopedSchedulerLock sl(kernel); + KScopedSchedulerLock sl(m_kernel); ASSERT(m_state != State::Created); ASSERT(m_state != State::CreatedAttached); ASSERT(m_state != State::Crashed); ASSERT(m_state != State::Terminated); - if (m_state == State::Running || m_state == State::RunningAttached || m_state == State::DebugBreak) { - this->ChangeState(kernel, State::Terminating); + if (m_state == State::Running || m_state == State::RunningAttached || + m_state == State::DebugBreak) { + this->ChangeState(State::Terminating); needs_terminate = true; } } // If we need to start termination, do so. if (needs_terminate) { - this->StartTermination(kernel); + this->StartTermination(); // Register the process as a work task. - kernel.WorkerTaskManager().AddTask(kernel, KWorkerTaskManager::WorkerType::Exit, this); + m_kernel.WorkerTaskManager().AddTask(m_kernel, KWorkerTaskManager::WorkerType::Exit, this); } // Exit the current thread. - GetCurrentThread(kernel).Exit(kernel); + GetCurrentThread(m_kernel).Exit(); } -Result KProcess::Terminate(KernelCore& kernel) { +Result KProcess::Terminate() { // Determine whether we need to start terminating. bool needs_terminate = false; { @@ -548,11 +555,11 @@ Result KProcess::Terminate(KernelCore& kernel) { R_UNLESS(m_state != State::Created, ResultInvalidState); R_UNLESS(m_state != State::CreatedAttached, ResultInvalidState); - KScopedSchedulerLock sl(kernel); + KScopedSchedulerLock sl(m_kernel); if (m_state == State::Running || m_state == State::RunningAttached || m_state == State::Crashed || m_state == State::DebugBreak) { - this->ChangeState(kernel, State::Terminating); + this->ChangeState(State::Terminating); needs_terminate = true; } } @@ -560,19 +567,20 @@ Result KProcess::Terminate(KernelCore& kernel) { // If we need to terminate, do so. if (needs_terminate) { // Start termination. - if (R_SUCCEEDED(this->StartTermination(kernel))) { + if (R_SUCCEEDED(this->StartTermination())) { // Finish termination. - this->FinishTermination(kernel); + this->FinishTermination(); } else { // Register the process as a work task. - kernel.WorkerTaskManager().AddTask(kernel, KWorkerTaskManager::WorkerType::Exit, this); + m_kernel.WorkerTaskManager().AddTask(m_kernel, KWorkerTaskManager::WorkerType::Exit, + this); } } R_SUCCEED(); } -Result KProcess::AddSharedMemory(KernelCore& kernel, KSharedMemory* shmem, KProcessAddress address, size_t size) { +Result KProcess::AddSharedMemory(KSharedMemory* shmem, KProcessAddress address, size_t size) { // Lock ourselves, to prevent concurrent access. KScopedLightLock lk(m_state_lock); @@ -588,7 +596,7 @@ Result KProcess::AddSharedMemory(KernelCore& kernel, KSharedMemory* shmem, KProc // If we didn't find an info, create one. if (info == nullptr) { // Allocate a new info. - info = KSharedMemoryInfo::Allocate(kernel); + info = KSharedMemoryInfo::Allocate(m_kernel); R_UNLESS(info != nullptr, ResultOutOfResource); // Initialize the info and add it to our list. @@ -597,13 +605,13 @@ Result KProcess::AddSharedMemory(KernelCore& kernel, KSharedMemory* shmem, KProc } // Open a reference to the shared memory and its info. - shmem->Open(kernel); + shmem->Open(); info->Open(); R_SUCCEED(); } -void KProcess::RemoveSharedMemory(KernelCore& kernel, KSharedMemory* shmem, KProcessAddress address, size_t size) { +void KProcess::RemoveSharedMemory(KSharedMemory* shmem, KProcessAddress address, size_t size) { // Lock ourselves, to prevent concurrent access. KScopedLightLock lk(m_state_lock); @@ -621,19 +629,19 @@ void KProcess::RemoveSharedMemory(KernelCore& kernel, KSharedMemory* shmem, KPro // Close a reference to the info and its memory. if (info->Close()) { m_shared_memory_list.erase(it); - KSharedMemoryInfo::Free(kernel, info); + KSharedMemoryInfo::Free(m_kernel, info); } - shmem->Close(kernel); + shmem->Close(); } -Result KProcess::CreateThreadLocalRegion(KernelCore& kernel, KProcessAddress* out) { +Result KProcess::CreateThreadLocalRegion(KProcessAddress* out) { KThreadLocalPage* tlp = nullptr; KProcessAddress tlr = 0; // See if we can get a region from a partially used TLP. { - KScopedSchedulerLock sl(kernel); + KScopedSchedulerLock sl(m_kernel); if (auto it = m_partially_used_tlp_tree.begin(); it != m_partially_used_tlp_tree.end()) { tlr = it->Reserve(); @@ -651,14 +659,14 @@ Result KProcess::CreateThreadLocalRegion(KernelCore& kernel, KProcessAddress* ou } // Allocate a new page. - tlp = KThreadLocalPage::Allocate(kernel); + tlp = KThreadLocalPage::Allocate(m_kernel); R_UNLESS(tlp != nullptr, ResultOutOfMemory); ON_RESULT_FAILURE { - KThreadLocalPage::Free(kernel, tlp); + KThreadLocalPage::Free(m_kernel, tlp); }; // Initialize the new page. - R_TRY(tlp->Initialize(kernel, this)); + R_TRY(tlp->Initialize(m_kernel, this)); // Reserve a TLR. tlr = tlp->Reserve(); @@ -666,7 +674,7 @@ Result KProcess::CreateThreadLocalRegion(KernelCore& kernel, KProcessAddress* ou // Insert into our tree. { - KScopedSchedulerLock sl(kernel); + KScopedSchedulerLock sl(m_kernel); if (tlp->IsAllUsed()) { m_fully_used_tlp_tree.insert(*tlp); } else { @@ -679,12 +687,12 @@ Result KProcess::CreateThreadLocalRegion(KernelCore& kernel, KProcessAddress* ou R_SUCCEED(); } -Result KProcess::DeleteThreadLocalRegion(KernelCore& kernel, KProcessAddress addr) { +Result KProcess::DeleteThreadLocalRegion(KProcessAddress addr) { KThreadLocalPage* page_to_free = nullptr; // Release the region. { - KScopedSchedulerLock sl(kernel); + KScopedSchedulerLock sl(m_kernel); // Try to find the page in the partially used list. auto it = m_partially_used_tlp_tree.find_key(Common::AlignDown(GetInteger(addr), PageSize)); @@ -721,56 +729,57 @@ Result KProcess::DeleteThreadLocalRegion(KernelCore& kernel, KProcessAddress add if (page_to_free != nullptr) { page_to_free->Finalize(); - KThreadLocalPage::Free(kernel, page_to_free); + KThreadLocalPage::Free(m_kernel, page_to_free); } R_SUCCEED(); } -bool KProcess::ReserveResource(KernelCore& kernel, Svc::LimitableResource which, s64 value) { +bool KProcess::ReserveResource(Svc::LimitableResource which, s64 value) { if (KResourceLimit* rl = this->GetResourceLimit(); rl != nullptr) { - return rl->Reserve(kernel, which, value); + return rl->Reserve(which, value); } else { return true; } } -bool KProcess::ReserveResource(KernelCore& kernel, Svc::LimitableResource which, s64 value, s64 timeout) { +bool KProcess::ReserveResource(Svc::LimitableResource which, s64 value, s64 timeout) { if (KResourceLimit* rl = this->GetResourceLimit(); rl != nullptr) { - return rl->Reserve(kernel, which, value, timeout); + return rl->Reserve(which, value, timeout); } else { return true; } } -void KProcess::ReleaseResource(KernelCore& kernel, Svc::LimitableResource which, s64 value) { +void KProcess::ReleaseResource(Svc::LimitableResource which, s64 value) { if (KResourceLimit* rl = this->GetResourceLimit(); rl != nullptr) { - rl->Release(kernel, which, value); + rl->Release(which, value); } } -void KProcess::ReleaseResource(KernelCore& kernel, Svc::LimitableResource which, s64 value, s64 hint) { +void KProcess::ReleaseResource(Svc::LimitableResource which, s64 value, s64 hint) { if (KResourceLimit* rl = this->GetResourceLimit(); rl != nullptr) { - rl->Release(kernel, which, value, hint); + rl->Release(which, value, hint); } } -void KProcess::IncrementRunningThreadCount(KernelCore& kernel) { +void KProcess::IncrementRunningThreadCount() { ASSERT(m_num_running_threads.load() >= 0); ++m_num_running_threads; } -void KProcess::DecrementRunningThreadCount(KernelCore& kernel) { +void KProcess::DecrementRunningThreadCount() { ASSERT(m_num_running_threads.load() > 0); + if (const auto prev = m_num_running_threads--; prev == 1) { - this->Terminate(kernel); + this->Terminate(); } } -bool KProcess::EnterUserException(KernelCore& kernel) { +bool KProcess::EnterUserException() { // Get the current thread. - KThread* cur_thread = GetCurrentThreadPointer(kernel); + KThread* cur_thread = GetCurrentThreadPointer(m_kernel); ASSERT(this == cur_thread->GetOwnerProcess()); // Check that we haven't already claimed the exception thread. @@ -779,13 +788,13 @@ bool KProcess::EnterUserException(KernelCore& kernel) { } // Create the wait queue we'll be using. - ThreadQueueImplForKProcessEnterUserException wait_queue(kernel, + ThreadQueueImplForKProcessEnterUserException wait_queue(m_kernel, std::addressof(m_exception_thread)); // Claim the exception thread. { // Lock the scheduler. - KScopedSchedulerLock sl(kernel); + KScopedSchedulerLock sl(m_kernel); // Check that we're not terminating. if (cur_thread->IsTerminationRequested()) { @@ -795,44 +804,45 @@ bool KProcess::EnterUserException(KernelCore& kernel) { // If we don't have an exception thread, we can just claim it directly. if (m_exception_thread == nullptr) { m_exception_thread = cur_thread; - KScheduler::SetSchedulerUpdateNeeded(kernel); + KScheduler::SetSchedulerUpdateNeeded(m_kernel); return true; } // Otherwise, we need to wait until we don't have an exception thread. // Add the current thread as a waiter on the current exception thread. - cur_thread->SetKernelAddressKey(uintptr_t(std::addressof(m_exception_thread)) | 1); - m_exception_thread->AddWaiter(kernel, cur_thread); + cur_thread->SetKernelAddressKey( + reinterpret_cast(std::addressof(m_exception_thread)) | 1); + m_exception_thread->AddWaiter(cur_thread); // Wait to claim the exception thread. - cur_thread->BeginWait(kernel, std::addressof(wait_queue)); + cur_thread->BeginWait(std::addressof(wait_queue)); } // If our wait didn't end due to thread termination, we succeeded. return ResultTerminationRequested != cur_thread->GetWaitResult(); } -bool KProcess::LeaveUserException(KernelCore& kernel) { - return this->ReleaseUserException(kernel, GetCurrentThreadPointer(kernel)); +bool KProcess::LeaveUserException() { + return this->ReleaseUserException(GetCurrentThreadPointer(m_kernel)); } -bool KProcess::ReleaseUserException(KernelCore& kernel, KThread* thread) { - KScopedSchedulerLock sl(kernel); +bool KProcess::ReleaseUserException(KThread* thread) { + KScopedSchedulerLock sl(m_kernel); if (m_exception_thread == thread) { m_exception_thread = nullptr; // Remove waiter thread. bool has_waiters; - if (KThread* next = thread->RemoveKernelWaiterByKey(kernel, + if (KThread* next = thread->RemoveKernelWaiterByKey( std::addressof(has_waiters), reinterpret_cast(std::addressof(m_exception_thread)) | 1); next != nullptr) { - next->EndWait(kernel, ResultSuccess); + next->EndWait(ResultSuccess); } - KScheduler::SetSchedulerUpdateNeeded(kernel); + KScheduler::SetSchedulerUpdateNeeded(m_kernel); return true; } else { @@ -840,19 +850,19 @@ bool KProcess::ReleaseUserException(KernelCore& kernel, KThread* thread) { } } -void KProcess::RegisterThread(KernelCore& kernel, KThread* thread) { +void KProcess::RegisterThread(KThread* thread) { KScopedLightLock lk(m_list_lock); m_thread_list.push_back(*thread); } -void KProcess::UnregisterThread(KernelCore& kernel, KThread* thread) { +void KProcess::UnregisterThread(KThread* thread) { KScopedLightLock lk(m_list_lock); m_thread_list.erase(m_thread_list.iterator_to(*thread)); } -size_t KProcess::GetUsedUserPhysicalMemorySize(KernelCore& kernel) const { +size_t KProcess::GetUsedUserPhysicalMemorySize() const { const size_t norm_size = m_page_table.GetNormalMemorySize(); const size_t other_size = m_code_size + m_main_thread_stack_size; const size_t sec_size = this->GetRequiredSecureMemorySizeNonDefault(); @@ -860,7 +870,7 @@ size_t KProcess::GetUsedUserPhysicalMemorySize(KernelCore& kernel) const { return norm_size + other_size + sec_size; } -size_t KProcess::GetTotalUserPhysicalMemorySize(KernelCore& kernel) const { +size_t KProcess::GetTotalUserPhysicalMemorySize() const { // Get the amount of free and used size. const size_t free_size = m_resource_limit->GetFreeValue(Svc::LimitableResource::PhysicalMemoryMax); @@ -879,18 +889,18 @@ size_t KProcess::GetTotalUserPhysicalMemorySize(KernelCore& kernel) const { if (used_size + free_size > max_size) { return max_size; } else { - return free_size + this->GetUsedUserPhysicalMemorySize(kernel); + return free_size + this->GetUsedUserPhysicalMemorySize(); } } -size_t KProcess::GetUsedNonSystemUserPhysicalMemorySize(KernelCore& kernel) const { +size_t KProcess::GetUsedNonSystemUserPhysicalMemorySize() const { const size_t norm_size = m_page_table.GetNormalMemorySize(); const size_t other_size = m_code_size + m_main_thread_stack_size; return norm_size + other_size; } -size_t KProcess::GetTotalNonSystemUserPhysicalMemorySize(KernelCore& kernel) const { +size_t KProcess::GetTotalNonSystemUserPhysicalMemorySize() const { // Get the amount of free and used size. const size_t free_size = m_resource_limit->GetFreeValue(Svc::LimitableResource::PhysicalMemoryMax); @@ -909,11 +919,11 @@ size_t KProcess::GetTotalNonSystemUserPhysicalMemorySize(KernelCore& kernel) con if (used_size + free_size > max_size) { return max_size - this->GetRequiredSecureMemorySizeNonDefault(); } else { - return free_size + this->GetUsedNonSystemUserPhysicalMemorySize(kernel); + return free_size + this->GetUsedNonSystemUserPhysicalMemorySize(); } } -Result KProcess::Run(KernelCore& kernel, s32 priority, size_t stack_size) { +Result KProcess::Run(s32 priority, size_t stack_size) { // Lock ourselves, to prevent concurrent access. KScopedLightLock lk(m_state_lock); @@ -922,7 +932,7 @@ Result KProcess::Run(KernelCore& kernel, s32 priority, size_t stack_size) { R_UNLESS(state == State::Created || state == State::CreatedAttached, ResultInvalidState); // Place a tentative reservation of a thread for this process. - KScopedResourceReservation thread_reservation(kernel, this, Svc::LimitableResource::ThreadCountMax); + KScopedResourceReservation thread_reservation(this, Svc::LimitableResource::ThreadCountMax); R_UNLESS(thread_reservation.Succeeded(), ResultLimitReached); // Ensure that we haven't already allocated stack. @@ -934,7 +944,7 @@ Result KProcess::Run(KernelCore& kernel, s32 priority, size_t stack_size) { R_UNLESS(stack_size + m_code_size >= m_code_size, ResultOutOfMemory); // Place a tentative reservation of memory for our new stack. - KScopedResourceReservation mem_reservation(kernel, this, Svc::LimitableResource::PhysicalMemoryMax, + KScopedResourceReservation mem_reservation(this, Svc::LimitableResource::PhysicalMemoryMax, stack_size); R_UNLESS(mem_reservation.Succeeded(), ResultLimitReached); @@ -964,29 +974,29 @@ Result KProcess::Run(KernelCore& kernel, s32 priority, size_t stack_size) { (m_main_thread_stack_size + m_code_size))); // Initialize our handle table. - R_TRY(this->InitializeHandleTable(kernel, m_capabilities.GetHandleTableSize())); + R_TRY(this->InitializeHandleTable(m_capabilities.GetHandleTableSize())); ON_RESULT_FAILURE_2 { - this->FinalizeHandleTable(kernel); + this->FinalizeHandleTable(); }; // Create a new thread for the process. - KThread* main_thread = KThread::Create(kernel); + KThread* main_thread = KThread::Create(m_kernel); R_UNLESS(main_thread != nullptr, ResultOutOfResource); SCOPE_EXIT { - main_thread->Close(kernel); + main_thread->Close(); }; // Initialize the thread. - R_TRY(KThread::InitializeUserThread(kernel.System(), main_thread, this->GetEntryPoint(), 0, + R_TRY(KThread::InitializeUserThread(m_kernel.System(), main_thread, this->GetEntryPoint(), 0, stack_top, priority, m_ideal_core_id, this)); // Register the thread, and commit our reservation. - KThread::Register(kernel, main_thread); + KThread::Register(m_kernel, main_thread); thread_reservation.Commit(); // Add the thread to our handle table. Handle thread_handle; - R_TRY(m_handle_table.Add(kernel, std::addressof(thread_handle), main_thread)); + R_TRY(m_handle_table.Add(std::addressof(thread_handle), main_thread)); // Set the thread arguments. Two distinct entry conventions: // * Kernel/NSO entry (no homebrew ABI): x0 = 0, x1 = thread_handle @@ -1014,21 +1024,21 @@ Result KProcess::Run(KernelCore& kernel, s32 priority, size_t stack_size) { this->GetMemory().Write32(GetInteger(main_thread->GetTlsAddress()) + 0x110, thread_handle); // Update our state. - this->ChangeState(kernel, (state == State::Created) ? State::Running : State::RunningAttached); + this->ChangeState((state == State::Created) ? State::Running : State::RunningAttached); ON_RESULT_FAILURE_2 { - this->ChangeState(kernel, state); + this->ChangeState(state); }; // Suspend for debug, if we should. - if (kernel.System().DebuggerEnabled()) { - main_thread->RequestSuspend(kernel, SuspendType::Debug); + if (m_kernel.System().DebuggerEnabled()) { + main_thread->RequestSuspend(SuspendType::Debug); } // Run our thread. - R_TRY(main_thread->Run(kernel)); + R_TRY(main_thread->Run()); // Open a reference to represent that we're running. - this->Open(kernel); + this->Open(); // We succeeded! Commit our memory reservation. mem_reservation.Commit(); @@ -1036,10 +1046,10 @@ Result KProcess::Run(KernelCore& kernel, s32 priority, size_t stack_size) { R_SUCCEED(); } -Result KProcess::Reset(KernelCore& kernel) { +Result KProcess::Reset() { // Lock the process and the scheduler. KScopedLightLock lk(m_state_lock); - KScopedSchedulerLock sl(kernel); + KScopedSchedulerLock sl(m_kernel); // Validate that we're in a state that we can reset. R_UNLESS(m_state != State::Terminated, ResultInvalidState); @@ -1050,11 +1060,11 @@ Result KProcess::Reset(KernelCore& kernel) { R_SUCCEED(); } -Result KProcess::SetActivity(KernelCore& kernel, Svc::ProcessActivity activity) { +Result KProcess::SetActivity(Svc::ProcessActivity activity) { // Lock ourselves and the scheduler. KScopedLightLock lk(m_state_lock); KScopedLightLock list_lk(m_list_lock); - KScopedSchedulerLock sl(kernel); + KScopedSchedulerLock sl(m_kernel); // Validate our state. R_UNLESS(m_state != State::Terminating, ResultInvalidState); @@ -1068,7 +1078,7 @@ Result KProcess::SetActivity(KernelCore& kernel, Svc::ProcessActivity activity) // Suspend all threads. auto end = this->GetThreadList().end(); for (auto it = this->GetThreadList().begin(); it != end; ++it) { - it->RequestSuspend(kernel, SuspendType::Process); + it->RequestSuspend(SuspendType::Process); } // Set ourselves as suspended. @@ -1082,7 +1092,7 @@ Result KProcess::SetActivity(KernelCore& kernel, Svc::ProcessActivity activity) // Resume all threads. auto end = this->GetThreadList().end(); for (auto it = this->GetThreadList().begin(); it != end; ++it) { - it->Resume(kernel, SuspendType::Process); + it->Resume(SuspendType::Process); } // Set ourselves as resumed. @@ -1092,54 +1102,54 @@ Result KProcess::SetActivity(KernelCore& kernel, Svc::ProcessActivity activity) R_SUCCEED(); } -void KProcess::PinCurrentThread(KernelCore& kernel) { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); +void KProcess::PinCurrentThread() { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); // Get the current thread. - const s32 core_id = GetCurrentCoreId(kernel); - KThread* cur_thread = GetCurrentThreadPointer(kernel); + const s32 core_id = GetCurrentCoreId(m_kernel); + KThread* cur_thread = GetCurrentThreadPointer(m_kernel); // If the thread isn't terminated, pin it. if (!cur_thread->IsTerminationRequested()) { // Pin it. this->PinThread(core_id, cur_thread); - cur_thread->Pin(kernel, core_id); + cur_thread->Pin(core_id); // An update is needed. - KScheduler::SetSchedulerUpdateNeeded(kernel); + KScheduler::SetSchedulerUpdateNeeded(m_kernel); } } -void KProcess::UnpinCurrentThread(KernelCore& kernel) { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); +void KProcess::UnpinCurrentThread() { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); // Get the current thread. - const s32 core_id = GetCurrentCoreId(kernel); - KThread* cur_thread = GetCurrentThreadPointer(kernel); + const s32 core_id = GetCurrentCoreId(m_kernel); + KThread* cur_thread = GetCurrentThreadPointer(m_kernel); // Unpin it. - cur_thread->Unpin(kernel); + cur_thread->Unpin(); this->UnpinThread(core_id, cur_thread); // An update is needed. - KScheduler::SetSchedulerUpdateNeeded(kernel); + KScheduler::SetSchedulerUpdateNeeded(m_kernel); } -void KProcess::UnpinThread(KernelCore& kernel, KThread* thread) { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); +void KProcess::UnpinThread(KThread* thread) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); // Get the thread's core id. const auto core_id = thread->GetActiveCore(); // Unpin it. this->UnpinThread(core_id, thread); - thread->Unpin(kernel); + thread->Unpin(); // An update is needed. - KScheduler::SetSchedulerUpdateNeeded(kernel); + KScheduler::SetSchedulerUpdateNeeded(m_kernel); } -Result KProcess::GetThreadList(KernelCore& kernel, s32* out_num_threads, KProcessAddress out_thread_ids, +Result KProcess::GetThreadList(s32* out_num_threads, KProcessAddress out_thread_ids, s32 max_out_count) { auto& memory = this->GetMemory(); @@ -1169,7 +1179,7 @@ Result KProcess::GetThreadList(KernelCore& kernel, s32* out_num_threads, KProces R_SUCCEED(); } -void KProcess::Switch(KernelCore& kernel, KProcess* cur_process, KProcess* next_process) {} +void KProcess::Switch(KProcess* cur_process, KProcess* next_process) {} KProcess::KProcess(KernelCore& kernel) : KAutoObjectWithSlabHeapAndContainer(kernel) @@ -1185,16 +1195,16 @@ KProcess::KProcess(KernelCore& kernel) KProcess::~KProcess() = default; -Result KProcess::LoadFromMetadata(KernelCore& kernel, const FileSys::ProgramMetadata& metadata, std::size_t code_size, KProcessAddress aslr_space_start, size_t aslr_space_offset) { +Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size, KProcessAddress aslr_space_start, size_t aslr_space_offset) { // Create a resource limit for the process. const auto pool = static_cast(metadata.GetPoolPartition()); - const auto physical_memory_size = kernel.MemoryManager().GetSize(pool); + const auto physical_memory_size = m_kernel.MemoryManager().GetSize(pool); auto* res_limit = - Kernel::CreateResourceLimitForProcess(kernel.System(), physical_memory_size); + Kernel::CreateResourceLimitForProcess(m_kernel.System(), physical_memory_size); // Ensure we maintain a clean state on exit. SCOPE_EXIT { - res_limit->Close(kernel); + res_limit->Close(); }; // Declare flags and code address. @@ -1253,20 +1263,22 @@ Result KProcess::LoadFromMetadata(KernelCore& kernel, const FileSys::ProgramMeta std::memcpy(params.name.data(), name.data(), sizeof(params.name)); // Initialize for application process. - R_TRY(this->Initialize(kernel, params, metadata.GetKernelCapabilities(), res_limit, pool, aslr_space_start)); + R_TRY(this->Initialize(params, metadata.GetKernelCapabilities(), res_limit, pool, + aslr_space_start)); // Assign remaining properties. m_ideal_core_id = metadata.GetMainThreadCore(); // Set up emulation context. - this->InitializeInterfaces(kernel); + this->InitializeInterfaces(); // We succeeded. R_SUCCEED(); } -void KProcess::LoadModule(KernelCore& kernel, CodeSet code_set, KProcessAddress base_addr) { - const auto ReprotectSegment = [&](const CodeSet::Segment& segment, Svc::MemoryPermission permission) { +void KProcess::LoadModule(CodeSet code_set, KProcessAddress base_addr) { + const auto ReprotectSegment = [&](const CodeSet::Segment& segment, + Svc::MemoryPermission permission) { m_page_table.SetProcessMemoryPermission(segment.addr + base_addr, segment.size, permission); }; @@ -1280,7 +1292,7 @@ void KProcess::LoadModule(KernelCore& kernel, CodeSet code_set, KProcessAddress const auto& patch = code_set.PatchSegment(); const auto& post_patch = code_set.PostPatchSegment(); if (this->IsApplication() && Settings::IsNceEnabled() && patch.size != 0) { - auto& buffer = kernel.System().DeviceMemory().buffer; + auto& buffer = m_kernel.System().DeviceMemory().buffer; const auto& code = code_set.CodeSegment(); buffer.Protect(GetInteger(base_addr + code.addr), code.size, Common::MemoryPermission::Read | Common::MemoryPermission::Execute); @@ -1299,32 +1311,32 @@ void KProcess::LoadModule(KernelCore& kernel, CodeSet code_set, KProcessAddress #endif } -void KProcess::InitializeInterfaces(KernelCore& kernel) { +void KProcess::InitializeInterfaces() { m_exclusive_monitor = Core::MakeExclusiveMonitor(this->GetMemory(), Core::Hardware::NUM_CPU_CORES); #ifdef HAS_NCE if (this->IsApplication() && Settings::IsNceEnabled()) { for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) - m_arm_interfaces[i] = std::make_unique(kernel.System(), true, i); + m_arm_interfaces[i] = std::make_unique(m_kernel.System(), true, i); } else #endif if (this->Is64Bit()) { for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { m_arm_interfaces[i] = std::make_unique( - kernel.System(), kernel.IsMulticore(), this, + m_kernel.System(), m_kernel.IsMulticore(), this, static_cast(*m_exclusive_monitor), i); } } else { for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { m_arm_interfaces[i] = std::make_unique( - kernel.System(), kernel.IsMulticore(), this, + m_kernel.System(), m_kernel.IsMulticore(), this, static_cast(*m_exclusive_monitor), i); } } } -bool KProcess::InsertWatchpoint(KernelCore& kernel, KProcessAddress addr, u64 size, DebugWatchpointType type) { +bool KProcess::InsertWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type) { const auto watch{std::find_if(m_watchpoints.begin(), m_watchpoints.end(), [&](const auto& wp) { return wp.type == DebugWatchpointType::None; })}; @@ -1346,7 +1358,7 @@ bool KProcess::InsertWatchpoint(KernelCore& kernel, KProcessAddress addr, u64 si return true; } -bool KProcess::RemoveWatchpoint(KernelCore& kernel, KProcessAddress addr, u64 size, DebugWatchpointType type) { +bool KProcess::RemoveWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type) { const auto watch{std::find_if(m_watchpoints.begin(), m_watchpoints.end(), [&](const auto& wp) { return wp.start_address == addr && wp.end_address == addr + size && wp.type == type; })}; diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h index c861a9ea51..2413e5bfd9 100644 --- a/src/core/hle/kernel/k_process.h +++ b/src/core/hle/kernel/k_process.h @@ -141,8 +141,8 @@ private: bool m_is_handle_table_initialized : 1 = false; private: - Result StartTermination(KernelCore& kernel); - void FinishTermination(KernelCore& kernel); + Result StartTermination(); + void FinishTermination(); void PinThread(s32 core_id, KThread* thread) { ASSERT(0 <= core_id && core_id < static_cast(Core::Hardware::NUM_CPU_CORES)); @@ -162,16 +162,16 @@ public: explicit KProcess(KernelCore& kernel); ~KProcess() override; - Result Initialize(KernelCore& kernel, const Svc::CreateProcessParameter& params, KResourceLimit* res_limit, + Result Initialize(const Svc::CreateProcessParameter& params, KResourceLimit* res_limit, bool is_real); - Result Initialize(KernelCore& kernel, const Svc::CreateProcessParameter& params, const KPageGroup& pg, + Result Initialize(const Svc::CreateProcessParameter& params, const KPageGroup& pg, std::span caps, KResourceLimit* res_limit, KMemoryManager::Pool pool, bool immortal); - Result Initialize(KernelCore& kernel, const Svc::CreateProcessParameter& params, std::span user_caps, + Result Initialize(const Svc::CreateProcessParameter& params, std::span user_caps, KResourceLimit* res_limit, KMemoryManager::Pool pool, KProcessAddress aslr_space_start); - void Exit(KernelCore& kernel); + void Exit(); const char* GetName() const { return m_name.data(); @@ -267,7 +267,7 @@ public: m_pointer_buffer_size = size; } - Result Terminate(KernelCore& kernel); + Result Terminate(); bool IsTerminated() const { return m_state == State::Terminated; @@ -300,9 +300,9 @@ public: return m_thread_list; } - bool EnterUserException(KernelCore& kernel); - bool LeaveUserException(KernelCore& kernel); - bool ReleaseUserException(KernelCore& kernel, KThread* thread); + bool EnterUserException(); + bool LeaveUserException(); + bool ReleaseUserException(KThread* thread); KThread* GetPinnedThread(s32 core_id) const { ASSERT(0 <= core_id && core_id < static_cast(Core::Hardware::NUM_CPU_CORES)); @@ -317,10 +317,10 @@ public: return m_resource_limit; } - bool ReserveResource(KernelCore& kernel, Svc::LimitableResource which, s64 value); - bool ReserveResource(KernelCore& kernel, Svc::LimitableResource which, s64 value, s64 timeout); - void ReleaseResource(KernelCore& kernel, Svc::LimitableResource which, s64 value); - void ReleaseResource(KernelCore& kernel, Svc::LimitableResource which, s64 value, s64 hint); + bool ReserveResource(Svc::LimitableResource which, s64 value); + bool ReserveResource(Svc::LimitableResource which, s64 value, s64 timeout); + void ReleaseResource(Svc::LimitableResource which, s64 value); + void ReleaseResource(Svc::LimitableResource which, s64 value, s64 hint); KLightLock& GetStateLock() { return m_state_lock; @@ -343,16 +343,16 @@ public: return m_handle_table; } - size_t GetUsedUserPhysicalMemorySize(KernelCore& kernel) const; - size_t GetTotalUserPhysicalMemorySize(KernelCore& kernel) const; - size_t GetUsedNonSystemUserPhysicalMemorySize(KernelCore& kernel) const; - size_t GetTotalNonSystemUserPhysicalMemorySize(KernelCore& kernel) const; + size_t GetUsedUserPhysicalMemorySize() const; + size_t GetTotalUserPhysicalMemorySize() const; + size_t GetUsedNonSystemUserPhysicalMemorySize() const; + size_t GetTotalNonSystemUserPhysicalMemorySize() const; - Result AddSharedMemory(KernelCore& kernel, KSharedMemory* shmem, KProcessAddress address, size_t size); - void RemoveSharedMemory(KernelCore& kernel, KSharedMemory* shmem, KProcessAddress address, size_t size); + Result AddSharedMemory(KSharedMemory* shmem, KProcessAddress address, size_t size); + void RemoveSharedMemory(KSharedMemory* shmem, KProcessAddress address, size_t size); - Result CreateThreadLocalRegion(KernelCore& kernel, KProcessAddress* out); - Result DeleteThreadLocalRegion(KernelCore& kernel, KProcessAddress addr); + Result CreateThreadLocalRegion(KProcessAddress* out); + Result DeleteThreadLocalRegion(KProcessAddress addr); KProcessAddress GetProcessLocalRegionAddress() const { return m_plr_address; @@ -376,8 +376,8 @@ public: ++m_schedule_count; } - void IncrementRunningThreadCount(KernelCore& kernel); - void DecrementRunningThreadCount(KernelCore& kernel); + void IncrementRunningThreadCount(); + void DecrementRunningThreadCount(); size_t GetRequiredSecureMemorySizeNonDefault() const { if (!this->IsDefaultApplicationSystemResource() && m_system_resource->IsSecureResource()) { @@ -422,9 +422,11 @@ public: } void ClearRunningThread(KThread* thread) { - for (size_t i = 0; i < m_running_threads.size(); ++i) - if (m_running_threads[i] == thread) + for (size_t i = 0; i < m_running_threads.size(); ++i) { + if (m_running_threads[i] == thread) { m_running_threads[i] = nullptr; + } + } } const KSystemResource& GetSystemResource() const { @@ -451,27 +453,30 @@ public: return m_running_thread_switch_counts[core]; } - void RegisterThread(KernelCore& kernel, KThread* thread); - void UnregisterThread(KernelCore& kernel, KThread* thread); - Result Run(KernelCore& kernel, s32 priority, size_t stack_size); - Result Reset(KernelCore& kernel); + void RegisterThread(KThread* thread); + void UnregisterThread(KThread* thread); - void SetDebugBreak(KernelCore& kernel) { + Result Run(s32 priority, size_t stack_size); + + Result Reset(); + + void SetDebugBreak() { if (m_state == State::RunningAttached) { - this->ChangeState(kernel, State::DebugBreak); + this->ChangeState(State::DebugBreak); } } - void SetAttached(KernelCore& kernel) { + void SetAttached() { if (m_state == State::DebugBreak) { - this->ChangeState(kernel, State::RunningAttached); + this->ChangeState(State::RunningAttached); } } - Result SetActivity(KernelCore& kernel, Svc::ProcessActivity activity); - void PinCurrentThread(KernelCore& kernel); - void UnpinCurrentThread(KernelCore& kernel); - void UnpinThread(KernelCore& kernel, KThread* thread); + Result SetActivity(Svc::ProcessActivity activity); + + void PinCurrentThread(); + void UnpinCurrentThread(); + void UnpinThread(KThread* thread); void SignalConditionVariable(uintptr_t cv_key, int32_t count) { return m_cond_var.Signal(cv_key, count); @@ -481,17 +486,19 @@ public: R_RETURN(m_cond_var.Wait(address, cv_key, tag, ns)); } - Result SignalAddressArbiter(uintptr_t address, Svc::SignalType signal_type, s32 value, s32 count) { + Result SignalAddressArbiter(uintptr_t address, Svc::SignalType signal_type, s32 value, + s32 count) { R_RETURN(m_address_arbiter.SignalToAddress(address, signal_type, value, count)); } - Result WaitAddressArbiter(uintptr_t address, Svc::ArbitrationType arb_type, s32 value, s64 timeout) { + Result WaitAddressArbiter(uintptr_t address, Svc::ArbitrationType arb_type, s32 value, + s64 timeout) { R_RETURN(m_address_arbiter.WaitForAddress(address, arb_type, value, timeout)); } - Result GetThreadList(KernelCore& kernel, s32* out_num_threads, KProcessAddress out_thread_ids, s32 max_out_count); + Result GetThreadList(s32* out_num_threads, KProcessAddress out_thread_ids, s32 max_out_count); - static void Switch(KernelCore& kernel, KProcess* cur_process, KProcess* next_process); + static void Switch(KProcess* cur_process, KProcess* next_process); #ifdef HAS_NCE ankerl::unordered_dense::map& GetPostHandlers() noexcept { @@ -505,21 +512,21 @@ public: public: // Attempts to insert a watchpoint into a free slot. Returns false if none are available. - bool InsertWatchpoint(KernelCore& kernel, KProcessAddress addr, u64 size, DebugWatchpointType type); + bool InsertWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type); // Attempts to remove the watchpoint specified by the given parameters. - bool RemoveWatchpoint(KernelCore& kernel, KProcessAddress addr, u64 size, DebugWatchpointType type); + bool RemoveWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type); const std::array& GetWatchpoints() const { return m_watchpoints; } public: - Result LoadFromMetadata(KernelCore& kernel, const FileSys::ProgramMetadata& metadata, std::size_t code_size, KProcessAddress aslr_space_start, size_t aslr_space_offset); + Result LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size, KProcessAddress aslr_space_start, size_t aslr_space_offset); - void LoadModule(KernelCore& kernel, CodeSet code_set, KProcessAddress base_addr); + void LoadModule(CodeSet code_set, KProcessAddress base_addr); - void InitializeInterfaces(KernelCore& kernel); + void InitializeInterfaces(); Core::Memory::Memory& GetMemory() { return m_memory; @@ -535,9 +542,9 @@ public: return m_is_initialized; } - static void PostDestroy(KernelCore& kernel, uintptr_t arg) {} + static void PostDestroy(uintptr_t arg) {} - void Finalize(KernelCore& kernel) override; + void Finalize() override; u64 GetIdImpl() const { return this->GetProcessId(); @@ -546,34 +553,34 @@ public: return this->GetIdImpl(); } - virtual bool IsSignaled(KernelCore& kernel) const override { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); + virtual bool IsSignaled() const override { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); return m_is_signaled; } - void DoWorkerTaskImpl(KernelCore& kernel); + void DoWorkerTaskImpl(); private: - void ChangeState(KernelCore& kernel, State new_state) { + void ChangeState(State new_state) { if (m_state != new_state) { m_state = new_state; m_is_signaled = true; - this->NotifyAvailable(kernel); + this->NotifyAvailable(); } } - Result InitializeHandleTable(KernelCore& kernel, s32 size) { + Result InitializeHandleTable(s32 size) { // Try to initialize the handle table. - R_TRY(m_handle_table.Initialize(kernel, size)); + R_TRY(m_handle_table.Initialize(size)); // We succeeded, so note that we did. m_is_handle_table_initialized = true; R_SUCCEED(); } - void FinalizeHandleTable(KernelCore& kernel) { + void FinalizeHandleTable() { // Finalize the table. - m_handle_table.Finalize(kernel); + m_handle_table.Finalize(); // Note that the table is finalized. m_is_handle_table_initialized = false; diff --git a/src/core/hle/kernel/k_readable_event.cpp b/src/core/hle/kernel/k_readable_event.cpp index a00941bc1e..c30662666b 100644 --- a/src/core/hle/kernel/k_readable_event.cpp +++ b/src/core/hle/kernel/k_readable_event.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -18,45 +15,50 @@ KReadableEvent::KReadableEvent(KernelCore& kernel) : KSynchronizationObject{kern KReadableEvent::~KReadableEvent() = default; -void KReadableEvent::Initialize(KernelCore& kernel, KEvent* parent) { +void KReadableEvent::Initialize(KEvent* parent) { m_is_signaled = false; m_parent = parent; + if (m_parent != nullptr) { - m_parent->Open(kernel); + m_parent->Open(); } } -bool KReadableEvent::IsSignaled(KernelCore& kernel) const { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); +bool KReadableEvent::IsSignaled() const { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + return m_is_signaled; } -void KReadableEvent::Destroy(KernelCore& kernel) { +void KReadableEvent::Destroy() { if (m_parent) { { - KScopedSchedulerLock sl{kernel}; + KScopedSchedulerLock sl{m_kernel}; m_parent->OnReadableEventDestroyed(); } - m_parent->Close(kernel); + m_parent->Close(); } } -Result KReadableEvent::Signal(KernelCore& kernel) { - KScopedSchedulerLock lk{kernel}; +Result KReadableEvent::Signal() { + KScopedSchedulerLock lk{m_kernel}; + if (!m_is_signaled) { m_is_signaled = true; - this->NotifyAvailable(kernel); + this->NotifyAvailable(); } + R_SUCCEED(); } -Result KReadableEvent::Clear(KernelCore& kernel) { - this->Reset(kernel); +Result KReadableEvent::Clear() { + this->Reset(); + R_SUCCEED(); } -Result KReadableEvent::Reset(KernelCore& kernel) { - KScopedSchedulerLock lk{kernel}; +Result KReadableEvent::Reset() { + KScopedSchedulerLock lk{m_kernel}; R_UNLESS(m_is_signaled, ResultInvalidState); diff --git a/src/core/hle/kernel/k_readable_event.h b/src/core/hle/kernel/k_readable_event.h index 63a6e8de60..d2ec363233 100644 --- a/src/core/hle/kernel/k_readable_event.h +++ b/src/core/hle/kernel/k_readable_event.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -23,17 +20,19 @@ public: explicit KReadableEvent(KernelCore& kernel); ~KReadableEvent() override; - void Initialize(KernelCore& kernel, KEvent* parent); + void Initialize(KEvent* parent); KEvent* GetParent() const { return m_parent; } - Result Signal(KernelCore& kernel); - Result Clear(KernelCore& kernel); - bool IsSignaled(KernelCore& kernel) const override; - void Destroy(KernelCore& kernel) override; - Result Reset(KernelCore& kernel); + Result Signal(); + Result Clear(); + + bool IsSignaled() const override; + void Destroy() override; + + Result Reset(); private: bool m_is_signaled{}; diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp index 1a2c92a665..e886f97ebd 100644 --- a/src/core/hle/kernel/k_resource_limit.cpp +++ b/src/core/hle/kernel/k_resource_limit.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project @@ -16,15 +16,12 @@ namespace Kernel { constexpr s64 DefaultTimeout = 10000000000; // 10 seconds KResourceLimit::KResourceLimit(KernelCore& kernel) - : KAutoObjectWithSlabHeapAndContainer{kernel} - , m_lock{kernel} - , m_cond_var{kernel} -{} + : KAutoObjectWithSlabHeapAndContainer{kernel}, m_lock{m_kernel}, m_cond_var{m_kernel} {} KResourceLimit::~KResourceLimit() = default; void KResourceLimit::Initialize() {} -void KResourceLimit::Finalize(KernelCore& kernel) {} +void KResourceLimit::Finalize() {} s64 KResourceLimit::GetLimitValue(LimitableResource which) const { const auto index = static_cast(which); @@ -90,11 +87,11 @@ Result KResourceLimit::SetLimitValue(LimitableResource which, s64 value) { R_SUCCEED(); } -bool KResourceLimit::Reserve(KernelCore& kernel, LimitableResource which, s64 value) { - return Reserve(kernel, which, value, kernel.HardwareTimer().GetTick() + DefaultTimeout); +bool KResourceLimit::Reserve(LimitableResource which, s64 value) { + return Reserve(which, value, m_kernel.HardwareTimer().GetTick() + DefaultTimeout); } -bool KResourceLimit::Reserve(KernelCore& kernel, LimitableResource which, s64 value, s64 timeout) { +bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) { ASSERT(value >= 0); const auto index = static_cast(which); KScopedLightLock lk(m_lock); @@ -122,7 +119,7 @@ bool KResourceLimit::Reserve(KernelCore& kernel, LimitableResource which, s64 va } if (m_current_hints[index] + value <= m_limit_values[index] && - (timeout < 0 || kernel.HardwareTimer().GetTick() < timeout)) { + (timeout < 0 || m_kernel.HardwareTimer().GetTick() < timeout)) { m_waiter_count++; m_cond_var.Wait(std::addressof(m_lock), timeout, false); m_waiter_count--; @@ -134,11 +131,11 @@ bool KResourceLimit::Reserve(KernelCore& kernel, LimitableResource which, s64 va return false; } -void KResourceLimit::Release(KernelCore& kernel, LimitableResource which, s64 value) { - Release(kernel, which, value, value); +void KResourceLimit::Release(LimitableResource which, s64 value) { + Release(which, value, value); } -void KResourceLimit::Release(KernelCore& kernel, LimitableResource which, s64 value, s64 hint) { +void KResourceLimit::Release(LimitableResource which, s64 value, s64 hint) { ASSERT(value >= 0); ASSERT(hint >= 0); diff --git a/src/core/hle/kernel/k_resource_limit.h b/src/core/hle/kernel/k_resource_limit.h index eb45d23bab..b733ec8f81 100644 --- a/src/core/hle/kernel/k_resource_limit.h +++ b/src/core/hle/kernel/k_resource_limit.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -35,7 +32,7 @@ public: ~KResourceLimit() override; void Initialize(); - void Finalize(KernelCore& kernel) override; + void Finalize() override; s64 GetLimitValue(LimitableResource which) const; s64 GetCurrentValue(LimitableResource which) const; @@ -44,12 +41,12 @@ public: Result SetLimitValue(LimitableResource which, s64 value); - bool Reserve(KernelCore& kernel, LimitableResource which, s64 value); - bool Reserve(KernelCore& kernel, LimitableResource which, s64 value, s64 timeout); - void Release(KernelCore& kernel, LimitableResource which, s64 value); - void Release(KernelCore& kernel, LimitableResource which, s64 value, s64 hint); + bool Reserve(LimitableResource which, s64 value); + bool Reserve(LimitableResource which, s64 value, s64 timeout); + void Release(LimitableResource which, s64 value); + void Release(LimitableResource which, s64 value, s64 hint); - static void PostDestroy(KernelCore& kernel, uintptr_t arg) {} + static void PostDestroy(uintptr_t arg) {} private: using ResourceArray = std::array(LimitableResource::Count)>; diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp index 8e629f6456..4b76e18950 100644 --- a/src/core/hle/kernel/k_scheduler.cpp +++ b/src/core/hle/kernel/k_scheduler.cpp @@ -30,32 +30,34 @@ static void IncrementScheduledCount(Kernel::KThread* thread) { } } -KScheduler::KScheduler(KernelCore& kernel) { - m_switch_fiber = std::make_shared([this, &kernel] { +KScheduler::KScheduler(KernelCore& kernel) : m_kernel{kernel} { + m_switch_fiber = std::make_shared([this] { while (true) { - ScheduleImplFiber(kernel); + ScheduleImplFiber(); } }); + m_state.needs_scheduling = true; } KScheduler::~KScheduler() = default; -void KScheduler::SetInterruptTaskRunnable(KernelCore& kernel) { +void KScheduler::SetInterruptTaskRunnable() { m_state.interrupt_task_runnable = true; m_state.needs_scheduling = true; } -void KScheduler::RequestScheduleOnInterrupt(KernelCore& kernel) { +void KScheduler::RequestScheduleOnInterrupt() { m_state.needs_scheduling = true; - if (CanSchedule(kernel)) { - ScheduleOnInterrupt(kernel); + + if (CanSchedule(m_kernel)) { + ScheduleOnInterrupt(); } } void KScheduler::DisableScheduling(KernelCore& kernel) { ASSERT(GetCurrentThread(kernel).GetDisableDispatchCount() >= 0); - GetCurrentThread(kernel).DisableDispatch(kernel); + GetCurrentThread(kernel).DisableDispatch(); } void KScheduler::EnableScheduling(KernelCore& kernel, u64 cores_needing_scheduling) { @@ -69,12 +71,12 @@ void KScheduler::EnableScheduling(KernelCore& kernel, u64 cores_needing_scheduli return; } - scheduler->RescheduleOtherCores(kernel, cores_needing_scheduling); + scheduler->RescheduleOtherCores(cores_needing_scheduling); if (GetCurrentThread(kernel).GetDisableDispatchCount() > 1) { - GetCurrentThread(kernel).EnableDispatch(kernel); + GetCurrentThread(kernel).EnableDispatch(); } else { - scheduler->RescheduleCurrentCore(kernel); + scheduler->RescheduleCurrentCore(); } } @@ -83,10 +85,10 @@ void KScheduler::RescheduleCurrentHLEThread(KernelCore& kernel) { ASSERT(GetCurrentThread(kernel).GetDisableDispatchCount() == 1); // Ensure dummy threads that are waiting block. - GetCurrentThread(kernel).DummyThreadBeginWait(kernel); + GetCurrentThread(kernel).DummyThreadBeginWait(); ASSERT(GetCurrentThread(kernel).GetState() != ThreadState::Waiting); - GetCurrentThread(kernel).EnableDispatch(kernel); + GetCurrentThread(kernel).EnableDispatch(); } u64 KScheduler::UpdateHighestPriorityThreads(KernelCore& kernel) { @@ -97,55 +99,55 @@ u64 KScheduler::UpdateHighestPriorityThreads(KernelCore& kernel) { } } -void KScheduler::Schedule(KernelCore& kernel) { - ASSERT(GetCurrentThread(kernel).GetDisableDispatchCount() == 1); - ASSERT(m_core_id == GetCurrentCoreId(kernel)); +void KScheduler::Schedule() { + ASSERT(GetCurrentThread(m_kernel).GetDisableDispatchCount() == 1); + ASSERT(m_core_id == GetCurrentCoreId(m_kernel)); - ScheduleImpl(kernel); + ScheduleImpl(); } -void KScheduler::ScheduleOnInterrupt(KernelCore& kernel) { - GetCurrentThread(kernel).DisableDispatch(kernel); - Schedule(kernel); - GetCurrentThread(kernel).EnableDispatch(kernel); +void KScheduler::ScheduleOnInterrupt() { + GetCurrentThread(m_kernel).DisableDispatch(); + Schedule(); + GetCurrentThread(m_kernel).EnableDispatch(); } -void KScheduler::PreemptSingleCore(KernelCore& kernel) { - GetCurrentThread(kernel).DisableDispatch(kernel); +void KScheduler::PreemptSingleCore() { + GetCurrentThread(m_kernel).DisableDispatch(); - auto* thread = GetCurrentThreadPointer(kernel); - auto& previous_scheduler = kernel.Scheduler(thread->GetCurrentCore()); - previous_scheduler.Unload(kernel, thread); + auto* thread = GetCurrentThreadPointer(m_kernel); + auto& previous_scheduler = m_kernel.Scheduler(thread->GetCurrentCore()); + previous_scheduler.Unload(thread); Common::Fiber::YieldTo(thread->GetHostContext(), *m_switch_fiber); - GetCurrentThread(kernel).EnableDispatch(kernel); + GetCurrentThread(m_kernel).EnableDispatch(); } -void KScheduler::RescheduleCurrentCore(KernelCore& kernel) { - ASSERT(!kernel.IsPhantomModeForSingleCore()); - ASSERT(GetCurrentThread(kernel).GetDisableDispatchCount() == 1); +void KScheduler::RescheduleCurrentCore() { + ASSERT(!m_kernel.IsPhantomModeForSingleCore()); + ASSERT(GetCurrentThread(m_kernel).GetDisableDispatchCount() == 1); - GetCurrentThread(kernel).EnableDispatch(kernel); + GetCurrentThread(m_kernel).EnableDispatch(); if (m_state.needs_scheduling.load()) { // Disable interrupts, and then check again if rescheduling is needed. // KScopedInterruptDisable intr_disable; - kernel.CurrentScheduler()->RescheduleCurrentCoreImpl(kernel); + m_kernel.CurrentScheduler()->RescheduleCurrentCoreImpl(); } } -void KScheduler::RescheduleCurrentCoreImpl(KernelCore& kernel) { +void KScheduler::RescheduleCurrentCoreImpl() { // Check that scheduling is needed. if (m_state.needs_scheduling.load()) [[likely]] { - GetCurrentThread(kernel).DisableDispatch(kernel); - Schedule(kernel); - GetCurrentThread(kernel).EnableDispatch(kernel); + GetCurrentThread(m_kernel).DisableDispatch(); + Schedule(); + GetCurrentThread(m_kernel).EnableDispatch(); } } -void KScheduler::Initialize(KernelCore& kernel, KThread* main_thread, KThread* idle_thread, s32 core_id) { +void KScheduler::Initialize(KThread* main_thread, KThread* idle_thread, s32 core_id) { // Set core ID/idle thread/interrupt task manager. m_core_id = core_id; m_idle_thread = idle_thread; @@ -154,39 +156,39 @@ void KScheduler::Initialize(KernelCore& kernel, KThread* main_thread, KThread* i // Insert the main thread into the priority queue. // { - // KScopedSchedulerLock lk{kernel}; - // GetPriorityQueue(kernel).PushBack(GetCurrentThreadPointer(kernel)); - // SetSchedulerUpdateNeeded(kernel); + // KScopedSchedulerLock lk{m_kernel}; + // GetPriorityQueue(m_kernel).PushBack(GetCurrentThreadPointer(m_kernel)); + // SetSchedulerUpdateNeeded(m_kernel); // } // Bind interrupt handler. // kernel.GetInterruptManager().BindHandler( - // GetSchedulerInterruptHandler(kernel), KInterruptName::Scheduler, m_core_id, + // GetSchedulerInterruptHandler(m_kernel), KInterruptName::Scheduler, m_core_id, // KInterruptController::PriorityLevel::Scheduler, false, false); // Set the current thread. m_current_thread = main_thread; } -void KScheduler::Activate(KernelCore& kernel) { - ASSERT(GetCurrentThread(kernel).GetDisableDispatchCount() == 1); +void KScheduler::Activate() { + ASSERT(GetCurrentThread(m_kernel).GetDisableDispatchCount() == 1); // m_state.should_count_idle = KTargetSystem::IsDebugMode(); m_is_active = true; - RescheduleCurrentCore(kernel); + RescheduleCurrentCore(); } -void KScheduler::OnThreadStart(KernelCore& kernel) { - GetCurrentThread(kernel).EnableDispatch(kernel); +void KScheduler::OnThreadStart() { + GetCurrentThread(m_kernel).EnableDispatch(); } -u64 KScheduler::UpdateHighestPriorityThread(KernelCore& kernel, KThread* highest_thread) { +u64 KScheduler::UpdateHighestPriorityThread(KThread* highest_thread) { if (KThread* prev_highest_thread = m_state.highest_priority_thread; prev_highest_thread != highest_thread) [[likely]] { if (prev_highest_thread != nullptr) [[likely]] { IncrementScheduledCount(prev_highest_thread); prev_highest_thread->SetLastScheduledTick( - kernel.System().CoreTiming().GetClockTicks()); + m_kernel.System().CoreTiming().GetClockTicks()); } if (m_state.should_count_idle) { if (highest_thread != nullptr) [[likely]] { @@ -243,7 +245,8 @@ u64 KScheduler::UpdateHighestPriorityThreadsImpl(KernelCore& kernel) { } top_threads[core_id] = top_thread; - cores_needing_scheduling |= kernel.Scheduler(core_id).UpdateHighestPriorityThread(kernel, top_threads[core_id]); + cores_needing_scheduling |= + kernel.Scheduler(core_id).UpdateHighestPriorityThread(top_threads[core_id]); } // Idle cores are bad. We're going to try to migrate threads to each idle core in turn. @@ -271,7 +274,8 @@ u64 KScheduler::UpdateHighestPriorityThreadsImpl(KernelCore& kernel) { suggested->SetActiveCore(core_id); priority_queue.ChangeCore(suggested_core, suggested); top_threads[core_id] = suggested; - cores_needing_scheduling |= kernel.Scheduler(core_id).UpdateHighestPriorityThread(kernel, top_threads[core_id]); + cores_needing_scheduling |= + kernel.Scheduler(core_id).UpdateHighestPriorityThread(top_threads[core_id]); break; } @@ -294,13 +298,17 @@ u64 KScheduler::UpdateHighestPriorityThreadsImpl(KernelCore& kernel) { // The candidate core can run some other thread! We'll migrate its current // top thread to us. top_threads[candidate_core] = next_on_candidate_core; - cores_needing_scheduling |= kernel.Scheduler(candidate_core).UpdateHighestPriorityThread(kernel, top_threads[candidate_core]); + cores_needing_scheduling |= + kernel.Scheduler(candidate_core) + .UpdateHighestPriorityThread(top_threads[candidate_core]); // Perform the migration. suggested->SetActiveCore(core_id); priority_queue.ChangeCore(candidate_core, suggested); top_threads[core_id] = suggested; - cores_needing_scheduling |= kernel.Scheduler(core_id).UpdateHighestPriorityThread(kernel, top_threads[core_id]); + cores_needing_scheduling |= + kernel.Scheduler(core_id).UpdateHighestPriorityThread( + top_threads[core_id]); break; } } @@ -311,21 +319,21 @@ u64 KScheduler::UpdateHighestPriorityThreadsImpl(KernelCore& kernel) { } // HACK: any waiting dummy threads can wake up now. - kernel.GlobalSchedulerContext().WakeupWaitingDummyThreads(kernel); + kernel.GlobalSchedulerContext().WakeupWaitingDummyThreads(); // HACK: if we are a dummy thread, and we need to go sleep, indicate // that for when the lock is released. KThread* const cur_thread = GetCurrentThreadPointer(kernel); if (cur_thread->IsDummyThread() && cur_thread->GetState() != ThreadState::Runnable) { - cur_thread->RequestDummyThreadWait(kernel); + cur_thread->RequestDummyThreadWait(); } return cores_needing_scheduling; } -void KScheduler::SwitchThread(KernelCore& kernel, KThread* next_thread) { - KProcess* const cur_process = GetCurrentProcessPointer(kernel); - KThread* const cur_thread = GetCurrentThreadPointer(kernel); +void KScheduler::SwitchThread(KThread* next_thread) { + KProcess* const cur_process = GetCurrentProcessPointer(m_kernel); + KThread* const cur_thread = GetCurrentThreadPointer(m_kernel); // We never want to schedule a null thread, so use the idle thread if we don't have a next. if (next_thread == nullptr) { @@ -347,7 +355,7 @@ void KScheduler::SwitchThread(KernelCore& kernel, KThread* next_thread) { // Update the CPU time tracking variables. const s64 prev_tick = m_last_context_switch_time; - const s64 cur_tick = kernel.System().CoreTiming().GetClockTicks(); + const s64 cur_tick = m_kernel.System().CoreTiming().GetClockTicks(); const s64 tick_diff = cur_tick - prev_tick; cur_thread->AddCpuTime(m_core_id, tick_diff); if (cur_process != nullptr) { @@ -371,23 +379,23 @@ void KScheduler::SwitchThread(KernelCore& kernel, KThread* next_thread) { // } // Set the new thread. - SetCurrentThread(kernel, next_thread); + SetCurrentThread(m_kernel, next_thread); m_current_thread = next_thread; // Set the new Thread Local region. // cpu::SwitchThreadLocalRegion(GetInteger(next_thread->GetThreadLocalRegionAddress())); // Update the thread's cpu time differential in TLS, if relevant. - next_thread->UpdateTlsThreadCpuTime(kernel, cur_tick); + next_thread->UpdateTlsThreadCpuTime(cur_tick); } -void KScheduler::ScheduleImpl(KernelCore& kernel) { +void KScheduler::ScheduleImpl() { // First, clear the needs scheduling bool. m_state.needs_scheduling.store(false, std::memory_order_relaxed); std::atomic_thread_fence(std::memory_order_seq_cst); // Load the appropriate thread pointers for scheduling. - KThread* const cur_thread{GetCurrentThreadPointer(kernel)}; + KThread* const cur_thread{GetCurrentThreadPointer(m_kernel)}; KThread* highest_priority_thread{m_state.highest_priority_thread}; // Check whether there are runnable interrupt tasks. @@ -415,7 +423,7 @@ void KScheduler::ScheduleImpl(KernelCore& kernel) { // Returning from ScheduleImpl occurs after this thread has been scheduled again. } -void KScheduler::ScheduleImplFiber(KernelCore& kernel) { +void KScheduler::ScheduleImplFiber() { KThread* const cur_thread{m_switch_cur_thread}; KThread* highest_priority_thread{m_switch_highest_priority_thread}; @@ -429,7 +437,7 @@ void KScheduler::ScheduleImplFiber(KernelCore& kernel) { m_switch_from_schedule = false; // Save the original thread context. - Unload(kernel, cur_thread); + Unload(cur_thread); // The current thread's context has been entirely taken care of. // Now we want to loop until we successfully switch the thread context. @@ -460,7 +468,7 @@ void KScheduler::ScheduleImplFiber(KernelCore& kernel) { // It's time to switch the thread. // Switch to the highest priority thread. - SwitchThread(kernel, highest_priority_thread); + SwitchThread(highest_priority_thread); // Check if we need scheduling. If we do, then we can't complete the switch and should // retry. @@ -485,14 +493,14 @@ void KScheduler::ScheduleImplFiber(KernelCore& kernel) { } // Reload the guest thread context. - Reload(kernel, highest_priority_thread); + Reload(highest_priority_thread); // Reload the host thread. Common::Fiber::YieldTo(m_switch_fiber, *highest_priority_thread->m_host_context); } -void KScheduler::Unload(KernelCore& kernel, KThread* thread) { - kernel.PhysicalCore(m_core_id).SaveContext(thread); +void KScheduler::Unload(KThread* thread) { + m_kernel.PhysicalCore(m_core_id).SaveContext(thread); // Check if the thread is terminated by checking the DPC flags. if ((thread->GetStackParameters().dpc_flags & static_cast(DpcFlag::Terminated)) == 0) { @@ -501,8 +509,8 @@ void KScheduler::Unload(KernelCore& kernel, KThread* thread) { } } -void KScheduler::Reload(KernelCore& kernel, KThread* thread) { - kernel.PhysicalCore(m_core_id).LoadContext(thread); +void KScheduler::Reload(KThread* thread) { + m_kernel.PhysicalCore(m_core_id).LoadContext(thread); } void KScheduler::ClearPreviousThread(KernelCore& kernel, KThread* thread) { @@ -869,9 +877,9 @@ void KScheduler::YieldToAnyThread(KernelCore& kernel) { } } -void KScheduler::RescheduleOtherCores(KernelCore& kernel, u64 cores_needing_scheduling) { +void KScheduler::RescheduleOtherCores(u64 cores_needing_scheduling) { if (const u64 core_mask = cores_needing_scheduling & ~(1ULL << m_core_id); core_mask != 0) { - RescheduleCores(kernel, core_mask); + RescheduleCores(m_kernel, core_mask); } } diff --git a/src/core/hle/kernel/k_scheduler.h b/src/core/hle/kernel/k_scheduler.h index 5a896fd899..d85a0c0408 100644 --- a/src/core/hle/kernel/k_scheduler.h +++ b/src/core/hle/kernel/k_scheduler.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -44,15 +41,15 @@ public: explicit KScheduler(KernelCore& kernel); ~KScheduler(); - void Initialize(KernelCore& kernel, KThread* main_thread, KThread* idle_thread, s32 core_id); - void Activate(KernelCore& kernel); - void OnThreadStart(KernelCore& kernel); - void Unload(KernelCore& kernel, KThread* thread); - void Reload(KernelCore& kernel, KThread* thread); + void Initialize(KThread* main_thread, KThread* idle_thread, s32 core_id); + void Activate(); + void OnThreadStart(); + void Unload(KThread* thread); + void Reload(KThread* thread); - void SetInterruptTaskRunnable(KernelCore& kernel); - void RequestScheduleOnInterrupt(KernelCore& kernel); - void PreemptSingleCore(KernelCore& kernel); + void SetInterruptTaskRunnable(); + void RequestScheduleOnInterrupt(); + void PreemptSingleCore(); u64 GetIdleCount() { return m_state.idle_count; @@ -125,18 +122,18 @@ private: static void RescheduleCurrentHLEThread(KernelCore& kernel); // Instanced private API. - void ScheduleImpl(KernelCore& kernel); - void ScheduleImplFiber(KernelCore& kernel); - void SwitchThread(KernelCore& kernel, KThread* next_thread); + void ScheduleImpl(); + void ScheduleImplFiber(); + void SwitchThread(KThread* next_thread); - void Schedule(KernelCore& kernel); - void ScheduleOnInterrupt(KernelCore& kernel); + void Schedule(); + void ScheduleOnInterrupt(); - void RescheduleOtherCores(KernelCore& kernel, u64 cores_needing_scheduling); - void RescheduleCurrentCore(KernelCore& kernel); - void RescheduleCurrentCoreImpl(KernelCore& kernel); + void RescheduleOtherCores(u64 cores_needing_scheduling); + void RescheduleCurrentCore(); + void RescheduleCurrentCoreImpl(); - u64 UpdateHighestPriorityThread(KernelCore& kernel, KThread* thread); + u64 UpdateHighestPriorityThread(KThread* thread); private: friend class KScopedDisableDispatch; @@ -152,12 +149,14 @@ private: KInterruptTaskManager* interrupt_task_manager{nullptr}; }; + KernelCore& m_kernel; SchedulingState m_state; bool m_is_active{false}; s32 m_core_id{0}; s64 m_last_context_switch_time{0}; KThread* m_idle_thread{nullptr}; std::atomic m_current_thread{nullptr}; + std::shared_ptr m_switch_fiber{}; KThread* m_switch_cur_thread{}; KThread* m_switch_highest_priority_thread{}; diff --git a/src/core/hle/kernel/k_scoped_resource_reservation.h b/src/core/hle/kernel/k_scoped_resource_reservation.h index 4fc66af725..2cc464612a 100644 --- a/src/core/hle/kernel/k_scoped_resource_reservation.h +++ b/src/core/hle/kernel/k_scoped_resource_reservation.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -14,42 +11,34 @@ namespace Kernel { class KScopedResourceReservation { public: - explicit KScopedResourceReservation(KernelCore& kernel, KResourceLimit* l, LimitableResource r, s64 v, s64 timeout) - : m_kernel{kernel} - , m_limit(l) - , m_value(v) - , m_resource(r) - { + explicit KScopedResourceReservation(KResourceLimit* l, LimitableResource r, s64 v, s64 timeout) + : m_limit(l), m_value(v), m_resource(r) { if (m_limit && m_value) { - m_succeeded = m_limit->Reserve(kernel, m_resource, m_value, timeout); + m_succeeded = m_limit->Reserve(m_resource, m_value, timeout); } else { m_succeeded = true; } } - explicit KScopedResourceReservation(KernelCore& kernel, KResourceLimit* l, LimitableResource r, s64 v = 1) - : m_kernel{kernel} - , m_limit(l) - , m_value(v) - , m_resource(r) - { + explicit KScopedResourceReservation(KResourceLimit* l, LimitableResource r, s64 v = 1) + : m_limit(l), m_value(v), m_resource(r) { if (m_limit && m_value) { - m_succeeded = m_limit->Reserve(kernel, m_resource, m_value); + m_succeeded = m_limit->Reserve(m_resource, m_value); } else { m_succeeded = true; } } - explicit KScopedResourceReservation(KernelCore& kernel, const KProcess* p, LimitableResource r, s64 v, s64 t) - : KScopedResourceReservation(kernel, p->GetResourceLimit(), r, v, t) {} + explicit KScopedResourceReservation(const KProcess* p, LimitableResource r, s64 v, s64 t) + : KScopedResourceReservation(p->GetResourceLimit(), r, v, t) {} - explicit KScopedResourceReservation(KernelCore& kernel, const KProcess* p, LimitableResource r, s64 v = 1) - : KScopedResourceReservation(kernel, p->GetResourceLimit(), r, v) {} + explicit KScopedResourceReservation(const KProcess* p, LimitableResource r, s64 v = 1) + : KScopedResourceReservation(p->GetResourceLimit(), r, v) {} ~KScopedResourceReservation() noexcept { if (m_limit && m_value && m_succeeded) { // Resource was not committed, release the reservation. - m_limit->Release(m_kernel, m_resource, m_value); + m_limit->Release(m_resource, m_value); } } @@ -63,7 +52,6 @@ public: } private: - KernelCore& m_kernel; KResourceLimit* m_limit{}; s64 m_value{}; LimitableResource m_resource{}; diff --git a/src/core/hle/kernel/k_server_port.cpp b/src/core/hle/kernel/k_server_port.cpp index dad6ef0678..bb6632f58e 100644 --- a/src/core/hle/kernel/k_server_port.cpp +++ b/src/core/hle/kernel/k_server_port.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -18,18 +15,18 @@ namespace Kernel { KServerPort::KServerPort(KernelCore& kernel) : KSynchronizationObject{kernel} {} KServerPort::~KServerPort() = default; -void KServerPort::Initialize(KernelCore& kernel, KPort* parent) { +void KServerPort::Initialize(KPort* parent) { // Set member variables. m_parent = parent; } -bool KServerPort::IsLight(KernelCore& kernel) const { +bool KServerPort::IsLight() const { return this->GetParent()->IsLight(); } -void KServerPort::CleanupSessions(KernelCore& kernel) { +void KServerPort::CleanupSessions() { // Ensure our preconditions are met. - if (this->IsLight(kernel)) { + if (this->IsLight()) { ASSERT(m_session_list.empty()); } else { ASSERT(m_light_session_list.empty()); @@ -40,7 +37,7 @@ void KServerPort::CleanupSessions(KernelCore& kernel) { // Get the last session in the list. KServerSession* session = nullptr; { - KScopedSchedulerLock sl{kernel}; + KScopedSchedulerLock sl{m_kernel}; if (!m_session_list.empty()) { session = std::addressof(m_session_list.front()); m_session_list.pop_front(); @@ -49,7 +46,7 @@ void KServerPort::CleanupSessions(KernelCore& kernel) { // Close the session. if (session != nullptr) { - session->Close(kernel); + session->Close(); } else { break; } @@ -60,7 +57,7 @@ void KServerPort::CleanupSessions(KernelCore& kernel) { // Get the last session in the list. KLightServerSession* session = nullptr; { - KScopedSchedulerLock sl{kernel}; + KScopedSchedulerLock sl{m_kernel}; if (!m_light_session_list.empty()) { session = std::addressof(m_light_session_list.front()); m_light_session_list.pop_front(); @@ -69,60 +66,60 @@ void KServerPort::CleanupSessions(KernelCore& kernel) { // Close the session. if (session != nullptr) { - session->Close(kernel); + session->Close(); } else { break; } } } -void KServerPort::Destroy(KernelCore& kernel) { +void KServerPort::Destroy() { // Note with our parent that we're closed. - m_parent->OnServerClosed(kernel); + m_parent->OnServerClosed(); // Perform necessary cleanup of our session lists. - this->CleanupSessions(kernel); + this->CleanupSessions(); // Close our reference to our parent. - m_parent->Close(kernel); + m_parent->Close(); } -bool KServerPort::IsSignaled(KernelCore& kernel) const { - if (this->IsLight(kernel)) { +bool KServerPort::IsSignaled() const { + if (this->IsLight()) { return !m_light_session_list.empty(); } else { return !m_session_list.empty(); } } -void KServerPort::EnqueueSession(KernelCore& kernel, KServerSession* session) { - ASSERT(!this->IsLight(kernel)); +void KServerPort::EnqueueSession(KServerSession* session) { + ASSERT(!this->IsLight()); - KScopedSchedulerLock sl{kernel}; + KScopedSchedulerLock sl{m_kernel}; // Add the session to our queue. m_session_list.push_back(*session); if (m_session_list.size() == 1) { - this->NotifyAvailable(kernel); + this->NotifyAvailable(); } } -void KServerPort::EnqueueSession(KernelCore& kernel, KLightServerSession* session) { - ASSERT(this->IsLight(kernel)); +void KServerPort::EnqueueSession(KLightServerSession* session) { + ASSERT(this->IsLight()); - KScopedSchedulerLock sl{kernel}; + KScopedSchedulerLock sl{m_kernel}; // Add the session to our queue. m_light_session_list.push_back(*session); if (m_light_session_list.size() == 1) { - this->NotifyAvailable(kernel); + this->NotifyAvailable(); } } -KServerSession* KServerPort::AcceptSession(KernelCore& kernel) { - ASSERT(!this->IsLight(kernel)); +KServerSession* KServerPort::AcceptSession() { + ASSERT(!this->IsLight()); - KScopedSchedulerLock sl{kernel}; + KScopedSchedulerLock sl{m_kernel}; // Return the first session in the list. if (m_session_list.empty()) { @@ -134,10 +131,10 @@ KServerSession* KServerPort::AcceptSession(KernelCore& kernel) { return session; } -KLightServerSession* KServerPort::AcceptLightSession(KernelCore& kernel) { - ASSERT(this->IsLight(kernel)); +KLightServerSession* KServerPort::AcceptLightSession() { + ASSERT(this->IsLight()); - KScopedSchedulerLock sl{kernel}; + KScopedSchedulerLock sl{m_kernel}; // Return the first session in the list. if (m_light_session_list.empty()) { diff --git a/src/core/hle/kernel/k_server_port.h b/src/core/hle/kernel/k_server_port.h index 5996a3a3ee..72fdb6734a 100644 --- a/src/core/hle/kernel/k_server_port.h +++ b/src/core/hle/kernel/k_server_port.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -29,29 +26,29 @@ public: explicit KServerPort(KernelCore& kernel); ~KServerPort() override; - void Initialize(KernelCore& kernel, KPort* parent); + void Initialize(KPort* parent); - void EnqueueSession(KernelCore& kernel, KServerSession* session); - void EnqueueSession(KernelCore& kernel, KLightServerSession* session); + void EnqueueSession(KServerSession* session); + void EnqueueSession(KLightServerSession* session); - KServerSession* AcceptSession(KernelCore& kernel); - KLightServerSession* AcceptLightSession(KernelCore& kernel); + KServerSession* AcceptSession(); + KLightServerSession* AcceptLightSession(); const KPort* GetParent() const { return m_parent; } - bool IsLight(KernelCore& kernel) const; + bool IsLight() const; // Overridden virtual functions. - void Destroy(KernelCore& kernel) override; - bool IsSignaled(KernelCore& kernel) const override; + void Destroy() override; + bool IsSignaled() const override; private: using SessionList = Common::IntrusiveListBaseTraits::ListType; using LightSessionList = Common::IntrusiveListBaseTraits::ListType; - void CleanupSessions(KernelCore& kernel); + void CleanupSessions(); SessionList m_session_list{}; LightSessionList m_light_session_list{}; diff --git a/src/core/hle/kernel/k_server_session.cpp b/src/core/hle/kernel/k_server_session.cpp index e3cfe6b6c2..4c91235ac9 100644 --- a/src/core/hle/kernel/k_server_session.cpp +++ b/src/core/hle/kernel/k_server_session.cpp @@ -159,7 +159,7 @@ private: }; template -Result ProcessMessageSpecialData(KernelCore& kernel, s32& offset, KProcess& dst_process, KProcess& src_process, +Result ProcessMessageSpecialData(s32& offset, KProcess& dst_process, KProcess& src_process, KThread& src_thread, const MessageBuffer& dst_msg, const MessageBuffer& src_msg, const MessageBuffer::SpecialHeader& src_special_header) { @@ -185,9 +185,10 @@ Result ProcessMessageSpecialData(KernelCore& kernel, s32& offset, KProcess& dst_ // If we're in a success state, try to move the handle to the new table. if (R_SUCCEEDED(result) && src_handle != Svc::InvalidHandle) { KScopedAutoObject obj = - src_handle_table.GetObjectForIpc(kernel, src_handle, std::addressof(src_thread)); + src_handle_table.GetObjectForIpc(src_handle, std::addressof(src_thread)); if (obj.IsNotNull()) { - Result add_result = dst_handle_table.Add(kernel, std::addressof(dst_handle), obj.GetPointerUnsafe()); + Result add_result = + dst_handle_table.Add(std::addressof(dst_handle), obj.GetPointerUnsafe()); if (R_FAILED(add_result)) { result = add_result; dst_handle = Svc::InvalidHandle; @@ -212,10 +213,12 @@ Result ProcessMessageSpecialData(KernelCore& kernel, s32& offset, KProcess& dst_ if (src_handle != Svc::InvalidHandle) { if (R_SUCCEEDED(result)) { KScopedAutoObject obj = - src_handle_table.GetObjectForIpcWithoutPseudoHandle(kernel, src_handle); + src_handle_table.GetObjectForIpcWithoutPseudoHandle(src_handle); if (obj.IsNotNull()) { - Result add_result = dst_handle_table.Add(kernel, std::addressof(dst_handle), obj.GetPointerUnsafe()); - src_handle_table.Remove(kernel, src_handle); + Result add_result = dst_handle_table.Add(std::addressof(dst_handle), + obj.GetPointerUnsafe()); + + src_handle_table.Remove(src_handle); if (R_FAILED(add_result)) { result = add_result; @@ -225,7 +228,7 @@ Result ProcessMessageSpecialData(KernelCore& kernel, s32& offset, KProcess& dst_ result = ResultInvalidHandle; } } else { - src_handle_table.Remove(kernel, src_handle); + src_handle_table.Remove(src_handle); } } @@ -333,7 +336,7 @@ constexpr Result GetMapAliasTestStateAndAttributeMask(KMemoryState& out_state, R_SUCCEED(); } -void CleanupSpecialData(KernelCore& kernel, KProcess& dst_process, u32* dst_msg_ptr, size_t dst_buffer_size) { +void CleanupSpecialData(KProcess& dst_process, u32* dst_msg_ptr, size_t dst_buffer_size) { // Parse the message. const MessageBuffer dst_msg(dst_msg_ptr, dst_buffer_size); const MessageBuffer::MessageHeader dst_header(dst_msg); @@ -360,14 +363,15 @@ void CleanupSpecialData(KernelCore& kernel, KProcess& dst_process, u32* dst_msg_ const Handle handle = dst_msg.GetHandle(offset); if (handle != Svc::InvalidHandle) { - dst_handle_table.Remove(kernel, handle); + dst_handle_table.Remove(handle); } offset = dst_msg.SetHandle(offset, Svc::InvalidHandle); } } -Result CleanupServerHandles(KernelCore& kernel, uint64_t message, size_t buffer_size, KPhysicalAddress message_paddr) { +Result CleanupServerHandles(KernelCore& kernel, uint64_t message, size_t buffer_size, + KPhysicalAddress message_paddr) { // Server is assumed to be current thread. KThread& thread = GetCurrentThread(kernel); @@ -406,7 +410,7 @@ Result CleanupServerHandles(KernelCore& kernel, uint64_t message, size_t buffer_ // Close the handles. for (auto i = 0; i < special_header.GetMoveHandleCount(); ++i) { - handle_table.Remove(kernel, msg.GetHandle(offset)); + handle_table.Remove(msg.GetHandle(offset)); offset += static_cast(sizeof(Svc::Handle) / sizeof(u32)); } } @@ -554,7 +558,7 @@ Result ReceiveMessage(KernelCore& kernel, bool& recv_list_broken, uint64_t dst_m recv_list_broken = false; // Set the server process for the request. - request->SetServerProcess(kernel, std::addressof(dst_process)); + request->SetServerProcess(std::addressof(dst_process)); // Determine the message buffers. u32 *dst_msg_ptr, *src_msg_ptr; @@ -635,7 +639,7 @@ Result ReceiveMessage(KernelCore& kernel, bool& recv_list_broken, uint64_t dst_m // Cleanup special data. if (src_header.GetHasSpecialHeader()) { - CleanupSpecialData(kernel, dst_process, dst_msg_ptr, dst_buffer_size); + CleanupSpecialData(dst_process, dst_msg_ptr, dst_buffer_size); } // Cleanup the header if the receive list isn't broken. @@ -657,7 +661,7 @@ Result ReceiveMessage(KernelCore& kernel, bool& recv_list_broken, uint64_t dst_m }; // Process special data. - R_TRY(ProcessMessageSpecialData(kernel, offset, dst_process, src_process, src_thread, + R_TRY(ProcessMessageSpecialData(offset, dst_process, src_process, src_thread, dst_msg, src_msg, src_special_header)); } @@ -918,7 +922,7 @@ Result SendMessage(KernelCore& kernel, uint64_t src_message_buffer, size_t src_b // Cleanup special data. if (processed_special_data) { if (src_header.GetHasSpecialHeader()) { - CleanupSpecialData(kernel, dst_process, dst_msg_ptr, dst_buffer_size); + CleanupSpecialData(dst_process, dst_msg_ptr, dst_buffer_size); } } else { CleanupServerHandles(kernel, src_user ? src_message_buffer : 0, src_buffer_size, @@ -983,7 +987,7 @@ Result SendMessage(KernelCore& kernel, uint64_t src_message_buffer, size_t src_b ASSERT(GetCurrentThreadPointer(kernel) == std::addressof(src_thread)); processed_special_data = true; if (src_header.GetHasSpecialHeader()) { - R_TRY(ProcessMessageSpecialData(kernel, offset, dst_process, src_process, src_thread, + R_TRY(ProcessMessageSpecialData(offset, dst_process, src_process, src_thread, dst_msg, src_msg, src_special_header)); } @@ -1076,17 +1080,19 @@ void ReplyAsyncError(KProcess* to_process, uint64_t to_msg_buf, size_t to_msg_bu } // namespace KServerSession::KServerSession(KernelCore& kernel) - : KSynchronizationObject{kernel}, m_lock{kernel} {} + : KSynchronizationObject{kernel}, m_lock{m_kernel} {} KServerSession::~KServerSession() = default; -void KServerSession::Destroy(KernelCore& kernel) { - m_parent->OnServerClosed(kernel); - this->CleanupRequests(kernel); - m_parent->Close(kernel); +void KServerSession::Destroy() { + m_parent->OnServerClosed(); + + this->CleanupRequests(); + + m_parent->Close(); } -Result KServerSession::ReceiveRequest(KernelCore& kernel, uintptr_t server_message, uintptr_t server_buffer_size, +Result KServerSession::ReceiveRequest(uintptr_t server_message, uintptr_t server_buffer_size, KPhysicalAddress server_message_paddr, std::shared_ptr* out_context, std::weak_ptr manager) { @@ -1098,7 +1104,7 @@ Result KServerSession::ReceiveRequest(KernelCore& kernel, uintptr_t server_messa KThread* client_thread; { - KScopedSchedulerLock sl{kernel}; + KScopedSchedulerLock sl{m_kernel}; // Ensure that we can service the request. R_UNLESS(!m_parent->IsClientClosed(), ResultSessionClosed); @@ -1118,11 +1124,11 @@ Result KServerSession::ReceiveRequest(KernelCore& kernel, uintptr_t server_messa R_UNLESS(client_thread != nullptr, ResultSessionClosed); // Open the client thread. - client_thread->Open(kernel); + client_thread->Open(); } SCOPE_EXIT { - client_thread->Close(kernel); + client_thread->Close(); }; // Set the request as our current. @@ -1144,13 +1150,13 @@ Result KServerSession::ReceiveRequest(KernelCore& kernel, uintptr_t server_messa Core::Memory::Memory& memory{client_thread->GetOwnerProcess()->GetMemory()}; u32* cmd_buf{reinterpret_cast(memory.GetPointer(client_message))}; *out_context = - std::make_shared(kernel, memory, this, client_thread); + std::make_shared(m_kernel, memory, this, client_thread); (*out_context)->SetSessionRequestManager(manager); (*out_context)->PopulateFromIncomingCommandBuffer(cmd_buf); // We succeeded. R_SUCCEED(); } else { - result = ReceiveMessage(kernel, recv_list_broken, server_message, server_buffer_size, + result = ReceiveMessage(m_kernel, recv_list_broken, server_message, server_buffer_size, server_message_paddr, *client_thread, client_message, client_buffer_size, this, request); } @@ -1162,11 +1168,11 @@ Result KServerSession::ReceiveRequest(KernelCore& kernel, uintptr_t server_messa // Clear the current request. { - KScopedSchedulerLock sl(kernel); + KScopedSchedulerLock sl(m_kernel); ASSERT(m_current_request == request); m_current_request = nullptr; if (!m_request_list.empty()) { - this->NotifyAvailable(kernel); + this->NotifyAvailable(); } } @@ -1174,7 +1180,7 @@ Result KServerSession::ReceiveRequest(KernelCore& kernel, uintptr_t server_messa { // After we reply, close our reference to the request. SCOPE_EXIT { - request->Close(kernel); + request->Close(); }; // Get the event to check whether the request is async. @@ -1193,13 +1199,13 @@ Result KServerSession::ReceiveRequest(KernelCore& kernel, uintptr_t server_messa client_pt.UnlockForIpcUserBuffer(client_message, client_buffer_size); // Signal the event. - event->Signal(kernel); + event->Signal(); } else { // End the client thread's wait. - KScopedSchedulerLock sl(kernel); + KScopedSchedulerLock sl(m_kernel); if (!client_thread->IsTerminationRequested()) { - client_thread->EndWait(kernel, result_for_client); + client_thread->EndWait(result_for_client); } } } @@ -1215,7 +1221,7 @@ Result KServerSession::ReceiveRequest(KernelCore& kernel, uintptr_t server_messa R_RETURN(result); } -Result KServerSession::SendReply(KernelCore& kernel, uintptr_t server_message, uintptr_t server_buffer_size, +Result KServerSession::SendReply(uintptr_t server_message, uintptr_t server_buffer_size, KPhysicalAddress server_message_paddr, bool is_hle) { // Lock the session. KScopedLightLock lk{m_lock}; @@ -1223,7 +1229,7 @@ Result KServerSession::SendReply(KernelCore& kernel, uintptr_t server_message, u // Get the request. KSessionRequest* request; { - KScopedSchedulerLock sl{kernel}; + KScopedSchedulerLock sl{m_kernel}; // Get the current request. request = m_current_request; @@ -1232,13 +1238,13 @@ Result KServerSession::SendReply(KernelCore& kernel, uintptr_t server_message, u // Clear the current request, since we're processing it. m_current_request = nullptr; if (!m_request_list.empty()) { - this->NotifyAvailable(kernel); + this->NotifyAvailable(); } } // Close reference to the request once we're done processing it. SCOPE_EXIT { - request->Close(kernel); + request->Close(); }; // Extract relevant information from the request. @@ -1257,7 +1263,7 @@ Result KServerSession::SendReply(KernelCore& kernel, uintptr_t server_message, u // HLE servers write directly to a pointer to the thread command buffer. Therefore // the reply has already been written in this case. } else { - result = SendMessage(kernel, server_message, server_buffer_size, server_message_paddr, + result = SendMessage(m_kernel, server_message, server_buffer_size, server_message_paddr, *client_thread, client_message, client_buffer_size, this, request); } } else if (!is_hle) { @@ -1269,7 +1275,7 @@ Result KServerSession::SendReply(KernelCore& kernel, uintptr_t server_message, u (client_process != nullptr) ? std::addressof(client_process->GetPageTable()) : nullptr; // Cleanup server handles. - result = CleanupServerHandles(kernel, server_message, server_buffer_size, + result = CleanupServerHandles(m_kernel, server_message, server_buffer_size, server_message_paddr); // Cleanup mappings. @@ -1307,13 +1313,13 @@ Result KServerSession::SendReply(KernelCore& kernel, uintptr_t server_message, u client_page_table->UnlockForIpcUserBuffer(client_message, client_buffer_size); // Signal the event. - event->Signal(kernel); + event->Signal(); } else { // End the client thread's wait. - KScopedSchedulerLock sl{kernel}; + KScopedSchedulerLock sl{m_kernel}; if (!client_thread->IsTerminationRequested()) { - client_thread->EndWait(kernel, client_result); + client_thread->EndWait(client_result); } } } @@ -1321,45 +1327,45 @@ Result KServerSession::SendReply(KernelCore& kernel, uintptr_t server_message, u R_RETURN(result); } -Result KServerSession::OnRequest(KernelCore& kernel, KSessionRequest* request) { +Result KServerSession::OnRequest(KSessionRequest* request) { // Create the wait queue. - ThreadQueueImplForKServerSessionRequest wait_queue{kernel}; + ThreadQueueImplForKServerSessionRequest wait_queue{m_kernel}; { // Lock the scheduler. - KScopedSchedulerLock sl{kernel}; + KScopedSchedulerLock sl{m_kernel}; // Ensure that we can handle new requests. R_UNLESS(!m_parent->IsServerClosed(), ResultSessionClosed); // Check that we're not terminating. - R_UNLESS(!GetCurrentThread(kernel).IsTerminationRequested(), ResultTerminationRequested); + R_UNLESS(!GetCurrentThread(m_kernel).IsTerminationRequested(), ResultTerminationRequested); // Get whether we're empty. const bool was_empty = m_request_list.empty(); // Add the request to the list. - request->Open(kernel); + request->Open(); m_request_list.push_back(*request); // If we were empty, signal. if (was_empty) { - this->NotifyAvailable(kernel); + this->NotifyAvailable(); } // If we have a request event, this is asynchronous, and we don't need to wait. R_SUCCEED_IF(request->GetEvent() != nullptr); // This is a synchronous request, so we should wait for our request to complete. - GetCurrentThread(kernel).SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); - GetCurrentThread(kernel).BeginWait(kernel, std::addressof(wait_queue)); + GetCurrentThread(m_kernel).SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); + GetCurrentThread(m_kernel).BeginWait(std::addressof(wait_queue)); } - return GetCurrentThread(kernel).GetWaitResult(); + return GetCurrentThread(m_kernel).GetWaitResult(); } -bool KServerSession::IsSignaled(KernelCore& kernel) const { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); +bool KServerSession::IsSignaled() const { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); // If the client is closed, we're always signaled. if (m_parent->IsClientClosed()) { @@ -1370,7 +1376,7 @@ bool KServerSession::IsSignaled(KernelCore& kernel) const { return !m_request_list.empty() && m_current_request == nullptr; } -void KServerSession::CleanupRequests(KernelCore& kernel) { +void KServerSession::CleanupRequests() { KScopedLightLock lk(m_lock); // Clean up any pending requests. @@ -1378,7 +1384,7 @@ void KServerSession::CleanupRequests(KernelCore& kernel) { // Get the next request. KSessionRequest* request = nullptr; { - KScopedSchedulerLock sl{kernel}; + KScopedSchedulerLock sl{m_kernel}; if (m_current_request) { // Choose the current request if we have one. @@ -1398,7 +1404,7 @@ void KServerSession::CleanupRequests(KernelCore& kernel) { // Close a reference to the request once it's cleaned up. SCOPE_EXIT { - request->Close(kernel); + request->Close(); }; // Extract relevant information from the request. @@ -1428,20 +1434,20 @@ void KServerSession::CleanupRequests(KernelCore& kernel) { client_page_table->UnlockForIpcUserBuffer(client_message, client_buffer_size); // Signal the event. - event->Signal(kernel); + event->Signal(); } else { // End the client thread's wait. - KScopedSchedulerLock sl{kernel}; + KScopedSchedulerLock sl{m_kernel}; if (!client_thread->IsTerminationRequested()) { - client_thread->EndWait(kernel, ResultSessionClosed); + client_thread->EndWait(ResultSessionClosed); } } } } } -void KServerSession::OnClientClosed(KernelCore& kernel) { +void KServerSession::OnClientClosed() { KScopedLightLock lk{m_lock}; // Handle any pending requests. @@ -1456,12 +1462,12 @@ void KServerSession::OnClientClosed(KernelCore& kernel) { // Get the next request. { - KScopedSchedulerLock sl{kernel}; + KScopedSchedulerLock sl{m_kernel}; if (m_current_request != nullptr && m_current_request != prev_request) { // Set the request, open a reference as we process it. request = m_current_request; - request->Open(kernel); + request->Open(); cur_request = true; // Get thread and event for the request. @@ -1497,14 +1503,14 @@ void KServerSession::OnClientClosed(KernelCore& kernel) { // Ensure that we close the request when done. SCOPE_EXIT { - request->Close(kernel); + request->Close(); }; // If we're terminating, close a reference to the thread and event. if (terminate) { - thread->Close(kernel); + thread->Close(); if (event != nullptr) { - event->Close(kernel); + event->Close(); } } @@ -1528,12 +1534,12 @@ void KServerSession::OnClientClosed(KernelCore& kernel) { client_pt.UnlockForIpcUserBuffer(request->GetAddress(), request->GetSize()); // Signal the event. - event->Signal(kernel); + event->Signal(); } } // Notify. - this->NotifyAvailable(kernel, ResultSessionClosed); + this->NotifyAvailable(ResultSessionClosed); } } // namespace Kernel diff --git a/src/core/hle/kernel/k_server_session.h b/src/core/hle/kernel/k_server_session.h index 217e7dc7be..2876c231b2 100644 --- a/src/core/hle/kernel/k_server_session.h +++ b/src/core/hle/kernel/k_server_session.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -39,7 +36,7 @@ public: explicit KServerSession(KernelCore& kernel); ~KServerSession() override; - void Destroy(KernelCore& kernel) override; + void Destroy() override; void Initialize(KSession* p) { m_parent = p; @@ -49,29 +46,29 @@ public: return m_parent; } - bool IsSignaled(KernelCore& kernel) const override; - void OnClientClosed(KernelCore& kernel); + bool IsSignaled() const override; + void OnClientClosed(); - Result OnRequest(KernelCore& kernel, KSessionRequest* request); - Result SendReply(KernelCore& kernel, uintptr_t server_message, uintptr_t server_buffer_size, + Result OnRequest(KSessionRequest* request); + Result SendReply(uintptr_t server_message, uintptr_t server_buffer_size, KPhysicalAddress server_message_paddr, bool is_hle = false); - Result ReceiveRequest(KernelCore& kernel, uintptr_t server_message, uintptr_t server_buffer_size, + Result ReceiveRequest(uintptr_t server_message, uintptr_t server_buffer_size, KPhysicalAddress server_message_paddr, std::shared_ptr* out_context = nullptr, std::weak_ptr manager = {}); - Result SendReplyHLE(KernelCore& kernel) { - R_RETURN(this->SendReply(kernel, 0, 0, 0, true)); + Result SendReplyHLE() { + R_RETURN(this->SendReply(0, 0, 0, true)); } - Result ReceiveRequestHLE(KernelCore& kernel, std::shared_ptr* out_context, + Result ReceiveRequestHLE(std::shared_ptr* out_context, std::weak_ptr manager) { - R_RETURN(this->ReceiveRequest(kernel, 0, 0, 0, out_context, manager)); + R_RETURN(this->ReceiveRequest(0, 0, 0, out_context, manager)); } private: /// Frees up waiting client sessions when this server session is about to die - void CleanupRequests(KernelCore& kernel); + void CleanupRequests(); /// KSession that owns this KServerSession KSession* m_parent{}; diff --git a/src/core/hle/kernel/k_session.cpp b/src/core/hle/kernel/k_session.cpp index 58b0d5de67..4a1f6027ee 100644 --- a/src/core/hle/kernel/k_session.cpp +++ b/src/core/hle/kernel/k_session.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -16,12 +13,12 @@ KSession::KSession(KernelCore& kernel) : KAutoObjectWithSlabHeapAndContainer{kernel}, m_server{kernel}, m_client{kernel} {} KSession::~KSession() = default; -void KSession::Initialize(KernelCore& kernel, KClientPort* client_port, uintptr_t name) { +void KSession::Initialize(KClientPort* client_port, uintptr_t name) { // Increment reference count. // Because reference count is one on creation, this will result // in a reference count of two. Thus, when both server and client are closed // this object will be destroyed. - this->Open(kernel); + this->Open(); // Create our sub sessions. KAutoObject::Create(std::addressof(m_server)); @@ -36,45 +33,45 @@ void KSession::Initialize(KernelCore& kernel, KClientPort* client_port, uintptr_ m_name = name; // Set our owner process. - m_process = GetCurrentProcessPointer(kernel); - m_process->Open(kernel); + m_process = GetCurrentProcessPointer(m_kernel); + m_process->Open(); // Set our port. m_port = client_port; if (m_port != nullptr) { - m_port->Open(kernel); + m_port->Open(); } // Mark initialized. m_initialized = true; } -void KSession::Finalize(KernelCore& kernel) { +void KSession::Finalize() { if (m_port != nullptr) { - m_port->OnSessionFinalized(kernel); - m_port->Close(kernel); + m_port->OnSessionFinalized(); + m_port->Close(); } } -void KSession::OnServerClosed(KernelCore& kernel) { +void KSession::OnServerClosed() { if (this->GetState() == State::Normal) { this->SetState(State::ServerClosed); m_client.OnServerClosed(); } } -void KSession::OnClientClosed(KernelCore& kernel) { +void KSession::OnClientClosed() { if (this->GetState() == State::Normal) { - this->SetState(State::ClientClosed); - m_server.OnClientClosed(kernel); + SetState(State::ClientClosed); + m_server.OnClientClosed(); } } -void KSession::PostDestroy(KernelCore& kernel, uintptr_t arg) { +void KSession::PostDestroy(uintptr_t arg) { // Release the session count resource the owner process holds. KProcess* owner = reinterpret_cast(arg); - owner->GetResourceLimit()->Release(kernel, LimitableResource::SessionCountMax, 1); - owner->Close(kernel); + owner->GetResourceLimit()->Release(LimitableResource::SessionCountMax, 1); + owner->Close(); } } // namespace Kernel diff --git a/src/core/hle/kernel/k_session.h b/src/core/hle/kernel/k_session.h index 0d77bc1fd4..3f4dd5989f 100644 --- a/src/core/hle/kernel/k_session.h +++ b/src/core/hle/kernel/k_session.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -24,8 +21,8 @@ public: explicit KSession(KernelCore& kernel); ~KSession() override; - void Initialize(KernelCore& kernel, KClientPort* port, uintptr_t name); - void Finalize(KernelCore& kernel) override; + void Initialize(KClientPort* port, uintptr_t name); + void Finalize() override; bool IsInitialized() const override { return m_initialized; @@ -35,9 +32,11 @@ public: return reinterpret_cast(m_process); } - static void PostDestroy(KernelCore& kernel, uintptr_t arg); - void OnServerClosed(KernelCore& kernel); - void OnClientClosed(KernelCore& kernel); + static void PostDestroy(uintptr_t arg); + + void OnServerClosed(); + + void OnClientClosed(); bool IsServerClosed() const { return this->GetState() != State::Normal; @@ -47,8 +46,8 @@ public: return this->GetState() != State::Normal; } - Result OnRequest(KernelCore& kernel, KSessionRequest* request) { - R_RETURN(m_server.OnRequest(kernel, request)); + Result OnRequest(KSessionRequest* request) { + R_RETURN(m_server.OnRequest(request)); } KClientSession& GetClientSession() { diff --git a/src/core/hle/kernel/k_session_request.cpp b/src/core/hle/kernel/k_session_request.cpp index 25451a3922..9a69b4ffc1 100644 --- a/src/core/hle/kernel/k_session_request.cpp +++ b/src/core/hle/kernel/k_session_request.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -21,7 +18,7 @@ Result KSessionRequest::SessionMappings::PushMap(KProcessAddress client, KProces } else { // Allocate a page for the extra mappings. if (m_mappings == nullptr) { - KPageBuffer* page_buffer = KPageBuffer::Allocate(kernel); + KPageBuffer* page_buffer = KPageBuffer::Allocate(m_kernel); R_UNLESS(page_buffer != nullptr, ResultOutOfMemory); m_mappings = reinterpret_cast(page_buffer); @@ -57,7 +54,7 @@ Result KSessionRequest::SessionMappings::PushExchange(KProcessAddress client, void KSessionRequest::SessionMappings::Finalize() { if (m_mappings) { - KPageBuffer::Free(kernel, reinterpret_cast(m_mappings)); + KPageBuffer::Free(m_kernel, reinterpret_cast(m_mappings)); m_mappings = nullptr; } } diff --git a/src/core/hle/kernel/k_session_request.h b/src/core/hle/kernel/k_session_request.h index 6665eca56f..283669e0ac 100644 --- a/src/core/hle/kernel/k_session_request.h +++ b/src/core/hle/kernel/k_session_request.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -59,7 +56,7 @@ public: }; public: - explicit SessionMappings(KernelCore& kernel_) : kernel(kernel_) {} + explicit SessionMappings(KernelCore& kernel) : m_kernel(kernel) {} void Initialize() {} void Finalize(); @@ -158,7 +155,7 @@ public: } private: - KernelCore& kernel; + KernelCore& m_kernel; std::array m_static_mappings{}; Mapping* m_mappings{}; u8 m_num_send{}; @@ -177,26 +174,26 @@ public: return req; } - void Destroy(KernelCore& kernel) override { - this->Finalize(kernel); - KSessionRequest::Free(kernel, this); + void Destroy() override { + this->Finalize(); + KSessionRequest::Free(m_kernel, this); } - void Initialize(KernelCore& kernel, KEvent* event, uintptr_t address, size_t size) { + void Initialize(KEvent* event, uintptr_t address, size_t size) { m_mappings.Initialize(); - m_thread = GetCurrentThreadPointer(kernel); + m_thread = GetCurrentThreadPointer(m_kernel); m_event = event; m_address = address; m_size = size; - m_thread->Open(kernel); + m_thread->Open(); if (m_event != nullptr) { - m_event->Open(kernel); + m_event->Open(); } } - static void PostDestroy(KernelCore& kernel, uintptr_t arg) {} + static void PostDestroy(uintptr_t arg) {} KThread* GetThread() const { return m_thread; @@ -214,9 +211,9 @@ public: return m_server; } - void SetServerProcess(KernelCore& kernel, KProcess* process) { + void SetServerProcess(KProcess* process) { m_server = process; - m_server->Open(kernel); + m_server->Open(); } void ClearThread() { @@ -292,16 +289,17 @@ public: private: // NOTE: This is public and virtual in Nintendo's kernel. - void Finalize(KernelCore& kernel) override { + void Finalize() override { m_mappings.Finalize(); + if (m_thread) { - m_thread->Close(kernel); + m_thread->Close(); } if (m_event) { - m_event->Close(kernel); + m_event->Close(); } if (m_server) { - m_server->Close(kernel); + m_server->Close(); } } diff --git a/src/core/hle/kernel/k_shared_memory.cpp b/src/core/hle/kernel/k_shared_memory.cpp index 61f2872560..f713968f68 100644 --- a/src/core/hle/kernel/k_shared_memory.cpp +++ b/src/core/hle/kernel/k_shared_memory.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: 2014 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -18,7 +15,7 @@ namespace Kernel { KSharedMemory::KSharedMemory(KernelCore& kernel) : KAutoObjectWithSlabHeapAndContainer{kernel} {} KSharedMemory::~KSharedMemory() = default; -Result KSharedMemory::Initialize(KernelCore& kernel, Core::DeviceMemory& device_memory, KProcess* owner_process, +Result KSharedMemory::Initialize(Core::DeviceMemory& device_memory, KProcess* owner_process, Svc::MemoryPermission owner_permission, Svc::MemoryPermission user_permission, std::size_t size) { // Set members. @@ -31,10 +28,11 @@ Result KSharedMemory::Initialize(KernelCore& kernel, Core::DeviceMemory& device_ const size_t num_pages = Common::DivideUp(size, PageSize); // Get the resource limit. - KResourceLimit* reslimit = kernel.GetSystemResourceLimit(); + KResourceLimit* reslimit = m_kernel.GetSystemResourceLimit(); // Reserve memory for ourselves. - KScopedResourceReservation memory_reservation(kernel, reslimit, LimitableResource::PhysicalMemoryMax, size); + KScopedResourceReservation memory_reservation(reslimit, LimitableResource::PhysicalMemoryMax, + size); R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); // Allocate the memory. @@ -42,11 +40,12 @@ Result KSharedMemory::Initialize(KernelCore& kernel, Core::DeviceMemory& device_ //! HACK: Open continuous mapping from sysmodule pool. auto option = KMemoryManager::EncodeOption(KMemoryManager::Pool::Secure, KMemoryManager::Direction::FromBack); - m_physical_address = kernel.MemoryManager().AllocateAndOpenContinuous(num_pages, 1, option); + m_physical_address = m_kernel.MemoryManager().AllocateAndOpenContinuous(num_pages, 1, option); R_UNLESS(m_physical_address != 0, ResultOutOfMemory); //! Insert the result into our page group. - m_page_group.emplace(kernel, std::addressof(kernel.GetSystemSystemResource().GetBlockInfoManager())); + m_page_group.emplace(m_kernel, + std::addressof(m_kernel.GetSystemSystemResource().GetBlockInfoManager())); m_page_group->AddBlock(m_physical_address, num_pages); // Commit our reservation. @@ -54,7 +53,7 @@ Result KSharedMemory::Initialize(KernelCore& kernel, Core::DeviceMemory& device_ // Set our resource limit. m_resource_limit = reslimit; - m_resource_limit->Open(kernel); + m_resource_limit->Open(); // Mark initialized. m_is_initialized = true; @@ -67,14 +66,14 @@ Result KSharedMemory::Initialize(KernelCore& kernel, Core::DeviceMemory& device_ R_SUCCEED(); } -void KSharedMemory::Finalize(KernelCore& kernel) { +void KSharedMemory::Finalize() { // Close and finalize the page group. - m_page_group->Close(kernel); + m_page_group->Close(); m_page_group->Finalize(); // Release the memory reservation. - m_resource_limit->Release(kernel, LimitableResource::PhysicalMemoryMax, m_size); - m_resource_limit->Close(kernel); + m_resource_limit->Release(LimitableResource::PhysicalMemoryMax, m_size); + m_resource_limit->Close(); } Result KSharedMemory::Map(KProcess& target_process, KProcessAddress address, std::size_t map_size, diff --git a/src/core/hle/kernel/k_shared_memory.h b/src/core/hle/kernel/k_shared_memory.h index 3aede457c9..54b23d7ac2 100644 --- a/src/core/hle/kernel/k_shared_memory.h +++ b/src/core/hle/kernel/k_shared_memory.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: 2014 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -29,7 +26,7 @@ public: explicit KSharedMemory(KernelCore& kernel); ~KSharedMemory() override; - Result Initialize(KernelCore& kernel, Core::DeviceMemory& device_memory_, KProcess* owner_process_, + Result Initialize(Core::DeviceMemory& device_memory_, KProcess* owner_process_, Svc::MemoryPermission owner_permission_, Svc::MemoryPermission user_permission_, std::size_t size_); @@ -69,12 +66,12 @@ public: return m_device_memory->GetPointer(m_physical_address + offset); } - void Finalize(KernelCore& kernel) override; + void Finalize() override; bool IsInitialized() const override { return m_is_initialized; } - static void PostDestroy(KernelCore& kernel, uintptr_t arg) {} + static void PostDestroy(uintptr_t arg) {} private: Core::DeviceMemory* m_device_memory{}; diff --git a/src/core/hle/kernel/k_synchronization_object.cpp b/src/core/hle/kernel/k_synchronization_object.cpp index 221cab655f..3e5b735b1e 100644 --- a/src/core/hle/kernel/k_synchronization_object.cpp +++ b/src/core/hle/kernel/k_synchronization_object.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -21,10 +18,12 @@ namespace { class ThreadQueueImplForKSynchronizationObjectWait final : public KThreadQueueWithoutEndWait { public: - ThreadQueueImplForKSynchronizationObjectWait(KernelCore& kernel, KSynchronizationObject** o, KSynchronizationObject::ThreadListNode* n, s32 c) + ThreadQueueImplForKSynchronizationObjectWait(KernelCore& kernel, KSynchronizationObject** o, + KSynchronizationObject::ThreadListNode* n, s32 c) : KThreadQueueWithoutEndWait(kernel), m_objects(o), m_nodes(n), m_count(c) {} - void NotifyAvailable(KernelCore& kernel, KThread* waiting_thread, KSynchronizationObject* signaled_object, Result wait_result) override { + void NotifyAvailable(KThread* waiting_thread, KSynchronizationObject* signaled_object, + Result wait_result) override { // Determine the sync index, and unlink all nodes. s32 sync_index = -1; for (auto i = 0; i < m_count; ++i) { @@ -44,10 +43,10 @@ public: waiting_thread->ClearCancellable(); // Invoke the base end wait handler. - KThreadQueue::EndWait(kernel, waiting_thread, wait_result); + KThreadQueue::EndWait(waiting_thread, wait_result); } - void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { + void CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { // Remove all nodes from our list. for (auto i = 0; i < m_count; ++i) { m_objects[i]->UnlinkNode(std::addressof(m_nodes[i])); @@ -57,7 +56,7 @@ public: waiting_thread->ClearCancellable(); // Invoke the base cancel wait handler. - KThreadQueue::CancelWait(kernel, waiting_thread, wait_result, cancel_timer_task); + KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); } private: @@ -68,9 +67,9 @@ private: } // namespace -void KSynchronizationObject::Finalize(KernelCore& kernel) { +void KSynchronizationObject::Finalize() { this->OnFinalizeSynchronizationObject(); - KAutoObject::Finalize(kernel); + KAutoObject::Finalize(); } Result KSynchronizationObject::Wait(KernelCore& kernel, s32* out_index, @@ -99,7 +98,7 @@ Result KSynchronizationObject::Wait(KernelCore& kernel, s32* out_index, for (auto i = 0; i < num_objects; ++i) { ASSERT(objects[i] != nullptr); - if (objects[i]->IsSignaled(kernel)) { + if (objects[i]->IsSignaled()) { *out_index = i; slp.CancelSleep(); R_THROW(ResultSuccess); @@ -135,7 +134,7 @@ Result KSynchronizationObject::Wait(KernelCore& kernel, s32* out_index, // Wait for an object to be signaled. wait_queue.SetHardwareTimer(timer); - thread->BeginWait(kernel, std::addressof(wait_queue)); + thread->BeginWait(std::addressof(wait_queue)); thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Synchronization); } @@ -150,26 +149,26 @@ KSynchronizationObject::KSynchronizationObject(KernelCore& kernel) : KAutoObject KSynchronizationObject::~KSynchronizationObject() = default; -void KSynchronizationObject::NotifyAvailable(KernelCore& kernel, Result result) { - KScopedSchedulerLock sl(kernel); +void KSynchronizationObject::NotifyAvailable(Result result) { + KScopedSchedulerLock sl(m_kernel); // If we're not signaled, we've nothing to notify. - if (!this->IsSignaled(kernel)) { + if (!this->IsSignaled()) { return; } // Iterate over each thread. for (auto* cur_node = m_thread_list_head; cur_node != nullptr; cur_node = cur_node->next) { - cur_node->thread->NotifyAvailable(kernel, this, result); + cur_node->thread->NotifyAvailable(this, result); } } -std::vector KSynchronizationObject::GetWaitingThreadsForDebugging(KernelCore& kernel) const { +std::vector KSynchronizationObject::GetWaitingThreadsForDebugging() const { std::vector threads; // If debugging, dump the list of waiters. { - KScopedSchedulerLock lock(kernel); + KScopedSchedulerLock lock(m_kernel); for (auto* cur_node = m_thread_list_head; cur_node != nullptr; cur_node = cur_node->next) { threads.emplace_back(cur_node->thread); } diff --git a/src/core/hle/kernel/k_synchronization_object.h b/src/core/hle/kernel/k_synchronization_object.h index 4c54a4d2cb..d55a2673df 100644 --- a/src/core/hle/kernel/k_synchronization_object.h +++ b/src/core/hle/kernel/k_synchronization_object.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -27,13 +24,14 @@ public: KThread* thread{}; }; - static Result Wait(KernelCore& kernel, s32* out_index, KSynchronizationObject** objects, const s32 num_objects, s64 timeout); + static Result Wait(KernelCore& kernel, s32* out_index, KSynchronizationObject** objects, + const s32 num_objects, s64 timeout); - void Finalize(KernelCore& kernel) override; + void Finalize() override; - virtual bool IsSignaled(KernelCore& kernel) const = 0; + virtual bool IsSignaled() const = 0; - std::vector GetWaitingThreadsForDebugging(KernelCore& kernel) const; + std::vector GetWaitingThreadsForDebugging() const; void LinkNode(ThreadListNode* node_) { // Link the node to the list. @@ -73,9 +71,9 @@ protected: virtual void OnFinalizeSynchronizationObject() {} - void NotifyAvailable(KernelCore& kernel, Result result); - void NotifyAvailable(KernelCore& kernel) { - return this->NotifyAvailable(kernel, ResultSuccess); + void NotifyAvailable(Result result); + void NotifyAvailable() { + return this->NotifyAvailable(ResultSuccess); } private: diff --git a/src/core/hle/kernel/k_system_resource.cpp b/src/core/hle/kernel/k_system_resource.cpp index fb664eb57a..b51941faf4 100644 --- a/src/core/hle/kernel/k_system_resource.cpp +++ b/src/core/hle/kernel/k_system_resource.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -10,7 +7,8 @@ namespace Kernel { -Result KSecureSystemResource::Initialize(KernelCore& kernel, size_t size, KResourceLimit* resource_limit, KMemoryManager::Pool pool) { +Result KSecureSystemResource::Initialize(size_t size, KResourceLimit* resource_limit, + KMemoryManager::Pool pool) { // Set members. m_resource_limit = resource_limit; m_resource_size = size; @@ -20,17 +18,18 @@ Result KSecureSystemResource::Initialize(KernelCore& kernel, size_t size, KResou const size_t secure_size = this->CalculateRequiredSecureMemorySize(); // Reserve memory for our secure resource. - KScopedResourceReservation memory_reservation(kernel, m_resource_limit, Svc::LimitableResource::PhysicalMemoryMax, secure_size); + KScopedResourceReservation memory_reservation( + m_resource_limit, Svc::LimitableResource::PhysicalMemoryMax, secure_size); R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); // Allocate secure memory. - R_TRY(KSystemControl::AllocateSecureMemory(kernel, std::addressof(m_resource_address), + R_TRY(KSystemControl::AllocateSecureMemory(m_kernel, std::addressof(m_resource_address), m_resource_size, static_cast(m_resource_pool))); ASSERT(m_resource_address != 0); // Ensure we clean up the secure memory, if we fail past this point. ON_RESULT_FAILURE { - KSystemControl::FreeSecureMemory(kernel, m_resource_address, m_resource_size, + KSystemControl::FreeSecureMemory(m_kernel, m_resource_address, m_resource_size, static_cast(m_resource_pool)); }; @@ -41,9 +40,9 @@ Result KSecureSystemResource::Initialize(KernelCore& kernel, size_t size, KResou // Get resource pointer. KPhysicalAddress resource_paddr = - KPageTable::GetHeapPhysicalAddress(kernel, m_resource_address); + KPageTable::GetHeapPhysicalAddress(m_kernel, m_resource_address); auto* resource = - kernel.System().DeviceMemory().GetPointer(resource_paddr); + m_kernel.System().DeviceMemory().GetPointer(resource_paddr); // Initialize slab heaps. m_dynamic_page_manager.Initialize(m_resource_address + rc_size, m_resource_size - rc_size, @@ -67,7 +66,7 @@ Result KSecureSystemResource::Initialize(KernelCore& kernel, size_t size, KResou memory_reservation.Commit(); // Open reference to our resource limit. - m_resource_limit->Open(kernel); + m_resource_limit->Open(); // Set ourselves as initialized. m_is_initialized = true; @@ -75,25 +74,26 @@ Result KSecureSystemResource::Initialize(KernelCore& kernel, size_t size, KResou R_SUCCEED(); } -void KSecureSystemResource::Finalize(KernelCore& kernel) { +void KSecureSystemResource::Finalize() { // Check that we have no outstanding allocations. ASSERT(m_memory_block_slab_manager.GetUsed() == 0); ASSERT(m_block_info_manager.GetUsed() == 0); ASSERT(m_page_table_manager.GetUsed() == 0); // Free our secure memory. - KSystemControl::FreeSecureMemory(kernel, m_resource_address, m_resource_size, + KSystemControl::FreeSecureMemory(m_kernel, m_resource_address, m_resource_size, static_cast(m_resource_pool)); // Release the memory reservation. - m_resource_limit->Release(kernel, Svc::LimitableResource::PhysicalMemoryMax, + m_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, this->CalculateRequiredSecureMemorySize()); // Close reference to our resource limit. - m_resource_limit->Close(kernel); + m_resource_limit->Close(); } -size_t KSecureSystemResource::CalculateRequiredSecureMemorySize(size_t size, KMemoryManager::Pool pool) { +size_t KSecureSystemResource::CalculateRequiredSecureMemorySize(size_t size, + KMemoryManager::Pool pool) { return KSystemControl::CalculateRequiredSecureMemorySize(size, static_cast(pool)); } diff --git a/src/core/hle/kernel/k_system_resource.h b/src/core/hle/kernel/k_system_resource.h index c0362497f9..6ea4821858 100644 --- a/src/core/hle/kernel/k_system_resource.h +++ b/src/core/hle/kernel/k_system_resource.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -32,7 +29,7 @@ protected: } public: - virtual void Destroy(KernelCore& kernel) override { + virtual void Destroy() override { UNREACHABLE_MSG("KSystemResource::Destroy() was called"); } @@ -96,13 +93,13 @@ public: this->SetSecureResource(); } - Result Initialize(KernelCore& kernel, size_t size, KResourceLimit* resource_limit, KMemoryManager::Pool pool); - void Finalize(KernelCore& kernel); + Result Initialize(size_t size, KResourceLimit* resource_limit, KMemoryManager::Pool pool); + void Finalize(); bool IsInitialized() const { return m_is_initialized; } - static void PostDestroy(KernelCore& kernel, uintptr_t arg) {} + static void PostDestroy(uintptr_t arg) {} size_t CalculateRequiredSecureMemorySize() const { return CalculateRequiredSecureMemorySize(m_resource_size, m_resource_pool); diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index b499bd4073..0af315d726 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -95,12 +95,12 @@ namespace Kernel { explicit ThreadQueueImplForKThreadSetProperty(KernelCore& kernel, KThread::WaiterList* wl) : KThreadQueue(kernel), m_wait_list(wl) {} - void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { + void CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { // Remove the thread from the wait list. m_wait_list->erase(m_wait_list->iterator_to(*waiting_thread)); // Invoke the base cancel wait handler. - KThreadQueue::CancelWait(kernel, waiting_thread, wait_result, cancel_timer_task); + KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); } private: @@ -113,7 +113,7 @@ namespace Kernel { : KAutoObjectWithSlabHeapAndContainer{kernel}, m_activity_pause_lock{kernel} {} KThread::~KThread() = default; - Result KThread::Initialize(KernelCore& kernel, KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, + Result KThread::Initialize(KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, s32 prio, s32 virt_core, KProcess* owner, ThreadType type) { // Assert parameters are valid. ASSERT((type == ThreadType::Main) || (type == ThreadType::Dummy) || @@ -225,12 +225,12 @@ namespace Kernel { if (owner != nullptr) { // Setup the TLS, if needed. if (type == ThreadType::User) { - R_TRY(owner->CreateThreadLocalRegion(kernel, std::addressof(m_tls_address))); + R_TRY(owner->CreateThreadLocalRegion(std::addressof(m_tls_address))); owner->GetMemory().ZeroBlock(m_tls_address, Svc::ThreadLocalRegionSize); } m_parent = owner; - m_parent->Open(kernel); + m_parent->Open(); } // Initialize thread context. @@ -247,28 +247,28 @@ namespace Kernel { this->SetInExceptionHandler(); // Set thread ID. - m_thread_id = kernel.CreateNewThreadID(); + m_thread_id = m_kernel.CreateNewThreadID(); // We initialized! m_initialized = true; // Register ourselves with our parent process. if (m_parent != nullptr) { - m_parent->RegisterThread(kernel, this); + m_parent->RegisterThread(this); if (m_parent->IsSuspended()) { - RequestSuspend(kernel, SuspendType::Process); + RequestSuspend(SuspendType::Process); } } R_SUCCEED(); } - Result KThread::InitializeThread(KernelCore& kernel, KThread* thread, KThreadFunction func, uintptr_t arg, + Result KThread::InitializeThread(KThread* thread, KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, s32 prio, s32 core, KProcess* owner, ThreadType type, std::function&& init_func) { // Initialize the thread. - R_TRY(thread->Initialize(kernel, func, arg, user_stack_top, prio, core, owner, type)); + R_TRY(thread->Initialize(func, arg, user_stack_top, prio, core, owner, type)); // Initialize emulation parameters. thread->m_host_context = std::make_shared(std::move(init_func)); @@ -276,9 +276,9 @@ namespace Kernel { R_SUCCEED(); } - Result KThread::InitializeDummyThread(Core::System& system, KThread* thread, KProcess* owner) { + Result KThread::InitializeDummyThread(KThread* thread, KProcess* owner) { // Initialize the thread. - R_TRY(thread->Initialize(system.Kernel(), {}, {}, {}, DummyThreadPriority, 3, owner, ThreadType::Dummy)); + R_TRY(thread->Initialize({}, {}, {}, DummyThreadPriority, 3, owner, ThreadType::Dummy)); // Initialize emulation parameters. thread->m_stack_parameters.disable_count = 0; @@ -287,27 +287,37 @@ namespace Kernel { } Result KThread::InitializeMainThread(Core::System& system, KThread* thread, s32 virt_core) { - R_RETURN(InitializeThread(system.Kernel(), thread, {}, {}, {}, IdleThreadPriority, virt_core, {}, ThreadType::Main, system.GetCpuManager().GetGuestActivateFunc(system.Kernel()))); + R_RETURN(InitializeThread(thread, {}, {}, {}, IdleThreadPriority, virt_core, {}, + ThreadType::Main, system.GetCpuManager().GetGuestActivateFunc())); } Result KThread::InitializeIdleThread(Core::System& system, KThread* thread, s32 virt_core) { - R_RETURN(InitializeThread(system.Kernel(), thread, {}, {}, {}, IdleThreadPriority, virt_core, {}, ThreadType::Main, system.GetCpuManager().GetIdleThreadStartFunc(system.Kernel()))); + R_RETURN(InitializeThread(thread, {}, {}, {}, IdleThreadPriority, virt_core, {}, + ThreadType::Main, system.GetCpuManager().GetIdleThreadStartFunc())); } - Result KThread::InitializeHighPriorityThread(Core::System& system, KThread* thread, KThreadFunction func, uintptr_t arg, s32 virt_core) { - R_RETURN(InitializeThread(system.Kernel(), thread, func, arg, {}, {}, virt_core, nullptr, ThreadType::HighPriority, system.GetCpuManager().GetShutdownThreadStartFunc(system.Kernel()))); + Result KThread::InitializeHighPriorityThread(Core::System& system, KThread* thread, + KThreadFunction func, uintptr_t arg, s32 virt_core) { + R_RETURN(InitializeThread(thread, func, arg, {}, {}, virt_core, nullptr, + ThreadType::HighPriority, + system.GetCpuManager().GetShutdownThreadStartFunc())); } - Result KThread::InitializeUserThread(Core::System& system, KThread* thread, KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, s32 prio, s32 virt_core, KProcess* owner) { + Result KThread::InitializeUserThread(Core::System& system, KThread* thread, KThreadFunction func, + uintptr_t arg, KProcessAddress user_stack_top, s32 prio, + s32 virt_core, KProcess* owner) { system.Kernel().GlobalSchedulerContext().AddThread(thread); - R_RETURN(InitializeThread(system.Kernel(), thread, func, arg, user_stack_top, prio, virt_core, owner, ThreadType::User, system.GetCpuManager().GetGuestThreadFunc(system.Kernel()))); + R_RETURN(InitializeThread(thread, func, arg, user_stack_top, prio, virt_core, owner, + ThreadType::User, system.GetCpuManager().GetGuestThreadFunc())); } - Result KThread::InitializeServiceThread(Core::System& system, KThread* thread, std::function&& func, s32 prio, s32 virt_core, KProcess* owner) { + Result KThread::InitializeServiceThread(Core::System& system, KThread* thread, + std::function&& func, s32 prio, s32 virt_core, + KProcess* owner) { system.Kernel().GlobalSchedulerContext().AddThread(thread); std::function func2{[&system, func_{std::move(func)}] { // Similar to UserModeThreadStarter. - system.Kernel().CurrentScheduler()->OnThreadStart(system.Kernel()); + system.Kernel().CurrentScheduler()->OnThreadStart(); // Run the guest function. func_(); @@ -316,35 +326,35 @@ namespace Kernel { Svc::ExitThread(system); }}; - R_RETURN(InitializeThread(system.Kernel(), thread, {}, {}, {}, prio, virt_core, owner, ThreadType::HighPriority, + R_RETURN(InitializeThread(thread, {}, {}, {}, prio, virt_core, owner, ThreadType::HighPriority, std::move(func2))); } - void KThread::PostDestroy(KernelCore& kernel, uintptr_t arg) { + void KThread::PostDestroy(uintptr_t arg) { KProcess* owner = reinterpret_cast(arg & ~1ULL); const bool resource_limit_release_hint = (arg & 1); const s64 hint_value = (resource_limit_release_hint ? 0 : 1); if (owner != nullptr) { - owner->GetResourceLimit()->Release(kernel, LimitableResource::ThreadCountMax, 1, hint_value); - owner->Close(kernel); + owner->GetResourceLimit()->Release(LimitableResource::ThreadCountMax, 1, hint_value); + owner->Close(); } } - void KThread::Finalize(KernelCore& kernel) { + void KThread::Finalize() { // If the thread has an owner process, unregister it. if (m_parent != nullptr) { - m_parent->UnregisterThread(kernel, this); + m_parent->UnregisterThread(this); } // If the thread has a local region, delete it. if (m_tls_address != 0) { - ASSERT(m_parent->DeleteThreadLocalRegion(kernel, m_tls_address).IsSuccess()); + ASSERT(m_parent->DeleteThreadLocalRegion(m_tls_address).IsSuccess()); } // Release any waiters. { ASSERT(m_waiting_lock_info == nullptr); - KScopedSchedulerLock sl{kernel}; + KScopedSchedulerLock sl{m_kernel}; // Check that we have no kernel waiters. ASSERT(m_num_kernel_waiters == 0); @@ -368,14 +378,14 @@ namespace Kernel { } // Cancel the thread's wait. - waiter->CancelWait(kernel, ResultInvalidState, true); + waiter->CancelWait(ResultInvalidState, true); } // Remove the held lock from our list. it = m_held_lock_info_list.erase(it); // Free the lock info. - LockWithPriorityInheritanceInfo::Free(kernel, lock_info); + LockWithPriorityInheritanceInfo::Free(m_kernel, lock_info); } } @@ -383,35 +393,35 @@ namespace Kernel { m_host_context.reset(); // Perform inherited finalization. - KSynchronizationObject::Finalize(kernel); + KSynchronizationObject::Finalize(); } - bool KThread::IsSignaled(KernelCore& kernel) const { + bool KThread::IsSignaled() const { return m_signaled; } - void KThread::OnTimer(KernelCore& kernel) { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); + void KThread::OnTimer() { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); // If we're waiting, cancel the wait. if (this->GetState() == ThreadState::Waiting) { - m_wait_queue->CancelWait(kernel, this, ResultTimedOut, false); + m_wait_queue->CancelWait(this, ResultTimedOut, false); } } - void KThread::StartTermination(KernelCore& kernel) { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); + void KThread::StartTermination() { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); // Release user exception and unpin, if relevant. if (m_parent != nullptr) { - m_parent->ReleaseUserException(kernel, this); - if (m_parent->GetPinnedThread(GetCurrentCoreId(kernel)) == this) { - m_parent->UnpinCurrentThread(kernel); + m_parent->ReleaseUserException(this); + if (m_parent->GetPinnedThread(GetCurrentCoreId(m_kernel)) == this) { + m_parent->UnpinCurrentThread(); } } // Set state to terminated. - this->SetState(kernel, ThreadState::Terminated); + this->SetState(ThreadState::Terminated); // Clear the thread's status as running in parent. if (m_parent != nullptr) { @@ -419,41 +429,41 @@ namespace Kernel { } // Clear previous thread in KScheduler. - KScheduler::ClearPreviousThread(kernel, this); + KScheduler::ClearPreviousThread(m_kernel, this); // Register terminated dpc flag. this->RegisterDpc(DpcFlag::Terminated); } - void KThread::FinishTermination(KernelCore& kernel) { + void KThread::FinishTermination() { // Ensure that the thread is not executing on any core. if (m_parent != nullptr) { - for (std::size_t i = 0; i < std::size_t(Core::Hardware::NUM_CPU_CORES); ++i) { + for (std::size_t i = 0; i < static_cast(Core::Hardware::NUM_CPU_CORES); ++i) { KThread* core_thread{}; do { - core_thread = kernel.Scheduler(i).GetSchedulerCurrentThread(); + core_thread = m_kernel.Scheduler(i).GetSchedulerCurrentThread(); } while (core_thread == this); } } // Acquire the scheduler lock. - KScopedSchedulerLock sl{kernel}; + KScopedSchedulerLock sl{m_kernel}; // Signal. m_signaled = true; - KSynchronizationObject::NotifyAvailable(kernel); + KSynchronizationObject::NotifyAvailable(); // Close the thread. - this->Close(kernel); + this->Close(); } - void KThread::DoWorkerTaskImpl(KernelCore& kernel) { + void KThread::DoWorkerTaskImpl() { // Finish the termination that was begun by Exit(). - this->FinishTermination(kernel); + this->FinishTermination(); } - void KThread::Pin(KernelCore& kernel, s32 current_core) { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); + void KThread::Pin(s32 current_core) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); // Set ourselves as pinned. GetStackParameters().is_pinned = true; @@ -477,7 +487,7 @@ namespace Kernel { if (active_core != current_core || m_physical_affinity_mask.GetAffinityMask() != m_original_physical_affinity_mask.GetAffinityMask()) { - KScheduler::OnThreadAffinityMaskChanged(kernel, this, + KScheduler::OnThreadAffinityMaskChanged(m_kernel, this, m_original_physical_affinity_mask, active_core); } } @@ -489,15 +499,15 @@ namespace Kernel { static_cast(ThreadState::SuspendShift))); // Update our state. - this->UpdateState(kernel); + this->UpdateState(); } // TODO(bunnei): Update our SVC access permissions. ASSERT(m_parent != nullptr); } - void KThread::Unpin(KernelCore& kernel) { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); + void KThread::Unpin() { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); // Set ourselves as unpinned. this->GetStackParameters().is_pinned = false; @@ -525,7 +535,7 @@ namespace Kernel { std::countl_zero(m_physical_affinity_mask.GetAffinityMask()))); } } - KScheduler::OnThreadAffinityMaskChanged(kernel, this, old_mask, active_core); + KScheduler::OnThreadAffinityMaskChanged(m_kernel, this, old_mask, active_core); } } @@ -536,19 +546,20 @@ namespace Kernel { static_cast(ThreadState::SuspendShift))); // Update our state. - this->UpdateState(kernel); + this->UpdateState(); } // TODO(bunnei): Update our SVC access permissions. ASSERT(m_parent != nullptr); // Resume any threads that began waiting on us while we were pinned. - for (auto it = m_pinned_waiter_list.begin(); it != m_pinned_waiter_list.end(); it = m_pinned_waiter_list.erase(it)) { - it->EndWait(kernel, ResultSuccess); - } + for (auto it = m_pinned_waiter_list.begin(); it != m_pinned_waiter_list.end(); + it = m_pinned_waiter_list.erase(it)) { + it->EndWait(ResultSuccess); + } } - u16 KThread::GetUserDisableCount(KernelCore& kernel) const { + u16 KThread::GetUserDisableCount() const { if (!this->IsUserThread()) { // We only emulate TLS for user threads return {}; @@ -558,7 +569,7 @@ namespace Kernel { return memory.Read16(m_tls_address + offsetof(ThreadLocalRegion, disable_count)); } - void KThread::SetInterruptFlag(KernelCore& kernel) { + void KThread::SetInterruptFlag() { if (!this->IsUserThread()) { // We only emulate TLS for user threads return; @@ -568,7 +579,7 @@ namespace Kernel { memory.Write16(m_tls_address + offsetof(ThreadLocalRegion, interrupt_flag), 1); } - void KThread::ClearInterruptFlag(KernelCore& kernel) { + void KThread::ClearInterruptFlag() { if (!this->IsUserThread()) { // We only emulate TLS for user threads return; @@ -578,7 +589,7 @@ namespace Kernel { memory.Write16(m_tls_address + offsetof(ThreadLocalRegion, interrupt_flag), 0); } - void KThread::UpdateTlsThreadCpuTime(KernelCore& kernel, s64 switch_tick) { + void KThread::UpdateTlsThreadCpuTime(s64 switch_tick) { if (!this->IsUserThread()) { return; } @@ -591,8 +602,8 @@ namespace Kernel { memory.Write64(m_tls_address + offsetof(ThreadLocalRegion, thread_cpu_time), static_cast(value)); } - Result KThread::GetCoreMask(KernelCore& kernel, s32* out_ideal_core, u64* out_affinity_mask) { - KScopedSchedulerLock sl{kernel}; + Result KThread::GetCoreMask(s32* out_ideal_core, u64* out_affinity_mask) { + KScopedSchedulerLock sl{m_kernel}; // Get the virtual mask. *out_ideal_core = m_virtual_ideal_core_id; @@ -601,8 +612,8 @@ namespace Kernel { R_SUCCEED(); } - Result KThread::GetPhysicalCoreMask(KernelCore& kernel, s32* out_ideal_core, u64* out_affinity_mask) { - KScopedSchedulerLock sl{kernel}; + Result KThread::GetPhysicalCoreMask(s32* out_ideal_core, u64* out_affinity_mask) { + KScopedSchedulerLock sl{m_kernel}; ASSERT(m_num_core_migration_disables >= 0); // Select between core mask and original core mask. @@ -617,7 +628,7 @@ namespace Kernel { R_SUCCEED(); } - Result KThread::SetCoreMask(KernelCore& kernel, s32 core_id, u64 v_affinity_mask) { + Result KThread::SetCoreMask(s32 core_id, u64 v_affinity_mask) { ASSERT(m_parent != nullptr); ASSERT(v_affinity_mask != 0); KScopedLightLock lk(m_activity_pause_lock); @@ -625,7 +636,7 @@ namespace Kernel { // Set the core mask. u64 p_affinity_mask = 0; { - KScopedSchedulerLock sl(kernel); + KScopedSchedulerLock sl(m_kernel); ASSERT(m_num_core_migration_disables >= 0); // If we're updating, set our ideal virtual core. @@ -671,7 +682,7 @@ namespace Kernel { std::countl_zero(m_physical_affinity_mask.GetAffinityMask())); SetActiveCore(new_core); } - KScheduler::OnThreadAffinityMaskChanged(kernel, this, old_mask, active_core); + KScheduler::OnThreadAffinityMaskChanged(m_kernel, this, old_mask, active_core); } } else { // Otherwise, we edit the original affinity for restoration later. @@ -681,12 +692,12 @@ namespace Kernel { } // Update the pinned waiter list. - ThreadQueueImplForKThreadSetProperty wait_queue(kernel, std::addressof(m_pinned_waiter_list)); + ThreadQueueImplForKThreadSetProperty wait_queue(m_kernel, std::addressof(m_pinned_waiter_list)); { bool retry_update{}; do { // Lock the scheduler. - KScopedSchedulerLock sl(kernel); + KScopedSchedulerLock sl(m_kernel); // Don't do any further management if our termination has been requested. R_SUCCEED_IF(this->IsTerminationRequested()); @@ -699,7 +710,7 @@ namespace Kernel { s32 thread_core; for (thread_core = 0; thread_core < static_cast(Core::Hardware::NUM_CPU_CORES); ++thread_core) { - if (kernel.Scheduler(thread_core).GetSchedulerCurrentThread() == this) { + if (m_kernel.Scheduler(thread_core).GetSchedulerCurrentThread() == this) { thread_is_current = true; break; } @@ -711,12 +722,12 @@ namespace Kernel { // If the thread is pinned, we want to wait until it's not pinned. if (this->GetStackParameters().is_pinned) { // Verify that the current thread isn't terminating. - R_UNLESS(!GetCurrentThread(kernel).IsTerminationRequested(), + R_UNLESS(!GetCurrentThread(m_kernel).IsTerminationRequested(), ResultTerminationRequested); // Wait until the thread isn't pinned any more. - m_pinned_waiter_list.push_back(GetCurrentThread(kernel)); - GetCurrentThread(kernel).BeginWait(kernel, std::addressof(wait_queue)); + m_pinned_waiter_list.push_back(GetCurrentThread(m_kernel)); + GetCurrentThread(m_kernel).BeginWait(std::addressof(wait_queue)); } else { // If the thread isn't pinned, release the scheduler lock and retry until it's // not current. @@ -729,25 +740,25 @@ namespace Kernel { R_SUCCEED(); } - void KThread::SetBasePriority(KernelCore& kernel, s32 value) { + void KThread::SetBasePriority(s32 value) { ASSERT(Svc::HighestThreadPriority <= value && value <= Svc::LowestThreadPriority); - KScopedSchedulerLock sl{kernel}; + KScopedSchedulerLock sl{m_kernel}; // Change our base priority. m_base_priority = value; // Perform a priority restoration. - RestorePriority(kernel, this); + RestorePriority(m_kernel, this); } - KThread* KThread::GetLockOwner(KernelCore& kernel) const { + KThread* KThread::GetLockOwner() const { return m_waiting_lock_info != nullptr ? m_waiting_lock_info->GetOwner() : nullptr; } - void KThread::IncreaseBasePriority(KernelCore& kernel, s32 priority) { + void KThread::IncreaseBasePriority(s32 priority) { ASSERT(Svc::HighestThreadPriority <= priority && priority <= Svc::LowestThreadPriority); - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); ASSERT(!this->GetStackParameters().is_pinned); // Set our base priority. @@ -755,47 +766,47 @@ namespace Kernel { m_base_priority = priority; // Perform a priority restoration. - RestorePriority(kernel, this); + RestorePriority(m_kernel, this); } } - void KThread::RequestSuspend(KernelCore& kernel, SuspendType type) { - KScopedSchedulerLock sl{kernel}; + void KThread::RequestSuspend(SuspendType type) { + KScopedSchedulerLock sl{m_kernel}; // Note the request in our flags. m_suspend_request_flags |= (1U << (static_cast(ThreadState::SuspendShift) + static_cast(type))); // Try to perform the suspend. - this->TrySuspend(kernel); + this->TrySuspend(); } - void KThread::Resume(KernelCore& kernel, SuspendType type) { - KScopedSchedulerLock sl{kernel}; + void KThread::Resume(SuspendType type) { + KScopedSchedulerLock sl{m_kernel}; // Clear the request in our flags. m_suspend_request_flags &= ~(1U << (static_cast(ThreadState::SuspendShift) + static_cast(type))); // Update our state. - this->UpdateState(kernel); + this->UpdateState(); } - void KThread::WaitCancel(KernelCore& kernel) { - KScopedSchedulerLock sl{kernel}; + void KThread::WaitCancel() { + KScopedSchedulerLock sl{m_kernel}; // Check if we're waiting and cancellable. if (this->GetState() == ThreadState::Waiting && m_cancellable) { m_wait_cancelled = false; - m_wait_queue->CancelWait(kernel, this, ResultCancelled, true); + m_wait_queue->CancelWait(this, ResultCancelled, true); } else { // Otherwise, note that we cancelled a wait. m_wait_cancelled = true; } } - void KThread::TrySuspend(KernelCore& kernel) { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); + void KThread::TrySuspend() { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); ASSERT(this->IsSuspendRequested()); // Ensure that we have no waiters. @@ -805,11 +816,11 @@ namespace Kernel { ASSERT(this->GetNumKernelWaiters() == 0); // Perform the suspend. - this->UpdateState(kernel); + this->UpdateState(); } - void KThread::UpdateState(KernelCore& kernel) { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); + void KThread::UpdateState() { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); // Set our suspend flags in state. const ThreadState old_state = m_thread_state.load(std::memory_order_relaxed); @@ -819,37 +830,37 @@ namespace Kernel { // Note the state change in scheduler. if (new_state != old_state) { - KScheduler::OnThreadStateChanged(kernel, this, old_state); + KScheduler::OnThreadStateChanged(m_kernel, this, old_state); } } - void KThread::Continue(KernelCore& kernel) { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); + void KThread::Continue() { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); // Clear our suspend flags in state. const ThreadState old_state = m_thread_state.load(std::memory_order_relaxed); m_thread_state.store(old_state & ThreadState::Mask, std::memory_order_relaxed); // Note the state change in scheduler. - KScheduler::OnThreadStateChanged(kernel, this, old_state); + KScheduler::OnThreadStateChanged(m_kernel, this, old_state); } - void KThread::CloneFpuStatus(KernelCore& kernel) { + void KThread::CloneFpuStatus() { // We shouldn't reach here when starting kernel threads. ASSERT(this->GetOwnerProcess() != nullptr); - ASSERT(this->GetOwnerProcess() == GetCurrentProcessPointer(kernel)); + ASSERT(this->GetOwnerProcess() == GetCurrentProcessPointer(m_kernel)); - kernel.CurrentPhysicalCore().CloneFpuStatus(this); + m_kernel.CurrentPhysicalCore().CloneFpuStatus(this); } - Result KThread::SetActivity(KernelCore& kernel, Svc::ThreadActivity activity) { + Result KThread::SetActivity(Svc::ThreadActivity activity) { // Lock ourselves. KScopedLightLock lk(m_activity_pause_lock); // Set the activity. { // Lock the scheduler. - KScopedSchedulerLock sl(kernel); + KScopedSchedulerLock sl(m_kernel); // Verify our state. const auto cur_state = this->GetState(); @@ -862,7 +873,7 @@ namespace Kernel { R_UNLESS(!this->IsSuspendRequested(SuspendType::Thread), ResultInvalidState); // Suspend. - this->RequestSuspend(kernel, SuspendType::Thread); + this->RequestSuspend(SuspendType::Thread); } else { ASSERT(activity == Svc::ThreadActivity::Runnable); @@ -870,19 +881,19 @@ namespace Kernel { R_UNLESS(this->IsSuspendRequested(SuspendType::Thread), ResultInvalidState); // Resume. - this->Resume(kernel, SuspendType::Thread); + this->Resume(SuspendType::Thread); } } // If the thread is now paused, update the pinned waiter list. if (activity == Svc::ThreadActivity::Paused) { - ThreadQueueImplForKThreadSetProperty wait_queue(kernel, + ThreadQueueImplForKThreadSetProperty wait_queue(m_kernel, std::addressof(m_pinned_waiter_list)); bool thread_is_current{}; do { // Lock the scheduler. - KScopedSchedulerLock sl(kernel); + KScopedSchedulerLock sl(m_kernel); // Don't do any further management if our termination has been requested. R_SUCCEED_IF(this->IsTerminationRequested()); @@ -893,17 +904,17 @@ namespace Kernel { // Check whether the thread is pinned. if (this->GetStackParameters().is_pinned) { // Verify that the current thread isn't terminating. - R_UNLESS(!GetCurrentThread(kernel).IsTerminationRequested(), + R_UNLESS(!GetCurrentThread(m_kernel).IsTerminationRequested(), ResultTerminationRequested); // Wait until the thread isn't pinned any more. - m_pinned_waiter_list.push_back(GetCurrentThread(kernel)); - GetCurrentThread(kernel).BeginWait(kernel, std::addressof(wait_queue)); + m_pinned_waiter_list.push_back(GetCurrentThread(m_kernel)); + GetCurrentThread(m_kernel).BeginWait(std::addressof(wait_queue)); } else { // Check if the thread is currently running. // If it is, we'll need to retry. for (auto i = 0; i < static_cast(Core::Hardware::NUM_CPU_CORES); ++i) { - if (kernel.Scheduler(i).GetSchedulerCurrentThread() == this) { + if (m_kernel.Scheduler(i).GetSchedulerCurrentThread() == this) { thread_is_current = true; break; } @@ -915,14 +926,14 @@ namespace Kernel { R_SUCCEED(); } - Result KThread::GetThreadContext3(KernelCore& kernel, Svc::ThreadContext* out) { + Result KThread::GetThreadContext3(Svc::ThreadContext* out) { // Lock ourselves. KScopedLightLock lk{m_activity_pause_lock}; // Get the context. { // Lock the scheduler. - KScopedSchedulerLock sl{kernel}; + KScopedSchedulerLock sl{m_kernel}; // Verify that we're suspended. R_UNLESS(this->IsSuspendRequested(SuspendType::Thread), ResultInvalidState); @@ -946,8 +957,8 @@ namespace Kernel { R_SUCCEED(); } - void KThread::AddHeldLock(KernelCore& kernel, LockWithPriorityInheritanceInfo* lock_info) { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); + void KThread::AddHeldLock(LockWithPriorityInheritanceInfo* lock_info) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); // Set ourselves as the lock's owner. lock_info->SetOwner(this); @@ -956,21 +967,23 @@ namespace Kernel { m_held_lock_info_list.push_front(*lock_info); } - KThread::LockWithPriorityInheritanceInfo* KThread::FindHeldLock(KernelCore& kernel, KProcessAddress address_key, bool is_kernel_address_key) { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); + KThread::LockWithPriorityInheritanceInfo* KThread::FindHeldLock(KProcessAddress address_key, + bool is_kernel_address_key) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); // Try to find an existing held lock. for (auto& held_lock : m_held_lock_info_list) { - if (held_lock.GetAddressKey() == address_key && held_lock.GetIsKernelAddressKey() == is_kernel_address_key) { + if (held_lock.GetAddressKey() == address_key && + held_lock.GetIsKernelAddressKey() == is_kernel_address_key) { return std::addressof(held_lock); - } + } } return nullptr; } - void KThread::AddWaiterImpl(KernelCore& kernel, KThread* thread) { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); + void KThread::AddWaiterImpl(KThread* thread) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); ASSERT(thread->GetConditionVariableTree() == nullptr); // Get the thread's address key. @@ -980,31 +993,31 @@ namespace Kernel { // Keep track of how many kernel waiters we have. if (is_kernel_address_key) { ASSERT((m_num_kernel_waiters++) >= 0); - KScheduler::SetSchedulerUpdateNeeded(kernel); + KScheduler::SetSchedulerUpdateNeeded(m_kernel); } // Get the relevant lock info. - auto* lock_info = this->FindHeldLock(kernel, address_key, is_kernel_address_key); + auto* lock_info = this->FindHeldLock(address_key, is_kernel_address_key); if (lock_info == nullptr) { // Create a new lock for the address key. lock_info = - LockWithPriorityInheritanceInfo::Create(kernel, address_key, is_kernel_address_key); + LockWithPriorityInheritanceInfo::Create(m_kernel, address_key, is_kernel_address_key); // Add the new lock to our list. - this->AddHeldLock(kernel, lock_info); + this->AddHeldLock(lock_info); } // Add the thread as waiter to the lock info. lock_info->AddWaiter(thread); } - void KThread::RemoveWaiterImpl(KernelCore& kernel, KThread* thread) { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); + void KThread::RemoveWaiterImpl(KThread* thread) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); // Keep track of how many kernel waiters we have. if (thread->GetIsKernelAddressKey()) { ASSERT((m_num_kernel_waiters--) > 0); - KScheduler::SetSchedulerUpdateNeeded(kernel); + KScheduler::SetSchedulerUpdateNeeded(m_kernel); } // Get the info for the lock the thread is waiting on. @@ -1014,7 +1027,7 @@ namespace Kernel { // Remove the waiter. if (lock_info->RemoveWaiter(thread)) { m_held_lock_info_list.erase(m_held_lock_info_list.iterator_to(*lock_info)); - LockWithPriorityInheritanceInfo::Free(kernel, lock_info); + LockWithPriorityInheritanceInfo::Free(m_kernel, lock_info); } } @@ -1035,12 +1048,12 @@ namespace Kernel { } // Get the owner of whatever lock this thread is waiting on. - KThread* const lock_owner = thread->GetLockOwner(kernel); + KThread* const lock_owner = thread->GetLockOwner(); // If the thread is waiting on some lock, remove it as a waiter to prevent violating red // black tree invariants. if (lock_owner != nullptr) { - lock_owner->RemoveWaiterImpl(kernel, thread); + lock_owner->RemoveWaiterImpl(thread); } // Ensure we don't violate condition variable red black tree invariants. @@ -1059,7 +1072,7 @@ namespace Kernel { // If we removed the thread from some lock's waiting list, add it back. if (lock_owner != nullptr) { - lock_owner->AddWaiterImpl(kernel, thread); + lock_owner->AddWaiterImpl(thread); } // Update the scheduler. @@ -1070,30 +1083,32 @@ namespace Kernel { } } - void KThread::AddWaiter(KernelCore& kernel, KThread* thread) { - this->AddWaiterImpl(kernel, thread); + void KThread::AddWaiter(KThread* thread) { + this->AddWaiterImpl(thread); // If the thread has a higher priority than us, we should inherit. if (thread->GetPriority() < this->GetPriority()) { - RestorePriority(kernel, this); + RestorePriority(m_kernel, this); } } - void KThread::RemoveWaiter(KernelCore& kernel, KThread* thread) { - this->RemoveWaiterImpl(kernel, thread); + void KThread::RemoveWaiter(KThread* thread) { + this->RemoveWaiterImpl(thread); // If our priority is the same as the thread's (and we've inherited), we may need to restore to // lower priority. - if (this->GetPriority() == thread->GetPriority() && this->GetPriority() < this->GetBasePriority()) { - RestorePriority(kernel, this); - } + if (this->GetPriority() == thread->GetPriority() && + this->GetPriority() < this->GetBasePriority()) { + RestorePriority(m_kernel, this); + } } - KThread* KThread::RemoveWaiterByKey(KernelCore& kernel, bool* out_has_waiters, KProcessAddress key, bool is_kernel_address_key_) { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); + KThread* KThread::RemoveWaiterByKey(bool* out_has_waiters, KProcessAddress key, + bool is_kernel_address_key_) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); // Get the relevant lock info. - auto* lock_info = this->FindHeldLock(kernel, key, is_kernel_address_key_); + auto* lock_info = this->FindHeldLock(key, is_kernel_address_key_); if (lock_info == nullptr) { *out_has_waiters = false; return nullptr; @@ -1106,7 +1121,7 @@ namespace Kernel { if (lock_info->GetIsKernelAddressKey()) { m_num_kernel_waiters -= lock_info->GetWaiterCount(); ASSERT(m_num_kernel_waiters >= 0); - KScheduler::SetSchedulerUpdateNeeded(kernel); + KScheduler::SetSchedulerUpdateNeeded(m_kernel); } ASSERT(lock_info->GetWaiterCount() > 0); @@ -1118,13 +1133,13 @@ namespace Kernel { *out_has_waiters = false; // Free the lock info, since it has no waiters. - LockWithPriorityInheritanceInfo::Free(kernel, lock_info); + LockWithPriorityInheritanceInfo::Free(m_kernel, lock_info); } else { // There are additional waiters on the lock. *out_has_waiters = true; // Add the lock to the new owner's held list. - next_lock_owner->AddHeldLock(kernel, lock_info); + next_lock_owner->AddHeldLock(lock_info); // Keep track of any kernel waiters for the new owner. if (lock_info->GetIsKernelAddressKey()) { @@ -1140,7 +1155,7 @@ namespace Kernel { // to lower priority. if (this->GetPriority() == next_lock_owner->GetPriority() && this->GetPriority() < this->GetBasePriority()) { - RestorePriority(kernel, this); + RestorePriority(m_kernel, this); // NOTE: No need to restore priority on the next lock owner, because it was already the // highest priority waiter on the lock. } @@ -1149,91 +1164,91 @@ namespace Kernel { return next_lock_owner; } - Result KThread::Run(KernelCore& kernel) { + Result KThread::Run() { while (true) { - KScopedSchedulerLock lk{kernel}; + KScopedSchedulerLock lk{m_kernel}; // If either this thread or the current thread are requesting termination, note it. R_UNLESS(!this->IsTerminationRequested(), ResultTerminationRequested); - R_UNLESS(!GetCurrentThread(kernel).IsTerminationRequested(), ResultTerminationRequested); + R_UNLESS(!GetCurrentThread(m_kernel).IsTerminationRequested(), ResultTerminationRequested); // Ensure our thread state is correct. R_UNLESS(this->GetState() == ThreadState::Initialized, ResultInvalidState); // If the current thread has been asked to suspend, suspend it and retry. - if (GetCurrentThread(kernel).IsSuspended()) { - GetCurrentThread(kernel).UpdateState(kernel); + if (GetCurrentThread(m_kernel).IsSuspended()) { + GetCurrentThread(m_kernel).UpdateState(); continue; } // If we're not a kernel thread and we've been asked to suspend, suspend ourselves. if (KProcess* owner = this->GetOwnerProcess(); owner != nullptr) { if (this->IsUserThread() && this->IsSuspended()) { - this->UpdateState(kernel); + this->UpdateState(); } - owner->IncrementRunningThreadCount(kernel); + owner->IncrementRunningThreadCount(); } // Open a reference, now that we're running. - this->Open(kernel); + this->Open(); // Set our state and finish. - this->SetState(kernel, ThreadState::Runnable); + this->SetState(ThreadState::Runnable); R_SUCCEED(); } } - void KThread::Exit(KernelCore& kernel) { - ASSERT(this == GetCurrentThreadPointer(kernel)); + void KThread::Exit() { + ASSERT(this == GetCurrentThreadPointer(m_kernel)); // Release the thread resource hint, running thread count from parent. if (m_parent != nullptr) { - m_parent->GetResourceLimit()->Release(kernel, Kernel::LimitableResource::ThreadCountMax, 0, 1); + m_parent->GetResourceLimit()->Release(Kernel::LimitableResource::ThreadCountMax, 0, 1); m_resource_limit_release_hint = true; - m_parent->DecrementRunningThreadCount(kernel); + m_parent->DecrementRunningThreadCount(); } // Perform termination. { - KScopedSchedulerLock sl{kernel}; + KScopedSchedulerLock sl{m_kernel}; // Disallow all suspension. m_suspend_allowed_flags = 0; - this->UpdateState(kernel); + this->UpdateState(); // Disallow all suspension. m_suspend_allowed_flags = 0; // Start termination. - this->StartTermination(kernel); + this->StartTermination(); // Register the thread as a work task. - KWorkerTaskManager::AddTask(kernel, KWorkerTaskManager::WorkerType::Exit, this); + KWorkerTaskManager::AddTask(m_kernel, KWorkerTaskManager::WorkerType::Exit, this); } UNREACHABLE_MSG("KThread::Exit() would return"); } - Result KThread::Terminate(KernelCore& kernel) { - ASSERT(this != GetCurrentThreadPointer(kernel)); + Result KThread::Terminate() { + ASSERT(this != GetCurrentThreadPointer(m_kernel)); // Request the thread terminate if it hasn't already. - if (const auto new_state = this->RequestTerminate(kernel); new_state != ThreadState::Terminated) { + if (const auto new_state = this->RequestTerminate(); new_state != ThreadState::Terminated) { // If the thread isn't terminated, wait for it to terminate. s32 index; KSynchronizationObject* objects[] = {this}; - R_TRY(KSynchronizationObject::Wait(kernel, std::addressof(index), objects, 1, + R_TRY(KSynchronizationObject::Wait(m_kernel, std::addressof(index), objects, 1, Svc::WaitInfinite)); } R_SUCCEED(); } - ThreadState KThread::RequestTerminate(KernelCore& kernel) { - ASSERT(this != GetCurrentThreadPointer(kernel)); + ThreadState KThread::RequestTerminate() { + ASSERT(this != GetCurrentThreadPointer(m_kernel)); - KScopedSchedulerLock sl{kernel}; + KScopedSchedulerLock sl{m_kernel}; // Determine if this is the first termination request. const bool first_request = [&]() -> bool { @@ -1255,46 +1270,46 @@ namespace Kernel { // If the thread is pinned, unpin it. if (this->GetStackParameters().is_pinned) { - this->GetOwnerProcess()->UnpinThread(kernel, this); + this->GetOwnerProcess()->UnpinThread(this); } // If the thread is suspended, continue it. if (this->IsSuspended()) { m_suspend_allowed_flags = 0; - this->UpdateState(kernel); + this->UpdateState(); } // Change the thread's priority to be higher than any system thread's. - this->IncreaseBasePriority(kernel, TerminatingThreadPriority); + this->IncreaseBasePriority(TerminatingThreadPriority); // If the thread is runnable, send a termination interrupt to cores it may be running on. if (this->GetState() == ThreadState::Runnable) { // NOTE: We do not mask the "current core", because this code may not actually be // executing from the thread representing the "current core". if (const u64 core_mask = m_physical_affinity_mask.GetAffinityMask(); core_mask != 0) { - Kernel::KInterruptManager::SendInterProcessorInterrupt(kernel, core_mask); + Kernel::KInterruptManager::SendInterProcessorInterrupt(m_kernel, core_mask); } } // Wake up the thread. if (this->GetState() == ThreadState::Waiting) { - m_wait_queue->CancelWait(kernel, this, ResultTerminationRequested, true); + m_wait_queue->CancelWait(this, ResultTerminationRequested, true); } } return this->GetState(); } - Result KThread::Sleep(KernelCore& kernel, s64 timeout) { - ASSERT(!KScheduler::IsSchedulerLockedByCurrentThread(kernel)); - ASSERT(this == GetCurrentThreadPointer(kernel)); + Result KThread::Sleep(s64 timeout) { + ASSERT(!KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + ASSERT(this == GetCurrentThreadPointer(m_kernel)); ASSERT(timeout > 0); - ThreadQueueImplForKThreadSleep wait_queue(kernel); + ThreadQueueImplForKThreadSleep wait_queue(m_kernel); KHardwareTimer* timer{}; { // Setup the scheduling lock and sleep. - KScopedSchedulerLockAndSleep slp(kernel, std::addressof(timer), this, timeout); + KScopedSchedulerLockAndSleep slp(m_kernel, std::addressof(timer), this, timeout); // Check if the thread should terminate. if (this->IsTerminationRequested()) { @@ -1304,15 +1319,15 @@ namespace Kernel { // Wait for the sleep to end. wait_queue.SetHardwareTimer(timer); - this->BeginWait(kernel, std::addressof(wait_queue)); + this->BeginWait(std::addressof(wait_queue)); this->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Sleep); } R_SUCCEED(); } - void KThread::RequestDummyThreadWait(KernelCore& kernel) { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); + void KThread::RequestDummyThreadWait() { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); ASSERT(this->IsDummyThread()); // We will block when the scheduler lock is released. @@ -1320,8 +1335,8 @@ namespace Kernel { m_dummy_thread_runnable = false; } - void KThread::DummyThreadBeginWait(KernelCore& kernel) { - if (!this->IsDummyThread() || kernel.IsPhantomModeForSingleCore()) { + void KThread::DummyThreadBeginWait() { + if (!this->IsDummyThread() || m_kernel.IsPhantomModeForSingleCore()) { // Occurs in single core mode. return; } @@ -1331,8 +1346,8 @@ namespace Kernel { m_dummy_thread_cv.wait(lock, [this] { return m_dummy_thread_runnable; }); } - void KThread::DummyThreadEndWait(KernelCore& kernel) { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); + void KThread::DummyThreadEndWait() { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); ASSERT(this->IsDummyThread()); // Wake up the waiting thread. @@ -1343,26 +1358,28 @@ namespace Kernel { m_dummy_thread_cv.notify_one(); } - void KThread::BeginWait(KernelCore& kernel, KThreadQueue* queue) { + void KThread::BeginWait(KThreadQueue* queue) { // Set our state as waiting. - this->SetState(kernel, ThreadState::Waiting); + this->SetState(ThreadState::Waiting); // Set our wait queue. m_wait_queue = queue; } - void KThread::NotifyAvailable(KernelCore& kernel, KSynchronizationObject* signaled_object, Result wait_result) { + void KThread::NotifyAvailable(KSynchronizationObject* signaled_object, Result wait_result) { // Lock the scheduler. - KScopedSchedulerLock sl(kernel); + KScopedSchedulerLock sl(m_kernel); + // If we're waiting, notify our queue that we're available. if (this->GetState() == ThreadState::Waiting) { - m_wait_queue->NotifyAvailable(kernel, this, signaled_object, wait_result); + m_wait_queue->NotifyAvailable(this, signaled_object, wait_result); } } - void KThread::EndWait(KernelCore& kernel, Result wait_result) { + void KThread::EndWait(Result wait_result) { // Lock the scheduler. - KScopedSchedulerLock sl(kernel); + KScopedSchedulerLock sl(m_kernel); + // If we're waiting, notify our queue that we're available. if (this->GetState() == ThreadState::Waiting) { if (m_wait_queue == nullptr) { @@ -1371,29 +1388,32 @@ namespace Kernel { return; } - m_wait_queue->EndWait(kernel, this, wait_result); + m_wait_queue->EndWait(this, wait_result); } } - void KThread::CancelWait(KernelCore& kernel, Result wait_result, bool cancel_timer_task) { + void KThread::CancelWait(Result wait_result, bool cancel_timer_task) { // Lock the scheduler. - KScopedSchedulerLock sl(kernel); + KScopedSchedulerLock sl(m_kernel); + // If we're waiting, notify our queue that we're available. if (this->GetState() == ThreadState::Waiting) { - m_wait_queue->CancelWait(kernel, this, wait_result, cancel_timer_task); + m_wait_queue->CancelWait(this, wait_result, cancel_timer_task); } } - void KThread::SetState(KernelCore& kernel, ThreadState state) { - KScopedSchedulerLock sl{kernel}; + void KThread::SetState(ThreadState state) { + KScopedSchedulerLock sl{m_kernel}; + // Clear debugging state this->SetWaitReasonForDebugging({}); + const ThreadState old_state = m_thread_state.load(std::memory_order_relaxed); m_thread_state.store( static_cast((old_state & ~ThreadState::Mask) | (state & ThreadState::Mask)), std::memory_order_relaxed); if (m_thread_state.load(std::memory_order_relaxed) != old_state) { - KScheduler::OnThreadStateChanged(kernel, this, old_state); + KScheduler::OnThreadStateChanged(m_kernel, this, old_state); } } @@ -1439,12 +1459,12 @@ namespace Kernel { auto* scheduler = m_kernel.CurrentScheduler(); if (scheduler && !m_kernel.IsPhantomModeForSingleCore()) { - scheduler->RescheduleCurrentCore(m_kernel); + scheduler->RescheduleCurrentCore(); } else { KScheduler::RescheduleCurrentHLEThread(m_kernel); } } else { - GetCurrentThread(m_kernel).EnableDispatch(m_kernel); + GetCurrentThread(m_kernel).EnableDispatch(); } } } \ No newline at end of file diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index 95ba1b4d76..e79704ce4b 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project @@ -181,17 +181,21 @@ public: return m_thread_id; } - void ContinueIfHasKernelWaiters(KernelCore& kernel) { + void ContinueIfHasKernelWaiters() { if (GetNumKernelWaiters() > 0) { - Continue(kernel); + Continue(); } } - void SetBasePriority(KernelCore& kernel, s32 value); - Result Run(KernelCore& kernel); - void Exit(KernelCore& kernel); - Result Terminate(KernelCore& kernel); - ThreadState RequestTerminate(KernelCore& kernel); + void SetBasePriority(s32 value); + + Result Run(); + + void Exit(); + + Result Terminate(); + + ThreadState RequestTerminate(); u32 GetSuspendFlags() const { return m_suspend_allowed_flags & m_suspend_request_flags; @@ -211,11 +215,15 @@ public: return m_suspend_request_flags != 0; } - void RequestSuspend(KernelCore& kernel, SuspendType type); - void Resume(KernelCore& kernel, SuspendType type); - void TrySuspend(KernelCore& kernel); - void UpdateState(KernelCore& kernel); - void Continue(KernelCore& kernel); + void RequestSuspend(SuspendType type); + + void Resume(SuspendType type); + + void TrySuspend(); + + void UpdateState(); + + void Continue(); constexpr void SetSyncedIndex(s32 index) { m_synced_index = index; @@ -254,7 +262,7 @@ public: m_thread_context.tpidr = value; } - void CloneFpuStatus(KernelCore& kernel); + void CloneFpuStatus(); Svc::ThreadContext& GetContext() { return m_thread_context; @@ -274,7 +282,7 @@ public: return m_thread_state.load(std::memory_order_relaxed); } - void SetState(KernelCore& kernel, ThreadState state); + void SetState(ThreadState state); StepState GetStepState() const { return m_step_state; @@ -334,27 +342,27 @@ public: Svc::ArgumentHandleCountMax}; } - u16 GetUserDisableCount(KernelCore& kernel) const; - void SetInterruptFlag(KernelCore& kernel); - void ClearInterruptFlag(KernelCore& kernel); + u16 GetUserDisableCount() const; + void SetInterruptFlag(); + void ClearInterruptFlag(); - void UpdateTlsThreadCpuTime(KernelCore& kernel, s64 switch_tick); + void UpdateTlsThreadCpuTime(s64 switch_tick); - KThread* GetLockOwner(KernelCore& kernel) const; + KThread* GetLockOwner() const; const KAffinityMask& GetAffinityMask() const { return m_physical_affinity_mask; } - Result GetCoreMask(KernelCore& kernel, s32* out_ideal_core, u64* out_affinity_mask); + Result GetCoreMask(s32* out_ideal_core, u64* out_affinity_mask); - Result GetPhysicalCoreMask(KernelCore& kernel, s32* out_ideal_core, u64* out_affinity_mask); + Result GetPhysicalCoreMask(s32* out_ideal_core, u64* out_affinity_mask); - Result SetCoreMask(KernelCore& kernel, s32 cpu_core_id, u64 v_affinity_mask); + Result SetCoreMask(s32 cpu_core_id, u64 v_affinity_mask); - Result SetActivity(KernelCore& kernel, Svc::ThreadActivity activity); + Result SetActivity(Svc::ThreadActivity activity); - Result Sleep(KernelCore& kernel, s64 timeout); + Result Sleep(s64 timeout); s64 GetYieldScheduleCount() const { return m_schedule_count; @@ -364,7 +372,7 @@ public: m_schedule_count = count; } - void WaitCancel(KernelCore& kernel); + void WaitCancel(); bool IsWaitCancelled() const { return m_wait_cancelled; @@ -409,17 +417,17 @@ public: return reinterpret_cast(m_parent) | (m_resource_limit_release_hint ? 1 : 0); } - void Finalize(KernelCore& kernel) override; + void Finalize() override; - bool IsSignaled(KernelCore& kernel) const override; + bool IsSignaled() const override; - void OnTimer(KernelCore& kernel); + void OnTimer(); - void DoWorkerTaskImpl(KernelCore& kernel); + void DoWorkerTaskImpl(); - static void PostDestroy(KernelCore& kernel, uintptr_t arg); + static void PostDestroy(uintptr_t arg); - static Result InitializeDummyThread(Core::System& system, KThread* thread, KProcess* owner); + static Result InitializeDummyThread(KThread* thread, KProcess* owner); static Result InitializeMainThread(Core::System& system, KThread* thread, s32 virt_core); @@ -506,18 +514,19 @@ public: return this->GetStackParameters().disable_count; } - void DisableDispatch(KernelCore& kernel) { - ASSERT(GetCurrentThread(kernel).GetDisableDispatchCount() >= 0); + void DisableDispatch() { + ASSERT(GetCurrentThread(m_kernel).GetDisableDispatchCount() >= 0); this->GetStackParameters().disable_count++; } - void EnableDispatch(KernelCore& kernel) { - ASSERT(GetCurrentThread(kernel).GetDisableDispatchCount() > 0); + void EnableDispatch() { + ASSERT(GetCurrentThread(m_kernel).GetDisableDispatchCount() > 0); this->GetStackParameters().disable_count--; } - void Pin(KernelCore& kernel, s32 current_core); - void Unpin(KernelCore& kernel); + void Pin(s32 current_core); + + void Unpin(); void SetInExceptionHandler() { this->GetStackParameters().is_in_exception_handler = true; @@ -583,18 +592,18 @@ public: return this->GetThreadType() == ThreadType::Dummy; } - void AddWaiter(KernelCore& kernel, KThread* thread); + void AddWaiter(KThread* thread); - void RemoveWaiter(KernelCore& kernel, KThread* thread); + void RemoveWaiter(KThread* thread); - Result GetThreadContext3(KernelCore& kernel, Svc::ThreadContext* out); + Result GetThreadContext3(Svc::ThreadContext* out); - KThread* RemoveUserWaiterByKey(KernelCore& kernel, bool* out_has_waiters, KProcessAddress key) { - return this->RemoveWaiterByKey(kernel, out_has_waiters, key, false); + KThread* RemoveUserWaiterByKey(bool* out_has_waiters, KProcessAddress key) { + return this->RemoveWaiterByKey(out_has_waiters, key, false); } - KThread* RemoveKernelWaiterByKey(KernelCore& kernel, bool* out_has_waiters, KProcessAddress key) { - return this->RemoveWaiterByKey(kernel, out_has_waiters, key, true); + KThread* RemoveKernelWaiterByKey(bool* out_has_waiters, KProcessAddress key) { + return this->RemoveWaiterByKey(out_has_waiters, key, true); } KProcessAddress GetAddressKey() const { @@ -632,10 +641,10 @@ public: m_wait_queue = nullptr; } - void BeginWait(KernelCore& kernel, KThreadQueue* queue); - void NotifyAvailable(KernelCore& kernel, KSynchronizationObject* signaled_object, Result wait_result); - void EndWait(KernelCore& kernel, Result wait_result); - void CancelWait(KernelCore& kernel, Result wait_result, bool cancel_timer_task); + void BeginWait(KThreadQueue* queue); + void NotifyAvailable(KSynchronizationObject* signaled_object, Result wait_result); + void EndWait(Result wait_result); + void CancelWait(Result wait_result, bool cancel_timer_task); s32 GetNumKernelWaiters() const { return m_num_kernel_waiters; @@ -653,9 +662,9 @@ public: // therefore will not block on guest kernel synchronization primitives. These methods handle // blocking as needed. - void RequestDummyThreadWait(KernelCore& kernel); - void DummyThreadBeginWait(KernelCore& kernel); - void DummyThreadEndWait(KernelCore& kernel); + void RequestDummyThreadWait(); + void DummyThreadBeginWait(); + void DummyThreadEndWait(); uintptr_t GetArgument() const { return m_argument; @@ -681,7 +690,8 @@ public: } private: - KThread* RemoveWaiterByKey(KernelCore& kernel, bool* out_has_waiters, KProcessAddress key, bool is_kernel_address_key); + KThread* RemoveWaiterByKey(bool* out_has_waiters, KProcessAddress key, + bool is_kernel_address_key); static constexpr size_t PriorityInheritanceCountMax = 10; union SyncObjectBuffer { @@ -725,19 +735,19 @@ private: } }; - void AddWaiterImpl(KernelCore& kernel, KThread* thread); - void RemoveWaiterImpl(KernelCore& kernel, KThread* thread); + void AddWaiterImpl(KThread* thread); + void RemoveWaiterImpl(KThread* thread); static void RestorePriority(KernelCore& kernel, KThread* thread); - void StartTermination(KernelCore& kernel); - void FinishTermination(KernelCore& kernel); + void StartTermination(); + void FinishTermination(); - void IncreaseBasePriority(KernelCore& kernel, s32 priority); + void IncreaseBasePriority(s32 priority); - Result Initialize(KernelCore& kernel, KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, s32 prio, + Result Initialize(KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, s32 prio, s32 virt_core, KProcess* owner, ThreadType type); - static Result InitializeThread(KernelCore& kernel, KThread* thread, KThreadFunction func, uintptr_t arg, + static Result InitializeThread(KThread* thread, KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, s32 prio, s32 core, KProcess* owner, ThreadType type, std::function&& init_func); @@ -868,8 +878,9 @@ public: return m_waiting_lock_info; } - void AddHeldLock(KernelCore& kernel, LockWithPriorityInheritanceInfo* lock_info); - LockWithPriorityInheritanceInfo* FindHeldLock(KernelCore& kernel, KProcessAddress address_key, bool is_kernel_address_key); + void AddHeldLock(LockWithPriorityInheritanceInfo* lock_info); + LockWithPriorityInheritanceInfo* FindHeldLock(KProcessAddress address_key, + bool is_kernel_address_key); private: using LockWithPriorityInheritanceInfoList = @@ -985,7 +996,7 @@ public: if (m_kernel.IsShuttingDown()) { return; } - GetCurrentThread(kernel).DisableDispatch(kernel); + GetCurrentThread(kernel).DisableDispatch(); } ~KScopedDisableDispatch(); @@ -994,8 +1005,8 @@ private: KernelCore& m_kernel; }; -inline void KTimerTask::OnTimer(KernelCore& kernel) { - static_cast(this)->OnTimer(kernel); +inline void KTimerTask::OnTimer() { + static_cast(this)->OnTimer(); } } // namespace Kernel diff --git a/src/core/hle/kernel/k_thread_queue.cpp b/src/core/hle/kernel/k_thread_queue.cpp index 7c4bfe5a49..61488f4ce6 100644 --- a/src/core/hle/kernel/k_thread_queue.cpp +++ b/src/core/hle/kernel/k_thread_queue.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -10,16 +7,17 @@ namespace Kernel { -void KThreadQueue::NotifyAvailable(KernelCore& kernel, KThread* waiting_thread, KSynchronizationObject* signaled_object, Result wait_result) { +void KThreadQueue::NotifyAvailable(KThread* waiting_thread, KSynchronizationObject* signaled_object, + Result wait_result) { UNREACHABLE(); } -void KThreadQueue::EndWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result) { +void KThreadQueue::EndWait(KThread* waiting_thread, Result wait_result) { // Set the thread's wait result. waiting_thread->SetWaitResult(wait_result); // Set the thread as runnable. - waiting_thread->SetState(kernel, ThreadState::Runnable); + waiting_thread->SetState(ThreadState::Runnable); // Clear the thread's wait queue. waiting_thread->ClearWaitQueue(); @@ -30,12 +28,12 @@ void KThreadQueue::EndWait(KernelCore& kernel, KThread* waiting_thread, Result w } } -void KThreadQueue::CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task) { +void KThreadQueue::CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) { // Set the thread's wait result. waiting_thread->SetWaitResult(wait_result); // Set the thread as runnable. - waiting_thread->SetState(kernel, ThreadState::Runnable); + waiting_thread->SetState(ThreadState::Runnable); // Clear the thread's wait queue. waiting_thread->ClearWaitQueue(); @@ -46,7 +44,7 @@ void KThreadQueue::CancelWait(KernelCore& kernel, KThread* waiting_thread, Resul } } -void KThreadQueueWithoutEndWait::EndWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result) { +void KThreadQueueWithoutEndWait::EndWait(KThread* waiting_thread, Result wait_result) { UNREACHABLE(); } diff --git a/src/core/hle/kernel/k_thread_queue.h b/src/core/hle/kernel/k_thread_queue.h index 953bb78ac6..117af0919a 100644 --- a/src/core/hle/kernel/k_thread_queue.h +++ b/src/core/hle/kernel/k_thread_queue.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -15,25 +12,28 @@ class KHardwareTimer; class KThreadQueue { public: - explicit KThreadQueue(KernelCore& kernel) : m_hardware_timer{} {} + explicit KThreadQueue(KernelCore& kernel) : m_kernel{kernel}, m_hardware_timer{} {} virtual ~KThreadQueue() = default; void SetHardwareTimer(KHardwareTimer* timer) { m_hardware_timer = timer; } - virtual void NotifyAvailable(KernelCore& kernel, KThread* waiting_thread, KSynchronizationObject* signaled_object, Result wait_result); - virtual void EndWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result); - virtual void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task); + virtual void NotifyAvailable(KThread* waiting_thread, KSynchronizationObject* signaled_object, + Result wait_result); + virtual void EndWait(KThread* waiting_thread, Result wait_result); + virtual void CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task); private: + KernelCore& m_kernel; KHardwareTimer* m_hardware_timer{}; }; class KThreadQueueWithoutEndWait : public KThreadQueue { public: explicit KThreadQueueWithoutEndWait(KernelCore& kernel) : KThreadQueue(kernel) {} - void EndWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result) override final; + + void EndWait(KThread* waiting_thread, Result wait_result) override final; }; } // namespace Kernel diff --git a/src/core/hle/kernel/k_timer_task.h b/src/core/hle/kernel/k_timer_task.h index 7625c1fee1..66f0a5a908 100644 --- a/src/core/hle/kernel/k_timer_task.h +++ b/src/core/hle/kernel/k_timer_task.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -10,7 +7,6 @@ namespace Kernel { -class KernelCore; class KTimerTask : public Common::IntrusiveRedBlackTreeBaseNode { public: static constexpr int Compare(const KTimerTask& lhs, const KTimerTask& rhs) { @@ -34,7 +30,7 @@ public: // NOTE: This is virtual in Nintendo's kernel. Prior to 13.0.0, KWaitObject was also a // TimerTask; this is no longer the case. Since this is now KThread exclusive, we have // devirtualized (see inline declaration for this inside k_thread.h). - void OnTimer(KernelCore& kernel); + void OnTimer(); private: // Absolute time in nanoseconds diff --git a/src/core/hle/kernel/k_trace.h b/src/core/hle/kernel/k_trace.h index 84dd4134e1..d61af48303 100644 --- a/src/core/hle/kernel/k_trace.h +++ b/src/core/hle/kernel/k_trace.h @@ -1,13 +1,8 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once -#include "common/literals.h" - namespace Kernel { using namespace Common::Literals; diff --git a/src/core/hle/kernel/k_transfer_memory.cpp b/src/core/hle/kernel/k_transfer_memory.cpp index a4ef530b5b..09295e8ad8 100644 --- a/src/core/hle/kernel/k_transfer_memory.cpp +++ b/src/core/hle/kernel/k_transfer_memory.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -17,15 +14,16 @@ KTransferMemory::KTransferMemory(KernelCore& kernel) KTransferMemory::~KTransferMemory() = default; -Result KTransferMemory::Initialize(KernelCore& kernel, KProcessAddress addr, std::size_t size, Svc::MemoryPermission own_perm) { +Result KTransferMemory::Initialize(KProcessAddress addr, std::size_t size, + Svc::MemoryPermission own_perm) { // Set members. - m_owner = GetCurrentProcessPointer(kernel); + m_owner = GetCurrentProcessPointer(m_kernel); // Get the owner page table. auto& page_table = m_owner->GetPageTable(); // Construct the page group, guarding to make sure our state is valid on exit. - m_page_group.emplace(kernel, page_table.GetBlockInfoManager()); + m_page_group.emplace(m_kernel, page_table.GetBlockInfoManager()); auto pg_guard = SCOPE_GUARD { m_page_group.reset(); }; @@ -35,7 +33,7 @@ Result KTransferMemory::Initialize(KernelCore& kernel, KProcessAddress addr, std ConvertToKMemoryPermission(own_perm))); // Set remaining tracking members. - m_owner->Open(kernel); + m_owner->Open(); m_owner_perm = own_perm; m_address = addr; m_is_initialized = true; @@ -46,7 +44,7 @@ Result KTransferMemory::Initialize(KernelCore& kernel, KProcessAddress addr, std R_SUCCEED(); } -void KTransferMemory::Finalize(KernelCore& kernel) { +void KTransferMemory::Finalize() { // Unlock. if (!m_is_mapped) { const size_t size = m_page_group->GetNumPages() * PageSize; @@ -55,17 +53,17 @@ void KTransferMemory::Finalize(KernelCore& kernel) { } // Close the page group. - m_page_group->Close(kernel); + m_page_group->Close(); m_page_group->Finalize(); } -void KTransferMemory::PostDestroy(KernelCore& kernel, uintptr_t arg) { +void KTransferMemory::PostDestroy(uintptr_t arg) { KProcess* owner = reinterpret_cast(arg); - owner->GetResourceLimit()->Release(kernel, LimitableResource::TransferMemoryCountMax, 1); - owner->Close(kernel); + owner->GetResourceLimit()->Release(LimitableResource::TransferMemoryCountMax, 1); + owner->Close(); } -Result KTransferMemory::Map(KernelCore& kernel, KProcessAddress address, size_t size, Svc::MemoryPermission map_perm) { +Result KTransferMemory::Map(KProcessAddress address, size_t size, Svc::MemoryPermission map_perm) { // Validate the size. R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); @@ -82,7 +80,7 @@ Result KTransferMemory::Map(KernelCore& kernel, KProcessAddress address, size_t const KMemoryState state = (m_owner_perm == Svc::MemoryPermission::None) ? KMemoryState::Transferred : KMemoryState::SharedTransferred; - R_TRY(GetCurrentProcess(kernel).GetPageTable().MapPageGroup( + R_TRY(GetCurrentProcess(m_kernel).GetPageTable().MapPageGroup( address, *m_page_group, state, KMemoryPermission::UserReadWrite)); // Mark ourselves as mapped. @@ -91,7 +89,7 @@ Result KTransferMemory::Map(KernelCore& kernel, KProcessAddress address, size_t R_SUCCEED(); } -Result KTransferMemory::Unmap(KernelCore& kernel, KProcessAddress address, size_t size) { +Result KTransferMemory::Unmap(KProcessAddress address, size_t size) { // Validate the size. R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); @@ -102,7 +100,7 @@ Result KTransferMemory::Unmap(KernelCore& kernel, KProcessAddress address, size_ const KMemoryState state = (m_owner_perm == Svc::MemoryPermission::None) ? KMemoryState::Transferred : KMemoryState::SharedTransferred; - R_TRY(GetCurrentProcess(kernel).GetPageTable().UnmapPageGroup(address, *m_page_group, state)); + R_TRY(GetCurrentProcess(m_kernel).GetPageTable().UnmapPageGroup(address, *m_page_group, state)); // Mark ourselves as unmapped. ASSERT(m_is_mapped); diff --git a/src/core/hle/kernel/k_transfer_memory.h b/src/core/hle/kernel/k_transfer_memory.h index 0753b4fd6d..530b452182 100644 --- a/src/core/hle/kernel/k_transfer_memory.h +++ b/src/core/hle/kernel/k_transfer_memory.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -33,9 +30,9 @@ public: explicit KTransferMemory(KernelCore& kernel); ~KTransferMemory() override; - Result Initialize(KernelCore& kernel, KProcessAddress address, std::size_t size, Svc::MemoryPermission owner_perm); + Result Initialize(KProcessAddress address, std::size_t size, Svc::MemoryPermission owner_perm); - void Finalize(KernelCore& kernel) override; + void Finalize() override; bool IsInitialized() const override { return m_is_initialized; @@ -45,7 +42,7 @@ public: return reinterpret_cast(m_owner); } - static void PostDestroy(KernelCore& kernel, uintptr_t arg); + static void PostDestroy(uintptr_t arg); KProcess* GetOwner() const override { return m_owner; @@ -57,8 +54,8 @@ public: size_t GetSize() const; - Result Map(KernelCore& kernel, KProcessAddress address, size_t size, Svc::MemoryPermission map_perm); - Result Unmap(KernelCore& kernel, KProcessAddress address, size_t size); + Result Map(KProcessAddress address, size_t size, Svc::MemoryPermission map_perm); + Result Unmap(KProcessAddress address, size_t size); private: std::optional m_page_group{}; diff --git a/src/core/hle/kernel/k_worker_task.h b/src/core/hle/kernel/k_worker_task.h index a4820bc412..9a230c03c4 100644 --- a/src/core/hle/kernel/k_worker_task.h +++ b/src/core/hle/kernel/k_worker_task.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -13,7 +10,8 @@ namespace Kernel { class KWorkerTask : public KSynchronizationObject { public: explicit KWorkerTask(KernelCore& kernel); - void DoWorkerTask(KernelCore& kernel); + + void DoWorkerTask(); }; } // namespace Kernel diff --git a/src/core/hle/kernel/k_worker_task_manager.cpp b/src/core/hle/kernel/k_worker_task_manager.cpp index 4427f9859a..8ead395911 100644 --- a/src/core/hle/kernel/k_worker_task_manager.cpp +++ b/src/core/hle/kernel/k_worker_task_manager.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -15,14 +12,14 @@ namespace Kernel { KWorkerTask::KWorkerTask(KernelCore& kernel) : KSynchronizationObject{kernel} {} -void KWorkerTask::DoWorkerTask(KernelCore& kernel) { +void KWorkerTask::DoWorkerTask() { if (auto* const thread = this->DynamicCast(); thread != nullptr) { - return thread->DoWorkerTaskImpl(kernel); + return thread->DoWorkerTaskImpl(); } else { auto* const process = this->DynamicCast(); ASSERT(process != nullptr); - return process->DoWorkerTaskImpl(kernel); + return process->DoWorkerTaskImpl(); } } @@ -35,9 +32,9 @@ void KWorkerTaskManager::AddTask(KernelCore& kernel, WorkerType type, KWorkerTas void KWorkerTaskManager::AddTask(KernelCore& kernel, KWorkerTask* task) { KScopedSchedulerLock sl(kernel); - m_waiting_thread.QueueWork([&kernel, task]() { + m_waiting_thread.QueueWork([task]() { // Do the task. - task->DoWorkerTask(kernel); + task->DoWorkerTask(); }); } diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index d25ac37df4..5f88fa498f 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -121,14 +121,14 @@ struct KernelCore::Impl { void TerminateAllProcesses() { std::scoped_lock lk{process_list_lock}; for (auto& process : process_list) { - process->Terminate(system.Kernel()); - process->Close(system.Kernel()); + process->Terminate(); + process->Close(); process = nullptr; } process_list.clear(); } - void Shutdown(KernelCore& kernel) { + void Shutdown() { is_shutting_down.store(true, std::memory_order_relaxed); SCOPE_EXIT { is_shutting_down.store(false, std::memory_order_relaxed); @@ -137,7 +137,7 @@ struct KernelCore::Impl { CloseServices(); if (application_process) { - application_process->Close(system.Kernel()); + application_process->Close(); application_process = nullptr; } @@ -149,9 +149,9 @@ struct KernelCore::Impl { preemption_event = nullptr; // Cleanup persistent kernel objects - auto CleanupObject = [&kernel](KAutoObject* obj) { + auto CleanupObject = [](KAutoObject* obj) { if (obj) { - obj->Close(kernel); + obj->Close(); obj = nullptr; } }; @@ -163,7 +163,7 @@ struct KernelCore::Impl { for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) { if (shutdown_threads[core_id]) { - shutdown_threads[core_id]->Close(kernel); + shutdown_threads[core_id]->Close(); shutdown_threads[core_id] = nullptr; } @@ -178,7 +178,7 @@ struct KernelCore::Impl { std::scoped_lock lk{registered_in_use_objects_lock}; if (registered_in_use_objects.size()) { for (auto& object : registered_in_use_objects) { - object->Close(kernel); + object->Close(); } registered_in_use_objects.clear(); } @@ -226,7 +226,7 @@ struct KernelCore::Impl { ASSERT(Kernel::KThread::InitializeIdleThread(system, idle_thread, core).IsSuccess()); KThread::Register(system.Kernel(), idle_thread); - schedulers[i]->Initialize(system.Kernel(), main_thread, idle_thread, core); + schedulers[i]->Initialize(main_thread, idle_thread, core); } } @@ -247,18 +247,19 @@ struct KernelCore::Impl { ASSERT(system_resource_limit->SetLimitValue(LimitableResource::EventCountMax, 900).IsSuccess()); ASSERT(system_resource_limit->SetLimitValue(LimitableResource::TransferMemoryCountMax, 200).IsSuccess()); ASSERT(system_resource_limit->SetLimitValue(LimitableResource::SessionCountMax, 1133).IsSuccess()); - system_resource_limit->Reserve(kernel, LimitableResource::PhysicalMemoryMax, kernel_size); + system_resource_limit->Reserve(LimitableResource::PhysicalMemoryMax, kernel_size); // Reserve secure applet memory, introduced in firmware 5.0.0 constexpr u64 secure_applet_memory_size{4_MiB}; - ASSERT(system_resource_limit->Reserve(kernel, LimitableResource::PhysicalMemoryMax, secure_applet_memory_size)); + ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemoryMax, + secure_applet_memory_size)); } void InitializePreemption(KernelCore& kernel) { preemption_event = Core::Timing::CreateEvent("PreemptionCallback", [this, &kernel](s64 time, std::chrono::nanoseconds) -> std::optional { { KScopedSchedulerLock lock(kernel); - global_scheduler_context->PreemptThreads(kernel); + global_scheduler_context->PreemptThreads(); } return std::nullopt; }); @@ -349,9 +350,9 @@ struct KernelCore::Impl { object_name_global_data.emplace(kernel); } - void MakeApplicationProcess(KernelCore& kernel, KProcess* process) { + void MakeApplicationProcess(KProcess* process) { application_process = process; - application_process->Open(kernel); + application_process->Open(); } /// Sets the host thread ID for the caller. @@ -373,10 +374,10 @@ struct KernelCore::Impl { // Gets the dummy KThread for the caller, allocating a new one if this is the first time KThread* GetHostDummyThread(ThreadLocalData& t, KThread* existing_thread) { if (t.thread == nullptr) { - auto const initialize = [this](KThread* thread) { - ASSERT(KThread::InitializeDummyThread(system, thread, nullptr).IsSuccess()); + auto const initialize{[](KThread* thread) { + ASSERT(KThread::InitializeDummyThread(thread, nullptr).IsSuccess()); return thread; - }; + }}; t.raw_thread.emplace(system.Kernel()); t.thread = existing_thread ? existing_thread : initialize(&*t.raw_thread); ASSERT(t.thread != nullptr); @@ -417,7 +418,8 @@ struct KernelCore::Impl { return is_shutting_down.load(std::memory_order_relaxed); } - KThread* GetCurrentEmuThread(ThreadLocalData& t) { + KThread* GetCurrentEmuThread() { + auto& t = tls_data; return t.current_thread ? t.current_thread : (t.current_thread = GetHostDummyThread(t, nullptr)); } @@ -740,19 +742,19 @@ struct KernelCore::Impl { time_shared_mem = KSharedMemory::Create(system.Kernel()); hidbus_shared_mem = KSharedMemory::Create(system.Kernel()); - font_shared_mem->Initialize(system.Kernel(), system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, + font_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, Svc::MemoryPermission::Read, font_size); KSharedMemory::Register(kernel, font_shared_mem); - irs_shared_mem->Initialize(system.Kernel(), system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, + irs_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, Svc::MemoryPermission::Read, irs_size); KSharedMemory::Register(kernel, irs_shared_mem); - time_shared_mem->Initialize(system.Kernel(), system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, + time_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, Svc::MemoryPermission::Read, time_size); KSharedMemory::Register(kernel, time_shared_mem); - hidbus_shared_mem->Initialize(system.Kernel(), system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, + hidbus_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, Svc::MemoryPermission::Read, hidbus_size); KSharedMemory::Register(kernel, hidbus_shared_mem); } @@ -850,7 +852,7 @@ void KernelCore::Initialize() { } void KernelCore::Shutdown() { - impl->Shutdown(*this); + impl->Shutdown(); } void KernelCore::CloseServices() { @@ -866,7 +868,7 @@ KResourceLimit* KernelCore::GetSystemResourceLimit() { } void KernelCore::AppendNewProcess(KProcess* process) { - process->Open(*this); + process->Open(); std::scoped_lock lk{impl->process_list_lock}; impl->process_list.push_back(process); @@ -875,12 +877,12 @@ void KernelCore::AppendNewProcess(KProcess* process) { void KernelCore::RemoveProcess(KProcess* process) { std::scoped_lock lk{impl->process_list_lock}; if (std::erase(impl->process_list, process)) { - process->Close(*this); + process->Close(); } } void KernelCore::MakeApplicationProcess(KProcess* process) { - impl->MakeApplicationProcess(*this, process); + impl->MakeApplicationProcess(process); } KProcess* KernelCore::ApplicationProcess() { @@ -894,8 +896,11 @@ const KProcess* KernelCore::ApplicationProcess() const { std::list> KernelCore::GetProcessList() { std::list> processes; std::scoped_lock lk{impl->process_list_lock}; - for (auto* const process : impl->process_list) - processes.emplace_back(*this, process); + + for (auto* const process : impl->process_list) { + processes.emplace_back(process); + } + return processes; } @@ -1024,14 +1029,15 @@ void KernelCore::RegisterHostThread(KThread* existing_thread) { } } -static std::jthread RunHostThreadFunc(KernelCore& kernel, KProcess* process, std::string&& thread_name, std::function&& func) { +static std::jthread RunHostThreadFunc(KernelCore& kernel, KProcess* process, + std::string&& thread_name, std::function&& func) { // Reserve a new thread from the process resource limit. - KScopedResourceReservation thread_reservation(kernel, process, LimitableResource::ThreadCountMax); + KScopedResourceReservation thread_reservation(process, LimitableResource::ThreadCountMax); ASSERT(thread_reservation.Succeeded()); // Initialize the thread. KThread* thread = KThread::Create(kernel); - ASSERT(R_SUCCEEDED(KThread::InitializeDummyThread(kernel.System(), thread, process))); + ASSERT(R_SUCCEEDED(KThread::InitializeDummyThread(thread, process))); // Commit the thread reservation. thread_reservation.Commit(); @@ -1051,7 +1057,7 @@ static std::jthread RunHostThreadFunc(KernelCore& kernel, KProcess* process, std // Close the thread. // This will free the process if it is the last reference. - thread->Close(kernel); + thread->Close(); }); } @@ -1060,11 +1066,11 @@ std::jthread KernelCore::RunOnHostCoreProcess(std::string&& process_name, // Make a new process. KProcess* process = KProcess::Create(*this); ASSERT(R_SUCCEEDED( - process->Initialize(*this, Svc::CreateProcessParameter{}, GetSystemResourceLimit(), false))); + process->Initialize(Svc::CreateProcessParameter{}, GetSystemResourceLimit(), false))); // Ensure that we don't hold onto any extra references. SCOPE_EXIT { - process->Close(*this); + process->Close(); }; // Register the new process. @@ -1090,18 +1096,18 @@ void KernelCore::RunOnGuestCoreProcess(std::string&& process_name, std::function // Make a new process. KProcess* process = KProcess::Create(*this); ASSERT(R_SUCCEEDED( - process->Initialize(*this, Svc::CreateProcessParameter{}, GetSystemResourceLimit(), false))); + process->Initialize(Svc::CreateProcessParameter{}, GetSystemResourceLimit(), false))); // Ensure that we don't hold onto any extra references. SCOPE_EXIT { - process->Close(*this); + process->Close(); }; // Register the new process. KProcess::Register(*this, process); // Reserve a new thread from the process resource limit. - KScopedResourceReservation thread_reservation(*this, process, LimitableResource::ThreadCountMax); + KScopedResourceReservation thread_reservation(process, LimitableResource::ThreadCountMax); ASSERT(thread_reservation.Succeeded()); // Initialize the thread. @@ -1116,7 +1122,7 @@ void KernelCore::RunOnGuestCoreProcess(std::string&& process_name, std::function KThread::Register(*this, thread); // Begin running the thread. - ASSERT(R_SUCCEEDED(thread->Run(*this))); + ASSERT(R_SUCCEEDED(thread->Run())); } u32 KernelCore::GetCurrentHostThreadID() const { @@ -1124,7 +1130,7 @@ u32 KernelCore::GetCurrentHostThreadID() const { } KThread* KernelCore::GetCurrentEmuThread() const { - return impl->GetCurrentEmuThread(Impl::tls_data); + return impl->GetCurrentEmuThread(); } void KernelCore::SetCurrentEmuThread(KThread* thread) { @@ -1200,9 +1206,9 @@ void KernelCore::SuspendEmulation(bool suspended) { for (auto& thread : process->GetThreadList()) { if (should_suspend) { - thread.RequestSuspend(*this, SuspendType::System); + thread.RequestSuspend(SuspendType::System); } else { - thread.Resume(*this, SuspendType::System); + thread.Resume(SuspendType::System); } } } @@ -1238,9 +1244,12 @@ void KernelCore::SuspendEmulation(bool suspended) { void KernelCore::ShutdownCores() { impl->TerminateAllProcesses(); + KScopedSchedulerLock lk{*this}; - for (auto* thread : impl->shutdown_threads) - void(thread->Run(*this)); + + for (auto* thread : impl->shutdown_threads) { + void(thread->Run()); + } } bool KernelCore::IsMulticore() const { diff --git a/src/core/hle/kernel/physical_core.cpp b/src/core/hle/kernel/physical_core.cpp index a81c14f643..f394122764 100644 --- a/src/core/hle/kernel/physical_core.cpp +++ b/src/core/hle/kernel/physical_core.cpp @@ -17,15 +17,14 @@ namespace Kernel { PhysicalCore::PhysicalCore(KernelCore& kernel, std::size_t core_index) - : m_core_index{core_index} -{ + : m_kernel{kernel}, m_core_index{core_index} { m_is_single_core = !kernel.IsMulticore(); } PhysicalCore::~PhysicalCore() = default; -void PhysicalCore::RunThread(KernelCore& kernel, Kernel::KThread* thread) { +void PhysicalCore::RunThread(Kernel::KThread* thread) { auto* process = thread->GetOwnerProcess(); - auto& system = kernel.System(); + auto& system = m_kernel.System(); auto* interface = process->GetArmInterface(m_core_index); interface->Initialize(); @@ -73,14 +72,14 @@ void PhysicalCore::RunThread(KernelCore& kernel, Kernel::KThread* thread) { while (true) { // If the thread is scheduled for termination, exit. if (thread->HasDpc() && thread->IsTerminationRequested()) { - thread->Exit(kernel); + thread->Exit(); } // Notify the debugger and go to sleep if a step was performed // and this thread has been scheduled again. if (thread->GetStepState() == StepState::StepPerformed) { system.GetDebugger().NotifyThreadStopped(thread); - thread->RequestSuspend(kernel, SuspendType::Debug); + thread->RequestSuspend(SuspendType::Debug); return; } @@ -136,7 +135,7 @@ void PhysicalCore::RunThread(KernelCore& kernel, Kernel::KThread* thread) { } else { interface->LogBacktrace(process); } - thread->RequestSuspend(kernel, SuspendType::Debug); + thread->RequestSuspend(SuspendType::Debug); return; } @@ -145,7 +144,7 @@ void PhysicalCore::RunThread(KernelCore& kernel, Kernel::KThread* thread) { if (system.DebuggerEnabled()) { system.GetDebugger().NotifyThreadWatchpoint(thread, *interface->HaltedWatchpoint()); } - thread->RequestSuspend(kernel, SuspendType::Debug); + thread->RequestSuspend(SuspendType::Debug); return; } @@ -209,8 +208,8 @@ void PhysicalCore::CloneFpuStatus(KThread* dst) const { dst->GetContext().fpsr = ctx.fpsr; } -void PhysicalCore::LogBacktrace(KernelCore& kernel) { - auto* process = GetCurrentProcessPointer(kernel); +void PhysicalCore::LogBacktrace() { + auto* process = GetCurrentProcessPointer(m_kernel); if (!process) { return; } diff --git a/src/core/hle/kernel/physical_core.h b/src/core/hle/kernel/physical_core.h index b92201204a..bae4fe5b88 100644 --- a/src/core/hle/kernel/physical_core.h +++ b/src/core/hle/kernel/physical_core.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -33,7 +30,7 @@ public: YUZU_NON_MOVEABLE(PhysicalCore); // Execute guest code running on the given thread. - void RunThread(KernelCore& kernel, KThread* thread); + void RunThread(KThread* thread); // Copy context from thread to current core. void LoadContext(const KThread* thread); @@ -47,7 +44,7 @@ public: void CloneFpuStatus(KThread* dst) const; // Log backtrace of current processor state. - void LogBacktrace(KernelCore& kernel); + void LogBacktrace(); // Wait for an interrupt. void Idle(); @@ -66,7 +63,9 @@ public: } private: + KernelCore& m_kernel; const std::size_t m_core_index; + std::mutex m_guard; std::condition_variable m_on_interrupt; Core::ArmInterface* m_arm_interface{}; diff --git a/src/core/hle/kernel/slab_helpers.h b/src/core/hle/kernel/slab_helpers.h index 95e6b9f6e6..d1bbc76709 100644 --- a/src/core/hle/kernel/slab_helpers.h +++ b/src/core/hle/kernel/slab_helpers.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -72,16 +69,16 @@ public: explicit KAutoObjectWithSlabHeap(KernelCore& kernel) : Base(kernel) {} virtual ~KAutoObjectWithSlabHeap() = default; - virtual void Destroy(KernelCore& kernel) override { + virtual void Destroy() override { const bool is_initialized = this->IsInitialized(); uintptr_t arg = 0; if (is_initialized) { arg = this->GetPostDestroyArgument(); - this->Finalize(kernel); + this->Finalize(); } - Free(kernel, static_cast(this)); + Free(Base::m_kernel, static_cast(this)); if (is_initialized) { - Derived::PostDestroy(kernel, arg); + Derived::PostDestroy(arg); } } @@ -92,8 +89,8 @@ public: return 0; } - size_t GetSlabIndex(KernelCore& kernel) const { - return SlabHeap(kernel).GetObjectIndex(static_cast(this)); + size_t GetSlabIndex() const { + return SlabHeap(Base::m_kernel).GetObjectIndex(static_cast(this)); } public: @@ -147,17 +144,17 @@ public: KAutoObjectWithSlabHeapAndContainer(KernelCore& kernel) : Base(kernel) {} virtual ~KAutoObjectWithSlabHeapAndContainer() {} - virtual void Destroy(KernelCore& kernel) override { + virtual void Destroy() override { const bool is_initialized = this->IsInitialized(); uintptr_t arg = 0; if (is_initialized) { - kernel.ObjectListContainer().Unregister(this); + Base::m_kernel.ObjectListContainer().Unregister(this); arg = this->GetPostDestroyArgument(); - this->Finalize(kernel); + this->Finalize(); } - Free(kernel, static_cast(this)); + Free(Base::m_kernel, static_cast(this)); if (is_initialized) { - Derived::PostDestroy(kernel, arg); + Derived::PostDestroy(arg); } } @@ -168,8 +165,8 @@ public: return 0; } - size_t GetSlabIndex(KernelCore& kernel) const { - return SlabHeap(kernel).GetObjectIndex(static_cast(this)); + size_t GetSlabIndex() const { + return SlabHeap(Base::m_kernel).GetObjectIndex(static_cast(this)); } public: @@ -180,8 +177,9 @@ public: static Derived* Create(KernelCore& kernel) { Derived* obj = Allocate(kernel); - if (obj != nullptr) + if (obj != nullptr) { KAutoObject::Create(obj); + } return obj; } diff --git a/src/core/hle/kernel/svc/svc_activity.cpp b/src/core/hle/kernel/svc/svc_activity.cpp index c1ab3daab3..63bc085554 100644 --- a/src/core/hle/kernel/svc/svc_activity.cpp +++ b/src/core/hle/kernel/svc/svc_activity.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -25,15 +22,17 @@ Result SetThreadActivity(Core::System& system, Handle thread_handle, R_UNLESS(IsValidThreadActivity(thread_activity), ResultInvalidEnumValue); // Get the thread from its handle. - KScopedAutoObject thread = GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(system.Kernel(), thread_handle); + KScopedAutoObject thread = + GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(thread_handle); R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); // Check that the activity is being set on a non-current thread for the current process. - R_UNLESS(thread->GetOwnerProcess() == GetCurrentProcessPointer(system.Kernel()), ResultInvalidHandle); + R_UNLESS(thread->GetOwnerProcess() == GetCurrentProcessPointer(system.Kernel()), + ResultInvalidHandle); R_UNLESS(thread.GetPointerUnsafe() != GetCurrentThreadPointer(system.Kernel()), ResultBusy); // Set the activity. - R_TRY(thread->SetActivity(system.Kernel(), thread_activity)); + R_TRY(thread->SetActivity(thread_activity)); return ResultSuccess; } diff --git a/src/core/hle/kernel/svc/svc_cache.cpp b/src/core/hle/kernel/svc/svc_cache.cpp index 24f64f28f1..c2c8be10f5 100644 --- a/src/core/hle/kernel/svc/svc_cache.cpp +++ b/src/core/hle/kernel/svc/svc_cache.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -40,7 +37,8 @@ Result FlushProcessDataCache(Core::System& system, Handle process_handle, u64 ad R_UNLESS(size == static_cast(size), ResultInvalidCurrentMemory); // Get the process from its handle. - KScopedAutoObject process = GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(system.Kernel(), process_handle); + KScopedAutoObject process = + GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(process_handle); R_UNLESS(process.IsNotNull(), ResultInvalidHandle); // Verify the region is within range. diff --git a/src/core/hle/kernel/svc/svc_code_memory.cpp b/src/core/hle/kernel/svc/svc_code_memory.cpp index 4133586d11..4e7af9f575 100644 --- a/src/core/hle/kernel/svc/svc_code_memory.cpp +++ b/src/core/hle/kernel/svc/svc_code_memory.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -35,6 +35,9 @@ constexpr bool IsValidUnmapFromOwnerCodeMemoryPermission(MemoryPermission perm) Result CreateCodeMemory(Core::System& system, Handle* out, u64 address, uint64_t size) { LOG_TRACE(Kernel_SVC, "called, address={:#X}, size=0x{:X}", address, size); + // Get kernel instance. + auto& kernel = system.Kernel(); + // Validate address / size. R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress); R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize); @@ -43,23 +46,24 @@ Result CreateCodeMemory(Core::System& system, Handle* out, u64 address, uint64_t // Create the code memory. - KCodeMemory* code_mem = KCodeMemory::Create(system.Kernel()); + KCodeMemory* code_mem = KCodeMemory::Create(kernel); R_UNLESS(code_mem != nullptr, ResultOutOfResource); SCOPE_EXIT { - code_mem->Close(system.Kernel()); + code_mem->Close(); }; // Verify that the region is in range. - R_UNLESS(GetCurrentProcess(system.Kernel()).GetPageTable().Contains(address, size), ResultInvalidCurrentMemory); + R_UNLESS(GetCurrentProcess(system.Kernel()).GetPageTable().Contains(address, size), + ResultInvalidCurrentMemory); // Initialize the code memory. - R_TRY(code_mem->Initialize(system.Kernel(), system.DeviceMemory(), address, size)); + R_TRY(code_mem->Initialize(system.DeviceMemory(), address, size)); // Register the code memory. - KCodeMemory::Register(system.Kernel(), code_mem); + KCodeMemory::Register(kernel, code_mem); // Add the code memory to the handle table. - R_TRY(GetCurrentProcess(system.Kernel()).GetHandleTable().Add(system.Kernel(), out, code_mem)); + R_TRY(GetCurrentProcess(system.Kernel()).GetHandleTable().Add(out, code_mem)); R_SUCCEED(); } @@ -81,8 +85,8 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle, // Get the code memory from its handle. KScopedAutoObject code_mem = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject(system.Kernel(), code_memory_handle); + .GetHandleTable() + .GetObject(code_memory_handle); R_UNLESS(code_mem.IsNotNull(), ResultInvalidHandle); // NOTE: Here, Atmosphere extends the SVC to allow code memory operations on one's own process. @@ -92,23 +96,29 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle, switch (operation) { case CodeMemoryOperation::Map: { // Check that the region is in range. - R_UNLESS(GetCurrentProcess(system.Kernel()).GetPageTable().CanContain(address, size, KMemoryState::CodeOut), ResultInvalidMemoryRegion); + R_UNLESS(GetCurrentProcess(system.Kernel()) + .GetPageTable() + .CanContain(address, size, KMemoryState::CodeOut), + ResultInvalidMemoryRegion); // Check the memory permission. R_UNLESS(IsValidMapCodeMemoryPermission(perm), ResultInvalidNewMemoryPermission); // Map the memory. - R_TRY(code_mem->Map(system.Kernel(), address, size)); + R_TRY(code_mem->Map(address, size)); } break; case CodeMemoryOperation::Unmap: { // Check that the region is in range. - R_UNLESS(GetCurrentProcess(system.Kernel()).GetPageTable().CanContain(address, size, KMemoryState::CodeOut), ResultInvalidMemoryRegion); + R_UNLESS(GetCurrentProcess(system.Kernel()) + .GetPageTable() + .CanContain(address, size, KMemoryState::CodeOut), + ResultInvalidMemoryRegion); // Check the memory permission. R_UNLESS(IsValidUnmapCodeMemoryPermission(perm), ResultInvalidNewMemoryPermission); // Unmap the memory. - R_TRY(code_mem->Unmap(system.Kernel(), address, size)); + R_TRY(code_mem->Unmap(address, size)); } break; case CodeMemoryOperation::MapToOwner: { // Check that the region is in range. @@ -120,7 +130,7 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle, R_UNLESS(IsValidMapToOwnerCodeMemoryPermission(perm), ResultInvalidNewMemoryPermission); // Map the memory to its owner. - R_TRY(code_mem->MapToOwner(system.Kernel(), address, size, perm)); + R_TRY(code_mem->MapToOwner(address, size, perm)); } break; case CodeMemoryOperation::UnmapFromOwner: { // Check that the region is in range. @@ -132,7 +142,7 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle, R_UNLESS(IsValidUnmapFromOwnerCodeMemoryPermission(perm), ResultInvalidNewMemoryPermission); // Unmap the memory from its owner. - R_TRY(code_mem->UnmapFromOwner(system.Kernel(), address, size)); + R_TRY(code_mem->UnmapFromOwner(address, size)); } break; default: R_THROW(ResultInvalidEnumValue); diff --git a/src/core/hle/kernel/svc/svc_device_address_space.cpp b/src/core/hle/kernel/svc/svc_device_address_space.cpp index 2deb683d4b..ac828320f4 100644 --- a/src/core/hle/kernel/svc/svc_device_address_space.cpp +++ b/src/core/hle/kernel/svc/svc_device_address_space.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -32,17 +29,17 @@ Result CreateDeviceAddressSpace(Core::System& system, Handle* out, uint64_t das_ KDeviceAddressSpace* das = KDeviceAddressSpace::Create(system.Kernel()); R_UNLESS(das != nullptr, ResultOutOfResource); SCOPE_EXIT { - das->Close(system.Kernel()); + das->Close(); }; // Initialize the device address space. - R_TRY(das->Initialize(system.Kernel(), das_address, das_size)); + R_TRY(das->Initialize(das_address, das_size)); // Register the device address space. KDeviceAddressSpace::Register(system.Kernel(), das); // Add to the handle table. - R_TRY(GetCurrentProcess(system.Kernel()).GetHandleTable().Add(system.Kernel(), out, das)); + R_TRY(GetCurrentProcess(system.Kernel()).GetHandleTable().Add(out, das)); R_SUCCEED(); } @@ -50,8 +47,8 @@ Result CreateDeviceAddressSpace(Core::System& system, Handle* out, uint64_t das_ Result AttachDeviceAddressSpace(Core::System& system, DeviceName device_name, Handle das_handle) { // Get the device address space. KScopedAutoObject das = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject(system.Kernel(), das_handle); + .GetHandleTable() + .GetObject(das_handle); R_UNLESS(das.IsNotNull(), ResultInvalidHandle); // Attach. @@ -61,8 +58,8 @@ Result AttachDeviceAddressSpace(Core::System& system, DeviceName device_name, Ha Result DetachDeviceAddressSpace(Core::System& system, DeviceName device_name, Handle das_handle) { // Get the device address space. KScopedAutoObject das = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject(system.Kernel(), das_handle); + .GetHandleTable() + .GetObject(das_handle); R_UNLESS(das.IsNotNull(), ResultInvalidHandle); // Detach. @@ -102,13 +99,13 @@ Result MapDeviceAddressSpaceByForce(Core::System& system, Handle das_handle, Han // Get the device address space. KScopedAutoObject das = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject(system.Kernel(), das_handle); + .GetHandleTable() + .GetObject(das_handle); R_UNLESS(das.IsNotNull(), ResultInvalidHandle); // Get the process. KScopedAutoObject process = - GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(system.Kernel(), process_handle); + GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(process_handle); R_UNLESS(process.IsNotNull(), ResultInvalidHandle); // Validate that the process address is within range. @@ -143,13 +140,13 @@ Result MapDeviceAddressSpaceAligned(Core::System& system, Handle das_handle, Han // Get the device address space. KScopedAutoObject das = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject(system.Kernel(), das_handle); + .GetHandleTable() + .GetObject(das_handle); R_UNLESS(das.IsNotNull(), ResultInvalidHandle); // Get the process. KScopedAutoObject process = - GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(system.Kernel(), process_handle); + GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(process_handle); R_UNLESS(process.IsNotNull(), ResultInvalidHandle); // Validate that the process address is within range. @@ -175,12 +172,13 @@ Result UnmapDeviceAddressSpace(Core::System& system, Handle das_handle, Handle p // Get the device address space. KScopedAutoObject das = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject(system.Kernel(), das_handle); + .GetHandleTable() + .GetObject(das_handle); R_UNLESS(das.IsNotNull(), ResultInvalidHandle); // Get the process. - KScopedAutoObject process = GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(system.Kernel(), process_handle); + KScopedAutoObject process = + GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(process_handle); R_UNLESS(process.IsNotNull(), ResultInvalidHandle); // Validate that the process address is within range. diff --git a/src/core/hle/kernel/svc/svc_event.cpp b/src/core/hle/kernel/svc/svc_event.cpp index 36de3b9096..586cb2b14e 100644 --- a/src/core/hle/kernel/svc/svc_event.cpp +++ b/src/core/hle/kernel/svc/svc_event.cpp @@ -22,9 +22,9 @@ Result SignalEvent(Core::System& system, Handle event_handle) { // Fail-safe for system applets const auto program_id = GetCurrentProcess(system.Kernel()).GetProgramId(); if ((program_id & 0xFFFFFFFFFFFFFF00ull) == 0x0100000000001000ull) { - KScopedAutoObject event = handle_table.GetObject(system.Kernel(), event_handle); + KScopedAutoObject event = handle_table.GetObject(event_handle); if (event.IsNotNull()) { - event->Signal(system.Kernel()); + event->Signal(); } else { LOG_WARNING(Kernel_SVC, "SignalEvent best-effort unknown handle=0x{:08X} (ignored)", event_handle); @@ -34,10 +34,10 @@ Result SignalEvent(Core::System& system, Handle event_handle) { // Get the event. - KScopedAutoObject event = handle_table.GetObject(system.Kernel(), event_handle); + KScopedAutoObject event = handle_table.GetObject(event_handle); R_UNLESS(event.IsNotNull(), ResultInvalidHandle); - R_RETURN(event->Signal(system.Kernel())); + R_RETURN(event->Signal()); } Result ClearEvent(Core::System& system, Handle event_handle) { @@ -48,18 +48,18 @@ Result ClearEvent(Core::System& system, Handle event_handle) { // Try to clear the writable event. { - KScopedAutoObject event = handle_table.GetObject(system.Kernel(), event_handle); + KScopedAutoObject event = handle_table.GetObject(event_handle); if (event.IsNotNull()) { - event->Clear(system.Kernel()); + event->Clear(); R_SUCCEED(); } } // Try to clear the readable event. { - KScopedAutoObject readable_event = handle_table.GetObject(system.Kernel(), event_handle); + KScopedAutoObject readable_event = handle_table.GetObject(event_handle); if (readable_event.IsNotNull()) { - readable_event->Clear(system.Kernel()); + readable_event->Clear(); R_SUCCEED(); } } @@ -71,42 +71,43 @@ Result CreateEvent(Core::System& system, Handle* out_write, Handle* out_read) { LOG_DEBUG(Kernel_SVC, "called"); // Get the kernel reference and handle table. - auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable(); + auto& kernel = system.Kernel(); + auto& handle_table = GetCurrentProcess(kernel).GetHandleTable(); // Reserve a new event from the process resource limit - KScopedResourceReservation event_reservation(system.Kernel(), GetCurrentProcessPointer(system.Kernel()), + KScopedResourceReservation event_reservation(GetCurrentProcessPointer(kernel), LimitableResource::EventCountMax); R_UNLESS(event_reservation.Succeeded(), ResultLimitReached); // Create a new event. - KEvent* event = KEvent::Create(system.Kernel()); + KEvent* event = KEvent::Create(kernel); R_UNLESS(event != nullptr, ResultOutOfResource); // Initialize the event. - event->Initialize(system.Kernel(), GetCurrentProcessPointer(system.Kernel())); + event->Initialize(GetCurrentProcessPointer(kernel)); // Commit the thread reservation. event_reservation.Commit(); // Ensure that we clean up the event (and its only references are handle table) on function end. SCOPE_EXIT { - event->GetReadableEvent().Close(system.Kernel()); - event->Close(system.Kernel()); + event->GetReadableEvent().Close(); + event->Close(); }; // Register the event. - KEvent::Register(system.Kernel(), event); + KEvent::Register(kernel, event); // Add the event to the handle table. - R_TRY(handle_table.Add(system.Kernel(), out_write, event)); + R_TRY(handle_table.Add(out_write, event)); // Ensure that we maintain a clean handle state on exit. ON_RESULT_FAILURE { - handle_table.Remove(system.Kernel(), *out_write); + handle_table.Remove(*out_write); }; // Add the readable event to the handle table. - R_RETURN(handle_table.Add(system.Kernel(), out_read, std::addressof(event->GetReadableEvent()))); + R_RETURN(handle_table.Add(out_read, std::addressof(event->GetReadableEvent()))); } Result SignalEvent64(Core::System& system, Handle event_handle) { diff --git a/src/core/hle/kernel/svc/svc_exception.cpp b/src/core/hle/kernel/svc/svc_exception.cpp index e1b0fa7b95..bf09641bad 100644 --- a/src/core/hle/kernel/svc/svc_exception.cpp +++ b/src/core/hle/kernel/svc/svc_exception.cpp @@ -106,14 +106,14 @@ void Break(Core::System& system, BreakReason reason, u64 info1, u64 info2) { handle_debug_buffer(info1, info2); - system.CurrentPhysicalCore().LogBacktrace(system.Kernel()); + system.CurrentPhysicalCore().LogBacktrace(); } const bool should_break = !notification_only; if (system.DebuggerEnabled() && should_break) { auto* thread = system.Kernel().GetCurrentEmuThread(); system.GetDebugger().NotifyThreadStopped(thread); - thread->RequestSuspend(system.Kernel(), Kernel::SuspendType::Debug); + thread->RequestSuspend(Kernel::SuspendType::Debug); } } diff --git a/src/core/hle/kernel/svc/svc_info.cpp b/src/core/hle/kernel/svc/svc_info.cpp index 62f203476e..9e651e1171 100644 --- a/src/core/hle/kernel/svc/svc_info.cpp +++ b/src/core/hle/kernel/svc/svc_info.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -46,7 +46,7 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle R_UNLESS(info_sub_id == 0, ResultInvalidEnumValue); const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable(); - KScopedAutoObject process = handle_table.GetObject(system.Kernel(), handle); + KScopedAutoObject process = handle_table.GetObject(handle); R_UNLESS(process.IsNotNull(), ResultInvalidHandle); switch (info_id_type) { @@ -90,11 +90,11 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle R_SUCCEED(); case InfoType::TotalMemorySize: - *result = process->GetTotalUserPhysicalMemorySize(system.Kernel()); + *result = process->GetTotalUserPhysicalMemorySize(); R_SUCCEED(); case InfoType::UsedMemorySize: - *result = process->GetUsedUserPhysicalMemorySize(system.Kernel()); + *result = process->GetUsedUserPhysicalMemorySize(); R_SUCCEED(); case InfoType::SystemResourceSizeTotal: @@ -114,11 +114,11 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle R_SUCCEED(); case InfoType::TotalNonSystemMemorySize: - *result = process->GetTotalNonSystemUserPhysicalMemorySize(system.Kernel()); + *result = process->GetTotalNonSystemUserPhysicalMemorySize(); R_SUCCEED(); case InfoType::UsedNonSystemMemorySize: - *result = process->GetUsedNonSystemUserPhysicalMemorySize(system.Kernel()); + *result = process->GetUsedNonSystemUserPhysicalMemorySize(); R_SUCCEED(); case InfoType::IsApplication: @@ -175,7 +175,7 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle } Handle resource_handle{}; - R_TRY(handle_table.Add(system.Kernel(), std::addressof(resource_handle), resource_limit)); + R_TRY(handle_table.Add(std::addressof(resource_handle), resource_limit)); *result = resource_handle; R_SUCCEED(); @@ -203,8 +203,8 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle } KScopedAutoObject thread = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject(system.Kernel(), Handle(handle)); + .GetHandleTable() + .GetObject(static_cast(handle)); if (thread.IsNull()) { LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", static_cast(handle)); @@ -256,7 +256,7 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle // Get a new handle for the current process. Handle tmp; - R_TRY(handle_table.Add(system.Kernel(), std::addressof(tmp), current_process)); + R_TRY(handle_table.Add(std::addressof(tmp), current_process)); // Set the output. *result = tmp; diff --git a/src/core/hle/kernel/svc/svc_ipc.cpp b/src/core/hle/kernel/svc/svc_ipc.cpp index 875590d6f7..db912b71fb 100644 --- a/src/core/hle/kernel/svc/svc_ipc.cpp +++ b/src/core/hle/kernel/svc/svc_ipc.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -20,17 +20,19 @@ namespace Kernel::Svc { namespace { -Result SendSyncRequestImpl(KernelCore& kernel, uintptr_t message, size_t buffer_size, Handle session_handle) { +Result SendSyncRequestImpl(KernelCore& kernel, uintptr_t message, size_t buffer_size, + Handle session_handle) { // Get the client session. - KScopedAutoObject session = GetCurrentProcess(kernel).GetHandleTable().GetObject(kernel, session_handle); + KScopedAutoObject session = + GetCurrentProcess(kernel).GetHandleTable().GetObject(session_handle); R_UNLESS(session.IsNotNull(), ResultInvalidHandle); // Get the parent, and persist a reference to it until we're done. - KScopedAutoObject parent = {kernel, session->GetParent()}; + KScopedAutoObject parent = session->GetParent(); ASSERT(parent.IsNotNull()); // Send the request. - R_RETURN(session->SendSyncRequest(kernel, message, buffer_size)); + R_RETURN(session->SendSyncRequest(message, buffer_size)); } Result ReplyAndReceiveImpl(KernelCore& kernel, int32_t* out_index, uintptr_t message, @@ -39,7 +41,8 @@ Result ReplyAndReceiveImpl(KernelCore& kernel, int32_t* out_index, uintptr_t mes int64_t timeout_ns) { // Reply to the target, if one is specified. if (reply_target != InvalidHandle) { - KScopedAutoObject session = GetCurrentProcess(kernel).GetHandleTable().GetObject(kernel, reply_target); + KScopedAutoObject session = + GetCurrentProcess(kernel).GetHandleTable().GetObject(reply_target); R_UNLESS(session.IsNotNull(), ResultInvalidHandle); // If we fail to reply, we want to set the output index to -1. @@ -48,7 +51,7 @@ Result ReplyAndReceiveImpl(KernelCore& kernel, int32_t* out_index, uintptr_t mes }; // Send the reply. - R_TRY(session->SendReply(kernel, message, buffer_size, message_paddr)); + R_TRY(session->SendReply(message, buffer_size, message_paddr)); } // Receive a message. @@ -74,7 +77,8 @@ Result ReplyAndReceiveImpl(KernelCore& kernel, int32_t* out_index, uintptr_t mes while (true) { // Wait for an object. s32 index; - Result result = KSynchronizationObject::Wait(kernel, std::addressof(index), objs, num_objects, timeout); + Result result = KSynchronizationObject::Wait(kernel, std::addressof(index), objs, + num_objects, timeout); if (ResultTimedOut == result) { R_THROW(result); } @@ -83,7 +87,7 @@ Result ReplyAndReceiveImpl(KernelCore& kernel, int32_t* out_index, uintptr_t mes if (R_SUCCEEDED(result)) { KServerSession* session = objs[index]->DynamicCast(); if (session != nullptr) { - result = session->ReceiveRequest(kernel, message, buffer_size, message_paddr); + result = session->ReceiveRequest(message, buffer_size, message_paddr); if (ResultNotFound == result) { continue; } @@ -123,14 +127,14 @@ Result ReplyAndReceiveImpl(KernelCore& kernel, int32_t* out_index, uintptr_t mes // Convert the handles to objects. R_UNLESS( - handle_table.GetMultipleObjects(kernel, objs, handles, num_handles), + handle_table.GetMultipleObjects(objs, handles, num_handles), ResultInvalidHandle); } // Ensure handles are closed when we're done. SCOPE_EXIT { for (auto i = 0; i < num_handles; ++i) { - objs[i]->Close(kernel); + objs[i]->Close(); } }; @@ -184,15 +188,16 @@ Result SendAsyncRequestWithUserBuffer(Core::System& system, Handle* out_event_ha auto& handle_table = process.GetHandleTable(); // Reserve a new event from the process resource limit. - KScopedResourceReservation event_reservation(system.Kernel(), std::addressof(process), Svc::LimitableResource::EventCountMax); + KScopedResourceReservation event_reservation(std::addressof(process), + Svc::LimitableResource::EventCountMax); R_UNLESS(event_reservation.Succeeded(), ResultLimitReached); // Get the client session. - KScopedAutoObject session = process.GetHandleTable().GetObject(system.Kernel(), session_handle); + KScopedAutoObject session = process.GetHandleTable().GetObject(session_handle); R_UNLESS(session.IsNotNull(), ResultInvalidHandle); // Get the parent, and persist a reference to it until we're done. - KScopedAutoObject parent = {system.Kernel(), session->GetParent()}; + KScopedAutoObject parent = session->GetParent(); ASSERT(parent.IsNotNull()); // Create a new event. @@ -200,30 +205,30 @@ Result SendAsyncRequestWithUserBuffer(Core::System& system, Handle* out_event_ha R_UNLESS(event != nullptr, ResultOutOfResource); // Initialize the event. - event->Initialize(system.Kernel(), std::addressof(process)); + event->Initialize(std::addressof(process)); // Commit our reservation. event_reservation.Commit(); // At end of scope, kill the standing references to the sub events. SCOPE_EXIT { - event->GetReadableEvent().Close(system.Kernel()); - event->Close(system.Kernel()); + event->GetReadableEvent().Close(); + event->Close(); }; // Register the event. KEvent::Register(system.Kernel(), event); // Add the readable event to the handle table. - R_TRY(handle_table.Add(system.Kernel(), out_event_handle, std::addressof(event->GetReadableEvent()))); + R_TRY(handle_table.Add(out_event_handle, std::addressof(event->GetReadableEvent()))); // Ensure that if we fail to send the request, we close the readable handle. ON_RESULT_FAILURE { - handle_table.Remove(system.Kernel(), *out_event_handle); + handle_table.Remove(*out_event_handle); }; // Send the async request. - R_RETURN(session->SendAsyncRequest(system.Kernel(), event, message, buffer_size)); + R_RETURN(session->SendAsyncRequest(event, message, buffer_size)); } Result ReplyAndReceive(Core::System& system, s32* out_index, uint64_t handles, s32 num_handles, diff --git a/src/core/hle/kernel/svc/svc_light_ipc.cpp b/src/core/hle/kernel/svc/svc_light_ipc.cpp index ae3ff85a88..4772cbda17 100644 --- a/src/core/hle/kernel/svc/svc_light_ipc.cpp +++ b/src/core/hle/kernel/svc/svc_light_ipc.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -17,12 +14,12 @@ namespace Kernel::Svc { Result SendSyncRequestLight(Core::System& system, Handle session_handle, u32* args) { // Get the light client session from its handle. KScopedAutoObject session = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject(system.Kernel(), session_handle); + .GetHandleTable() + .GetObject(session_handle); R_UNLESS(session.IsNotNull(), ResultInvalidHandle); // Send the request. - R_TRY(session->SendSyncRequest(system.Kernel(), args)); + R_TRY(session->SendSyncRequest(args)); R_SUCCEED(); } @@ -30,12 +27,12 @@ Result SendSyncRequestLight(Core::System& system, Handle session_handle, u32* ar Result ReplyAndReceiveLight(Core::System& system, Handle session_handle, u32* args) { // Get the light server session from its handle. KScopedAutoObject session = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject(system.Kernel(), session_handle); + .GetHandleTable() + .GetObject(session_handle); R_UNLESS(session.IsNotNull(), ResultInvalidHandle); // Handle the request. - R_TRY(session->ReplyAndReceive(system.Kernel(), args)); + R_TRY(session->ReplyAndReceive(args)); R_SUCCEED(); } diff --git a/src/core/hle/kernel/svc/svc_port.cpp b/src/core/hle/kernel/svc/svc_port.cpp index bddd57e8f9..9a22dadaf7 100644 --- a/src/core/hle/kernel/svc/svc_port.cpp +++ b/src/core/hle/kernel/svc/svc_port.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -36,18 +33,18 @@ Result ConnectToNamedPort(Core::System& system, Handle* out, u64 user_name) { // Reserve a handle for the port. // NOTE: Nintendo really does write directly to the output handle here. - R_TRY(handle_table.Reserve(system.Kernel(), out)); + R_TRY(handle_table.Reserve(out)); ON_RESULT_FAILURE { - handle_table.Unreserve(system.Kernel(), *out); + handle_table.Unreserve(*out); }; // Create a session. KClientSession* session; - R_TRY(port->CreateSession(system.Kernel(), std::addressof(session))); + R_TRY(port->CreateSession(std::addressof(session))); // Register the session in the table, close the extra reference. - handle_table.Register(system.Kernel(), *out, session); - session->Close(system.Kernel()); + handle_table.Register(*out, session); + session->Close(); // We succeeded. R_SUCCEED(); @@ -68,27 +65,27 @@ Result CreatePort(Core::System& system, Handle* out_server, Handle* out_client, R_UNLESS(port != nullptr, ResultOutOfResource); // Initialize the port. - port->Initialize(system.Kernel(), max_sessions, is_light, name); + port->Initialize(max_sessions, is_light, name); // Ensure that we clean up the port (and its only references are handle table) on function end. SCOPE_EXIT { - port->GetServerPort().Close(system.Kernel()); - port->GetClientPort().Close(system.Kernel()); + port->GetServerPort().Close(); + port->GetClientPort().Close(); }; // Register the port. KPort::Register(kernel, port); // Add the client to the handle table. - R_TRY(handle_table.Add(system.Kernel(), out_client, std::addressof(port->GetClientPort()))); + R_TRY(handle_table.Add(out_client, std::addressof(port->GetClientPort()))); // Ensure that we maintain a clean handle state on exit. ON_RESULT_FAILURE { - handle_table.Remove(system.Kernel(), *out_client); + handle_table.Remove(*out_client); }; // Add the server to the handle table. - R_RETURN(handle_table.Add(system.Kernel(), out_server, std::addressof(port->GetServerPort()))); + R_RETURN(handle_table.Add(out_server, std::addressof(port->GetServerPort()))); } Result ConnectToPort(Core::System& system, Handle* out, Handle port) { @@ -96,33 +93,36 @@ Result ConnectToPort(Core::System& system, Handle* out, Handle port) { auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable(); // Get the client port. - KScopedAutoObject client_port = handle_table.GetObject(system.Kernel(), port); + KScopedAutoObject client_port = handle_table.GetObject(port); R_UNLESS(client_port.IsNotNull(), ResultInvalidHandle); // Reserve a handle for the port. // NOTE: Nintendo really does write directly to the output handle here. - R_TRY(handle_table.Reserve(system.Kernel(), out)); + R_TRY(handle_table.Reserve(out)); ON_RESULT_FAILURE { - handle_table.Unreserve(system.Kernel(), *out); + handle_table.Unreserve(*out); }; // Create the session. KAutoObject* session; - if (client_port->IsLight(system.Kernel())) { - R_TRY(client_port->CreateLightSession(system.Kernel(), reinterpret_cast(std::addressof(session)))); + if (client_port->IsLight()) { + R_TRY(client_port->CreateLightSession( + reinterpret_cast(std::addressof(session)))); } else { - R_TRY(client_port->CreateSession(system.Kernel(), reinterpret_cast(std::addressof(session)))); + R_TRY(client_port->CreateSession( + reinterpret_cast(std::addressof(session)))); } // Register the session. - handle_table.Register(system.Kernel(), *out, session); - session->Close(system.Kernel()); + handle_table.Register(*out, session); + session->Close(); // We succeeded. R_SUCCEED(); } -Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t user_name, int32_t max_sessions) { +Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t user_name, + int32_t max_sessions) { // Copy the provided name from user memory to kernel memory. auto string_name = GetCurrentMemory(system.Kernel()).ReadCString(user_name, KObjectName::NameLengthMax); @@ -144,21 +144,21 @@ Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t R_UNLESS(port != nullptr, ResultOutOfResource); // Initialize the new port. - port->Initialize(system.Kernel(), max_sessions, false, 0); + port->Initialize(max_sessions, false, 0); // Register the port. KPort::Register(system.Kernel(), port); // Ensure that our only reference to the port is in the handle table when we're done. SCOPE_EXIT { - port->GetClientPort().Close(system.Kernel()); - port->GetServerPort().Close(system.Kernel()); + port->GetClientPort().Close(); + port->GetServerPort().Close(); }; // Register the handle in the table. - R_TRY(handle_table.Add(system.Kernel(), out_server_handle, std::addressof(port->GetServerPort()))); + R_TRY(handle_table.Add(out_server_handle, std::addressof(port->GetServerPort()))); ON_RESULT_FAILURE { - handle_table.Remove(system.Kernel(), *out_server_handle); + handle_table.Remove(*out_server_handle); }; // Create a new object name. diff --git a/src/core/hle/kernel/svc/svc_process.cpp b/src/core/hle/kernel/svc/svc_process.cpp index dc2566e85a..6d63892a94 100644 --- a/src/core/hle/kernel/svc/svc_process.cpp +++ b/src/core/hle/kernel/svc/svc_process.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -27,8 +27,8 @@ Result GetProcessId(Core::System& system, u64* out_process_id, Handle handle) { // Get the object from the handle table. KScopedAutoObject obj = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject(system.Kernel(), Handle(handle)); + .GetHandleTable() + .GetObject(static_cast(handle)); R_UNLESS(obj.IsNotNull(), ResultInvalidHandle); // Get the process from the object. @@ -98,7 +98,7 @@ Result GetProcessInfo(Core::System& system, s64* out, Handle process_handle, LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, type={:#X}", process_handle, info_type); const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable(); - KScopedAutoObject process = handle_table.GetObject(system.Kernel(), process_handle); + KScopedAutoObject process = handle_table.GetObject(process_handle); if (process.IsNull()) { LOG_ERROR(Kernel_SVC, "Process handle does not exist, process_handle=0x{:08X}", process_handle); diff --git a/src/core/hle/kernel/svc/svc_process_memory.cpp b/src/core/hle/kernel/svc/svc_process_memory.cpp index 0c18be91ba..3313118dfa 100644 --- a/src/core/hle/kernel/svc/svc_process_memory.cpp +++ b/src/core/hle/kernel/svc/svc_process_memory.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -48,7 +48,7 @@ Result SetProcessMemoryPermission(Core::System& system, Handle process_handle, u // Get the process from its handle. KScopedAutoObject process = - GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(system.Kernel(), process_handle); + GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(process_handle); R_UNLESS(process.IsNotNull(), ResultInvalidHandle); // Validate that the address is in range. @@ -76,7 +76,7 @@ Result MapProcessMemory(Core::System& system, u64 dst_address, Handle process_ha // Get the processes. KProcess* dst_process = GetCurrentProcessPointer(system.Kernel()); KScopedAutoObject src_process = - dst_process->GetHandleTable().GetObjectWithoutPseudoHandle(system.Kernel(), process_handle); + dst_process->GetHandleTable().GetObjectWithoutPseudoHandle(process_handle); R_UNLESS(src_process.IsNotNull(), ResultInvalidHandle); // Get the page tables. @@ -117,7 +117,7 @@ Result UnmapProcessMemory(Core::System& system, u64 dst_address, Handle process_ // Get the processes. KProcess* dst_process = GetCurrentProcessPointer(system.Kernel()); KScopedAutoObject src_process = - dst_process->GetHandleTable().GetObjectWithoutPseudoHandle(system.Kernel(), process_handle); + dst_process->GetHandleTable().GetObjectWithoutPseudoHandle(process_handle); R_UNLESS(src_process.IsNotNull(), ResultInvalidHandle); // Get the page tables. @@ -174,7 +174,7 @@ Result MapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst } const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable(); - KScopedAutoObject process = handle_table.GetObject(system.Kernel(), process_handle); + KScopedAutoObject process = handle_table.GetObject(process_handle); if (process.IsNull()) { LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).", process_handle); @@ -234,7 +234,7 @@ Result UnmapProcessCodeMemory(Core::System& system, Handle process_handle, u64 d } const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable(); - KScopedAutoObject process = handle_table.GetObject(system.Kernel(), process_handle); + KScopedAutoObject process = handle_table.GetObject(process_handle); if (process.IsNull()) { LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).", process_handle); diff --git a/src/core/hle/kernel/svc/svc_query_memory.cpp b/src/core/hle/kernel/svc/svc_query_memory.cpp index ad7a667bb5..816dcb8d0f 100644 --- a/src/core/hle/kernel/svc/svc_query_memory.cpp +++ b/src/core/hle/kernel/svc/svc_query_memory.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -26,7 +23,7 @@ Result QueryProcessMemory(Core::System& system, uint64_t out_memory_info, PageIn Handle process_handle, uint64_t address) { LOG_TRACE(Kernel_SVC, "called process=0x{:08X} address={:X}", process_handle, address); const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable(); - KScopedAutoObject process = handle_table.GetObject(system.Kernel(), process_handle); + KScopedAutoObject process = handle_table.GetObject(process_handle); if (process.IsNull()) { LOG_ERROR(Kernel_SVC, "Process handle does not exist, process_handle=0x{:08X}", process_handle); diff --git a/src/core/hle/kernel/svc/svc_resource_limit.cpp b/src/core/hle/kernel/svc/svc_resource_limit.cpp index 7f78aa8b10..6f3972482f 100644 --- a/src/core/hle/kernel/svc/svc_resource_limit.cpp +++ b/src/core/hle/kernel/svc/svc_resource_limit.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -22,7 +19,7 @@ Result CreateResourceLimit(Core::System& system, Handle* out_handle) { // Ensure we don't leak a reference to the limit. SCOPE_EXIT { - resource_limit->Close(system.Kernel()); + resource_limit->Close(); }; // Initialize the resource limit. @@ -32,7 +29,7 @@ Result CreateResourceLimit(Core::System& system, Handle* out_handle) { KResourceLimit::Register(kernel, resource_limit); // Add the limit to the handle table. - R_RETURN(GetCurrentProcess(kernel).GetHandleTable().Add(system.Kernel(), out_handle, resource_limit)); + R_RETURN(GetCurrentProcess(kernel).GetHandleTable().Add(out_handle, resource_limit)); } Result GetResourceLimitLimitValue(Core::System& system, s64* out_limit_value, @@ -45,8 +42,8 @@ Result GetResourceLimitLimitValue(Core::System& system, s64* out_limit_value, // Get the resource limit. KScopedAutoObject resource_limit = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject(system.Kernel(), resource_limit_handle); + .GetHandleTable() + .GetObject(resource_limit_handle); R_UNLESS(resource_limit.IsNotNull(), ResultInvalidHandle); // Get the limit value. @@ -65,8 +62,8 @@ Result GetResourceLimitCurrentValue(Core::System& system, s64* out_current_value // Get the resource limit. KScopedAutoObject resource_limit = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject(system.Kernel(), resource_limit_handle); + .GetHandleTable() + .GetObject(resource_limit_handle); R_UNLESS(resource_limit.IsNotNull(), ResultInvalidHandle); // Get the current value. @@ -86,7 +83,7 @@ Result SetResourceLimitLimitValue(Core::System& system, Handle resource_limit_ha // Get the resource limit. KScopedAutoObject resource_limit = GetCurrentProcess(system.Kernel()) .GetHandleTable() - .GetObject(system.Kernel(), resource_limit_handle); + .GetObject(resource_limit_handle); R_UNLESS(resource_limit.IsNotNull(), ResultInvalidHandle); // Set the limit value. diff --git a/src/core/hle/kernel/svc/svc_session.cpp b/src/core/hle/kernel/svc/svc_session.cpp index 4d04f0c5a3..b034d21d15 100644 --- a/src/core/hle/kernel/svc/svc_session.cpp +++ b/src/core/hle/kernel/svc/svc_session.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -26,7 +23,7 @@ Result CreateSession(Core::System& system, Handle* out_server, Handle* out_clien // Reserve a new session from the process resource limit. // TODO: Dynamic resource limits - KScopedResourceReservation session_reservation(system.Kernel(), std::addressof(process), + KScopedResourceReservation session_reservation(std::addressof(process), LimitableResource::SessionCountMax); if (session_reservation.Succeeded()) { session = T::Create(system.Kernel()); @@ -65,7 +62,7 @@ Result CreateSession(Core::System& system, Handle* out_server, Handle* out_clien R_UNLESS(session != nullptr, ResultOutOfResource); // Initialize the session. - session->Initialize(system.Kernel(), nullptr, name); + session->Initialize(nullptr, name); // Commit the session reservation. session_reservation.Commit(); @@ -73,23 +70,23 @@ Result CreateSession(Core::System& system, Handle* out_server, Handle* out_clien // Ensure that we clean up the session (and its only references are handle table) on function // end. SCOPE_EXIT { - session->GetClientSession().Close(system.Kernel()); - session->GetServerSession().Close(system.Kernel()); + session->GetClientSession().Close(); + session->GetServerSession().Close(); }; // Register the session. T::Register(system.Kernel(), session); // Add the server session to the handle table. - R_TRY(handle_table.Add(system.Kernel(), out_server, std::addressof(session->GetServerSession()))); + R_TRY(handle_table.Add(out_server, std::addressof(session->GetServerSession()))); // Ensure that we maintain a clean handle state on exit. ON_RESULT_FAILURE { - handle_table.Remove(system.Kernel(), *out_server); + handle_table.Remove(*out_server); }; // Add the client session to the handle table. - R_RETURN(handle_table.Add(system.Kernel(), out_client, std::addressof(session->GetClientSession()))); + R_RETURN(handle_table.Add(out_client, std::addressof(session->GetClientSession()))); } } // namespace @@ -108,29 +105,29 @@ Result AcceptSession(Core::System& system, Handle* out, Handle port_handle) { auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable(); // Get the server port. - KScopedAutoObject port = handle_table.GetObject(system.Kernel(), port_handle); + KScopedAutoObject port = handle_table.GetObject(port_handle); R_UNLESS(port.IsNotNull(), ResultInvalidHandle); // Reserve an entry for the new session. - R_TRY(handle_table.Reserve(system.Kernel(), out)); + R_TRY(handle_table.Reserve(out)); ON_RESULT_FAILURE { - handle_table.Unreserve(system.Kernel(), *out); + handle_table.Unreserve(*out); }; // Accept the session. KAutoObject* session; - if (port->IsLight(system.Kernel())) { - session = port->AcceptLightSession(system.Kernel()); + if (port->IsLight()) { + session = port->AcceptLightSession(); } else { - session = port->AcceptSession(system.Kernel()); + session = port->AcceptSession(); } // Ensure we accepted successfully. R_UNLESS(session != nullptr, ResultNotFound); // Register the session. - handle_table.Register(system.Kernel(), *out, session); - session->Close(system.Kernel()); + handle_table.Register(*out, session); + session->Close(); R_SUCCEED(); } diff --git a/src/core/hle/kernel/svc/svc_shared_memory.cpp b/src/core/hle/kernel/svc/svc_shared_memory.cpp index 66cf5902ec..3ca07abe8b 100644 --- a/src/core/hle/kernel/svc/svc_shared_memory.cpp +++ b/src/core/hle/kernel/svc/svc_shared_memory.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -49,18 +49,18 @@ Result MapSharedMemory(Core::System& system, Handle shmem_handle, u64 address, u auto& page_table = process.GetPageTable(); // Get the shared memory. - KScopedAutoObject shmem = process.GetHandleTable().GetObject(system.Kernel(), shmem_handle); + KScopedAutoObject shmem = process.GetHandleTable().GetObject(shmem_handle); R_UNLESS(shmem.IsNotNull(), ResultInvalidHandle); // Verify that the mapping is in range. R_UNLESS(page_table.CanContain(address, size, KMemoryState::Shared), ResultInvalidMemoryRegion); // Add the shared memory to the process. - R_TRY(process.AddSharedMemory(system.Kernel(), shmem.GetPointerUnsafe(), address, size)); + R_TRY(process.AddSharedMemory(shmem.GetPointerUnsafe(), address, size)); // Ensure that we clean up the shared memory if we fail to map it. ON_RESULT_FAILURE { - process.RemoveSharedMemory(system.Kernel(), shmem.GetPointerUnsafe(), address, size); + process.RemoveSharedMemory(shmem.GetPointerUnsafe(), address, size); }; // Map the shared memory. @@ -79,7 +79,7 @@ Result UnmapSharedMemory(Core::System& system, Handle shmem_handle, u64 address, auto& page_table = process.GetPageTable(); // Get the shared memory. - KScopedAutoObject shmem = process.GetHandleTable().GetObject(system.Kernel(), shmem_handle); + KScopedAutoObject shmem = process.GetHandleTable().GetObject(shmem_handle); R_UNLESS(shmem.IsNotNull(), ResultInvalidHandle); // Verify that the mapping is in range. @@ -89,7 +89,7 @@ Result UnmapSharedMemory(Core::System& system, Handle shmem_handle, u64 address, R_TRY(shmem->Unmap(process, address, size)); // Remove the shared memory from the process. - process.RemoveSharedMemory(system.Kernel(), shmem.GetPointerUnsafe(), address, size); + process.RemoveSharedMemory(shmem.GetPointerUnsafe(), address, size); R_SUCCEED(); } diff --git a/src/core/hle/kernel/svc/svc_synchronization.cpp b/src/core/hle/kernel/svc/svc_synchronization.cpp index 1b29fd5865..fdd4408d4d 100644 --- a/src/core/hle/kernel/svc/svc_synchronization.cpp +++ b/src/core/hle/kernel/svc/svc_synchronization.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -20,7 +20,7 @@ Result CloseHandle(Core::System& system, Handle handle) { LOG_TRACE(Kernel_SVC, "Closing handle 0x{:08X}", handle); // Remove the handle. - R_UNLESS(GetCurrentProcess(system.Kernel()).GetHandleTable().Remove(system.Kernel(), handle), + R_UNLESS(GetCurrentProcess(system.Kernel()).GetHandleTable().Remove(handle), ResultInvalidHandle); R_SUCCEED(); @@ -35,17 +35,17 @@ Result ResetSignal(Core::System& system, Handle handle) { // Try to reset as readable event. { - KScopedAutoObject readable_event = handle_table.GetObject(system.Kernel(), handle); + KScopedAutoObject readable_event = handle_table.GetObject(handle); if (readable_event.IsNotNull()) { - R_RETURN(readable_event->Reset(system.Kernel())); + R_RETURN(readable_event->Reset()); } } // Try to reset as process. { - KScopedAutoObject process = handle_table.GetObject(system.Kernel(), handle); + KScopedAutoObject process = handle_table.GetObject(handle); if (process.IsNotNull()) { - R_RETURN(process->Reset(system.Kernel())); + R_RETURN(process->Reset()); } } @@ -62,30 +62,35 @@ Result WaitSynchronization(Core::System& system, int32_t* out_index, u64 user_ha R_UNLESS(0 <= num_handles && num_handles <= Svc::ArgumentHandleCountMax, ResultOutOfRange); // Get the synchronization context. - auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable(); - auto objs = GetCurrentThread(system.Kernel()).GetSynchronizationObjectBuffer(); - auto handles = GetCurrentThread(system.Kernel()).GetHandleBuffer(); + auto& kernel = system.Kernel(); + auto& handle_table = GetCurrentProcess(kernel).GetHandleTable(); + auto objs = GetCurrentThread(kernel).GetSynchronizationObjectBuffer(); + auto handles = GetCurrentThread(kernel).GetHandleBuffer(); // Copy user handles. if (num_handles > 0) { // Get the handles. - R_UNLESS(GetCurrentMemory(system.Kernel()).ReadBlock(user_handles, handles.data(), sizeof(Handle) * num_handles), ResultInvalidPointer); + R_UNLESS(GetCurrentMemory(kernel).ReadBlock(user_handles, handles.data(), + sizeof(Handle) * num_handles), + ResultInvalidPointer); // Convert the handles to objects. - R_UNLESS(handle_table.GetMultipleObjects(system.Kernel(), objs.data(), handles.data(), num_handles), ResultInvalidHandle); + R_UNLESS(handle_table.GetMultipleObjects( + objs.data(), handles.data(), num_handles), + ResultInvalidHandle); } // Ensure handles are closed when we're done. SCOPE_EXIT { for (auto i = 0; i < num_handles; ++i) { - objs[i]->Close(system.Kernel()); + objs[i]->Close(); } }; // Convert the timeout from nanoseconds to ticks. s64 timeout; if (timeout_ns > 0) { - u64 ticks = system.Kernel().HardwareTimer().GetTick(); + u64 ticks = kernel.HardwareTimer().GetTick(); ticks += timeout_ns; ticks += 2; @@ -95,7 +100,7 @@ Result WaitSynchronization(Core::System& system, int32_t* out_index, u64 user_ha } // Wait on the objects. - Result res = KSynchronizationObject::Wait(system.Kernel(), out_index, objs.data(), num_handles, timeout); + Result res = KSynchronizationObject::Wait(kernel, out_index, objs.data(), num_handles, timeout); R_SUCCEED_IF(res == ResultSessionClosed); R_RETURN(res); @@ -106,28 +111,31 @@ Result CancelSynchronization(Core::System& system, Handle handle) { LOG_TRACE(Kernel_SVC, "called handle={:#X}", handle); // Get the thread from its handle. - KScopedAutoObject thread = GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(system.Kernel(), handle); + KScopedAutoObject thread = + GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(handle); R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); // Cancel the thread's wait. - thread->WaitCancel(system.Kernel()); + thread->WaitCancel(); R_SUCCEED(); } void SynchronizePreemptionState(Core::System& system) { + auto& kernel = system.Kernel(); + // Lock the scheduler. - KScopedSchedulerLock sl{system.Kernel()}; + KScopedSchedulerLock sl{kernel}; // If the current thread is pinned, unpin it. - KProcess* cur_process = GetCurrentProcessPointer(system.Kernel()); - const auto core_id = GetCurrentCoreId(system.Kernel()); + KProcess* cur_process = GetCurrentProcessPointer(kernel); + const auto core_id = GetCurrentCoreId(kernel); - if (cur_process->GetPinnedThread(core_id) == GetCurrentThreadPointer(system.Kernel())) { + if (cur_process->GetPinnedThread(core_id) == GetCurrentThreadPointer(kernel)) { // Clear the current thread's interrupt flag. - GetCurrentThread(system.Kernel()).ClearInterruptFlag(system.Kernel()); + GetCurrentThread(kernel).ClearInterruptFlag(); // Unpin the current thread. - cur_process->UnpinCurrentThread(system.Kernel()); + cur_process->UnpinCurrentThread(); } } diff --git a/src/core/hle/kernel/svc/svc_thread.cpp b/src/core/hle/kernel/svc/svc_thread.cpp index b1159020d3..1aa6f87c04 100644 --- a/src/core/hle/kernel/svc/svc_thread.cpp +++ b/src/core/hle/kernel/svc/svc_thread.cpp @@ -46,7 +46,7 @@ Result CreateThread(Core::System& system, Handle* out_handle, u64 entry_point, u R_UNLESS(process.CheckThreadPriority(priority), ResultInvalidPriority); // Reserve a new thread from the process resource limit (waiting up to 100ms). - KScopedResourceReservation thread_reservation(system.Kernel(), std::addressof(process), + KScopedResourceReservation thread_reservation(std::addressof(process), LimitableResource::ThreadCountMax, 1, kernel.HardwareTimer().GetTick() + 100000000); R_UNLESS(thread_reservation.Succeeded(), ResultLimitReached); @@ -55,7 +55,7 @@ Result CreateThread(Core::System& system, Handle* out_handle, u64 entry_point, u KThread* thread = KThread::Create(kernel); R_UNLESS(thread != nullptr, ResultOutOfResource) SCOPE_EXIT { - thread->Close(system.Kernel()); + thread->Close(); }; // Initialize the thread. @@ -69,13 +69,13 @@ Result CreateThread(Core::System& system, Handle* out_handle, u64 entry_point, u thread_reservation.Commit(); // Clone the current fpu status to the new thread. - thread->CloneFpuStatus(system.Kernel()); + thread->CloneFpuStatus(); // Register the new thread. KThread::Register(kernel, thread); // Add the thread to the handle table. - R_TRY(process.GetHandleTable().Add(system.Kernel(), out_handle, thread)); + R_TRY(process.GetHandleTable().Add(out_handle, thread)); // Pass the thread handle to the thread local region. process.GetMemory().Write32(GetInteger(thread->GetTlsAddress()) + 0x110, *out_handle); @@ -88,11 +88,12 @@ Result StartThread(Core::System& system, Handle thread_handle) { LOG_DEBUG(Kernel_SVC, "called thread=0x{:08X}", thread_handle); // Get the thread from its handle. - KScopedAutoObject thread = GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(system.Kernel(), thread_handle); + KScopedAutoObject thread = + GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(thread_handle); R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); // Try to start the thread. - R_TRY(thread->Run(system.Kernel())); + R_TRY(thread->Run()); R_SUCCEED(); } @@ -101,7 +102,7 @@ Result StartThread(Core::System& system, Handle thread_handle) { void ExitThread(Core::System& system) { auto* const current_thread = GetCurrentThreadPointer(system.Kernel()); system.GlobalSchedulerContext().RemoveThread(current_thread); - current_thread->Exit(system.Kernel()); + current_thread->Exit(); } /// Sleep the current thread @@ -129,7 +130,7 @@ void SleepThread(Core::System& system, s64 ns) { // Sleep. // NOTE: Nintendo does not check the result of this sleep. - static_cast(GetCurrentThread(kernel).Sleep(kernel, timeout)); + static_cast(GetCurrentThread(kernel).Sleep(timeout)); } else if (yield_type == Svc::YieldType::WithoutCoreMigration) { KScheduler::YieldWithoutCoreMigration(kernel); } else if (yield_type == Svc::YieldType::WithCoreMigration) { @@ -143,23 +144,27 @@ void SleepThread(Core::System& system, s64 ns) { /// Gets the thread context Result GetThreadContext3(Core::System& system, u64 out_context, Handle thread_handle) { - LOG_DEBUG(Kernel_SVC, "called, out_context=0x{:08X}, thread_handle={:#X}", out_context, thread_handle); + LOG_DEBUG(Kernel_SVC, "called, out_context=0x{:08X}, thread_handle={:#X}", out_context, + thread_handle); + + auto& kernel = system.Kernel(); // Get the thread from its handle. - KScopedAutoObject thread = GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(system.Kernel(), thread_handle); + KScopedAutoObject thread = + GetCurrentProcess(kernel).GetHandleTable().GetObject(thread_handle); R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); // Require the handle be to a non-current thread in the current process. - R_UNLESS(thread->GetOwnerProcess() == GetCurrentProcessPointer(system.Kernel()), ResultInvalidHandle); - R_UNLESS(thread.GetPointerUnsafe() != GetCurrentThreadPointer(system.Kernel()), ResultBusy); + R_UNLESS(thread->GetOwnerProcess() == GetCurrentProcessPointer(kernel), ResultInvalidHandle); + R_UNLESS(thread.GetPointerUnsafe() != GetCurrentThreadPointer(kernel), ResultBusy); // Get the thread context. Svc::ThreadContext context{}; - R_TRY(thread->GetThreadContext3(system.Kernel(), std::addressof(context))); + R_TRY(thread->GetThreadContext3(std::addressof(context))); // Copy the thread context to user space. R_UNLESS( - GetCurrentMemory(system.Kernel()).WriteBlock(out_context, std::addressof(context), sizeof(context)), + GetCurrentMemory(kernel).WriteBlock(out_context, std::addressof(context), sizeof(context)), ResultInvalidPointer); R_SUCCEED(); @@ -170,7 +175,8 @@ Result GetThreadPriority(Core::System& system, s32* out_priority, Handle handle) LOG_TRACE(Kernel_SVC, "called"); // Get the thread from its handle. - KScopedAutoObject thread = GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(system.Kernel(), handle); + KScopedAutoObject thread = + GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(handle); R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); // Get the thread's priority. @@ -189,11 +195,11 @@ Result SetThreadPriority(Core::System& system, Handle thread_handle, s32 priorit R_UNLESS(process.CheckThreadPriority(priority), ResultInvalidPriority); // Get the thread from its handle. - KScopedAutoObject thread = process.GetHandleTable().GetObject(system.Kernel(), thread_handle); + KScopedAutoObject thread = process.GetHandleTable().GetObject(thread_handle); R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); // Set the thread priority. - thread->SetBasePriority(system.Kernel(), priority); + thread->SetBasePriority(priority); R_SUCCEED(); } @@ -242,11 +248,12 @@ Result GetThreadCoreMask(Core::System& system, s32* out_core_id, u64* out_affini LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle); // Get the thread from its handle. - KScopedAutoObject thread = GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(system.Kernel(), thread_handle); + KScopedAutoObject thread = + GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(thread_handle); R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); // Get the core mask. - R_RETURN(thread->GetCoreMask(system.Kernel(), out_core_id, out_affinity_mask)); + R_RETURN(thread->GetCoreMask(out_core_id, out_affinity_mask)); } Result SetThreadCoreMask(Core::System& system, Handle thread_handle, s32 core_id, @@ -272,17 +279,18 @@ Result SetThreadCoreMask(Core::System& system, Handle thread_handle, s32 core_id // Get the thread from its handle. KScopedAutoObject thread = - GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(system.Kernel(), thread_handle); + GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(thread_handle); R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); // Set the core mask. - R_RETURN(thread->SetCoreMask(system.Kernel(), core_id, affinity_mask)); + R_RETURN(thread->SetCoreMask(core_id, affinity_mask)); } /// Get the ID for the specified thread. Result GetThreadId(Core::System& system, u64* out_thread_id, Handle thread_handle) { // Get the thread from its handle. - KScopedAutoObject thread = GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(system.Kernel(), thread_handle); + KScopedAutoObject thread = + GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(thread_handle); R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); // Get the thread's id. diff --git a/src/core/hle/kernel/svc/svc_transfer_memory.cpp b/src/core/hle/kernel/svc/svc_transfer_memory.cpp index e539eee911..2ea0d44215 100644 --- a/src/core/hle/kernel/svc/svc_transfer_memory.cpp +++ b/src/core/hle/kernel/svc/svc_transfer_memory.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -46,7 +43,8 @@ Result CreateTransferMemory(Core::System& system, Handle* out, u64 address, u64 auto& handle_table = process.GetHandleTable(); // Reserve a new transfer memory from the process resource limit. - KScopedResourceReservation trmem_reservation(system.Kernel(), std::addressof(process), LimitableResource::TransferMemoryCountMax); + KScopedResourceReservation trmem_reservation(std::addressof(process), + LimitableResource::TransferMemoryCountMax); R_UNLESS(trmem_reservation.Succeeded(), ResultLimitReached); // Create the transfer memory. @@ -55,14 +53,14 @@ Result CreateTransferMemory(Core::System& system, Handle* out, u64 address, u64 // Ensure the only reference is in the handle table when we're done. SCOPE_EXIT { - trmem->Close(system.Kernel()); + trmem->Close(); }; // Ensure that the region is in range. R_UNLESS(process.GetPageTable().Contains(address, size), ResultInvalidCurrentMemory); // Initialize the transfer memory. - R_TRY(trmem->Initialize(system.Kernel(), address, size, map_perm)); + R_TRY(trmem->Initialize(address, size, map_perm)); // Commit the reservation. trmem_reservation.Commit(); @@ -71,7 +69,7 @@ Result CreateTransferMemory(Core::System& system, Handle* out, u64 address, u64 KTransferMemory::Register(kernel, trmem); // Add the transfer memory to the handle table. - R_RETURN(handle_table.Add(system.Kernel(), out, trmem)); + R_RETURN(handle_table.Add(out, trmem)); } Result MapTransferMemory(Core::System& system, Handle trmem_handle, uint64_t address, uint64_t size, @@ -88,7 +86,7 @@ Result MapTransferMemory(Core::System& system, Handle trmem_handle, uint64_t add // Get the transfer memory. KScopedAutoObject trmem = GetCurrentProcess(system.Kernel()) .GetHandleTable() - .GetObject(system.Kernel(), trmem_handle); + .GetObject(trmem_handle); R_UNLESS(trmem.IsNotNull(), ResultInvalidHandle); // Verify that the mapping is in range. @@ -98,7 +96,7 @@ Result MapTransferMemory(Core::System& system, Handle trmem_handle, uint64_t add ResultInvalidMemoryRegion); // Map the transfer memory. - R_TRY(trmem->Map(system.Kernel(), address, size, map_perm)); + R_TRY(trmem->Map(address, size, map_perm)); // We succeeded. R_SUCCEED(); @@ -115,7 +113,7 @@ Result UnmapTransferMemory(Core::System& system, Handle trmem_handle, uint64_t a // Get the transfer memory. KScopedAutoObject trmem = GetCurrentProcess(system.Kernel()) .GetHandleTable() - .GetObject(system.Kernel(), trmem_handle); + .GetObject(trmem_handle); R_UNLESS(trmem.IsNotNull(), ResultInvalidHandle); // Verify that the mapping is in range. @@ -125,7 +123,7 @@ Result UnmapTransferMemory(Core::System& system, Handle trmem_handle, uint64_t a ResultInvalidMemoryRegion); // Unmap the transfer memory. - R_TRY(trmem->Unmap(system.Kernel(), address, size)); + R_TRY(trmem->Unmap(address, size)); R_SUCCEED(); } diff --git a/src/core/hle/service/acc/async_context.cpp b/src/core/hle/service/acc/async_context.cpp index c767e46e8f..c9e0af90ce 100644 --- a/src/core/hle/service/acc/async_context.cpp +++ b/src/core/hle/service/acc/async_context.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -67,7 +64,7 @@ void IAsyncContext::GetResult(HLERequestContext& ctx) { void IAsyncContext::MarkComplete() { is_complete.store(true); - completion_event->Signal(system.Kernel()); + completion_event->Signal(); } } // namespace Service::Account diff --git a/src/core/hle/service/am/applet.cpp b/src/core/hle/service/am/applet.cpp index efedcc5692..2ae3102aff 100644 --- a/src/core/hle/service/am/applet.cpp +++ b/src/core/hle/service/am/applet.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator @@ -52,7 +52,7 @@ void Applet::UpdateSuspensionStateLocked(bool force_message) { // Signal if the focus state was changed or the process state was changed. if (update_requested_focus_state || was_changed || force_message) { - lifecycle_manager.SignalSystemEventIfNeeded(context.kernel); + lifecycle_manager.SignalSystemEventIfNeeded(); } } @@ -76,7 +76,7 @@ void Applet::SetInteractibleLocked(bool interactible) { void Applet::OnProcessTerminatedLocked() { is_completed = true; - state_changed_event.Signal(context.kernel); + state_changed_event.Signal(); } } // namespace Service::AM diff --git a/src/core/hle/service/am/applet_data_broker.cpp b/src/core/hle/service/am/applet_data_broker.cpp index f75baac282..fff78c5afb 100644 --- a/src/core/hle/service/am/applet_data_broker.cpp +++ b/src/core/hle/service/am/applet_data_broker.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -14,23 +11,22 @@ namespace Service::AM { AppletStorageChannel::AppletStorageChannel(KernelHelpers::ServiceContext& context) - : m_event(context) -{} + : m_event(context) {} AppletStorageChannel::~AppletStorageChannel() = default; -void AppletStorageChannel::Push(Kernel::KernelCore& kernel, std::shared_ptr storage) { +void AppletStorageChannel::Push(std::shared_ptr storage) { std::scoped_lock lk{m_lock}; m_data.emplace_back(std::move(storage)); - m_event.Signal(kernel); + m_event.Signal(); } -Result AppletStorageChannel::Pop(Kernel::KernelCore& kernel, std::shared_ptr* out_storage) { +Result AppletStorageChannel::Pop(std::shared_ptr* out_storage) { std::scoped_lock lk{m_lock}; SCOPE_EXIT { if (m_data.empty()) { - m_event.Clear(kernel); + m_event.Clear(); } }; diff --git a/src/core/hle/service/am/applet_data_broker.h b/src/core/hle/service/am/applet_data_broker.h index 36ce8a24d4..2718f608ad 100644 --- a/src/core/hle/service/am/applet_data_broker.h +++ b/src/core/hle/service/am/applet_data_broker.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -25,8 +22,8 @@ public: explicit AppletStorageChannel(KernelHelpers::ServiceContext& ctx); ~AppletStorageChannel(); - void Push(Kernel::KernelCore& kernel, std::shared_ptr storage); - Result Pop(Kernel::KernelCore& kernel, std::shared_ptr* out_storage); + void Push(std::shared_ptr storage); + Result Pop(std::shared_ptr* out_storage); Kernel::KReadableEvent* GetEvent(); private: diff --git a/src/core/hle/service/am/applet_manager.cpp b/src/core/hle/service/am/applet_manager.cpp index 2388faa541..c2920f91ae 100644 --- a/src/core/hle/service/am/applet_manager.cpp +++ b/src/core/hle/service/am/applet_manager.cpp @@ -34,7 +34,8 @@ struct LaunchParameterAccountPreselectedUser { }; static_assert(sizeof(LaunchParameterAccountPreselectedUser) == 0x88); -AppletStorageChannel& InitializeFakeCallerApplet(Core::System& system, std::shared_ptr& applet) { +AppletStorageChannel& InitializeFakeCallerApplet(Core::System& system, + std::shared_ptr& applet) { applet->caller_applet_broker = std::make_shared(system); return applet->caller_applet_broker->GetInData(); } @@ -51,7 +52,7 @@ void PushInShowQlaunch(Core::System& system, AppletStorageChannel& channel) { std::vector argument_data(sizeof(arguments)); std::memcpy(argument_data.data(), &arguments, sizeof(arguments)); - channel.Push(system.Kernel(), std::make_shared(system, std::move(argument_data))); + channel.Push(std::make_shared(system, std::move(argument_data))); } void PushInShowAlbum(Core::System& system, AppletStorageChannel& channel) { @@ -67,8 +68,8 @@ void PushInShowAlbum(Core::System& system, AppletStorageChannel& channel) { std::vector argument_data(sizeof(arguments)); std::vector settings_data{2}; std::memcpy(argument_data.data(), &arguments, sizeof(arguments)); - channel.Push(system.Kernel(), std::make_shared(system, std::move(argument_data))); - channel.Push(system.Kernel(), std::make_shared(system, std::move(settings_data))); + channel.Push(std::make_shared(system, std::move(argument_data))); + channel.Push(std::make_shared(system, std::move(settings_data))); } void PushInShowController(Core::System& system, AppletStorageChannel& channel) { @@ -115,9 +116,9 @@ void PushInShowController(Core::System& system, AppletStorageChannel& channel) { std::memcpy(private_args_data.data(), &private_args, sizeof(private_args)); std::memcpy(user_args_data.data(), &user_args, sizeof(user_args)); - channel.Push(system.Kernel(), std::make_shared(system, std::move(common_args_data))); - channel.Push(system.Kernel(), std::make_shared(system, std::move(private_args_data))); - channel.Push(system.Kernel(), std::make_shared(system, std::move(user_args_data))); + channel.Push(std::make_shared(system, std::move(common_args_data))); + channel.Push(std::make_shared(system, std::move(private_args_data))); + channel.Push(std::make_shared(system, std::move(user_args_data))); } void PushInShowCabinetData(Core::System& system, AppletStorageChannel& channel) { @@ -145,8 +146,8 @@ void PushInShowCabinetData(Core::System& system, AppletStorageChannel& channel) std::vector settings_data(sizeof(amiibo_settings)); std::memcpy(argument_data.data(), &arguments, sizeof(arguments)); std::memcpy(settings_data.data(), &amiibo_settings, sizeof(amiibo_settings)); - channel.Push(system.Kernel(), std::make_shared(system, std::move(argument_data))); - channel.Push(system.Kernel(), std::make_shared(system, std::move(settings_data))); + channel.Push(std::make_shared(system, std::move(argument_data))); + channel.Push(std::make_shared(system, std::move(settings_data))); } void PushInShowMiiEditData(Core::System& system, AppletStorageChannel& channel) { @@ -168,7 +169,7 @@ void PushInShowMiiEditData(Core::System& system, AppletStorageChannel& channel) std::vector argument_data(sizeof(mii_arguments)); std::memcpy(argument_data.data(), &mii_arguments, sizeof(mii_arguments)); - channel.Push(system.Kernel(), std::make_shared(system, std::move(argument_data))); + channel.Push(std::make_shared(system, std::move(argument_data))); } void PushInShowSoftwareKeyboard(Core::System& system, AppletStorageChannel& channel) { @@ -221,9 +222,9 @@ void PushInShowSoftwareKeyboard(Core::System& system, AppletStorageChannel& chan std::memcpy(work_buffer.data(), initial_string.data(), swkbd_config.initial_string_length * sizeof(char16_t)); - channel.Push(system.Kernel(), std::make_shared(system, std::move(argument_data))); - channel.Push(system.Kernel(), std::make_shared(system, std::move(swkbd_data))); - channel.Push(system.Kernel(), std::make_shared(system, std::move(work_buffer))); + channel.Push(std::make_shared(system, std::move(argument_data))); + channel.Push(std::make_shared(system, std::move(swkbd_data))); + channel.Push(std::make_shared(system, std::move(work_buffer))); } } // namespace @@ -267,7 +268,7 @@ void AppletManager::SetWindowSystem(WindowSystem* window_system) { if (Settings::values.enable_overlay && m_window_system->GetOverlayDisplayApplet() == nullptr) { if (auto overlay_process = CreateProcess(m_system, static_cast(AppletProgramId::OverlayDisplay), 0, 0)) { - auto overlay_applet = std::make_shared(m_system, std::make_unique(*std::move(overlay_process)), false); + auto overlay_applet = std::make_shared(m_system, std::move(overlay_process), false); overlay_applet->program_id = static_cast(AppletProgramId::OverlayDisplay); overlay_applet->applet_id = AppletId::OverlayDisplay; overlay_applet->type = AppletType::OverlayApplet; @@ -339,7 +340,7 @@ void AppletManager::SetWindowSystem(WindowSystem* window_system) { } // Applet was started by frontend, so it is foreground. - applet->lifecycle_manager.SetFocusState(m_system.Kernel(), FocusState::InFocus); + applet->lifecycle_manager.SetFocusState(FocusState::InFocus); if (applet->applet_id == AppletId::QLaunch) { applet->lifecycle_manager.SetFocusHandlingMode(false); diff --git a/src/core/hle/service/am/button_poller.cpp b/src/core/hle/service/am/button_poller.cpp index 6999acfa12..069a1934d4 100644 --- a/src/core/hle/service/am/button_poller.cpp +++ b/src/core/hle/service/am/button_poller.cpp @@ -1,11 +1,9 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include -#include "common/thread.h" #include "core/core.h" #include "core/hle/service/am/am_types.h" #include "core/hle/service/am/button_poller.h" @@ -36,15 +34,16 @@ ButtonPressDuration ClassifyPressDuration(std::chrono::steady_clock::time_point } // namespace -ButtonPoller::ButtonPoller(Core::System& system, WindowSystem& window_system) { +ButtonPoller::ButtonPoller(Core::System& system, WindowSystem& window_system) + : m_window_system(window_system) { // TODO: am reads this from the home button state in hid, which is controller-agnostic. Core::HID::ControllerUpdateCallback engine_callback{ - .on_change = [this, &window_system](Core::HID::ControllerTriggerType type) { - if (type == Core::HID::ControllerTriggerType::Button) { - std::unique_lock lk{m_mutex}; - OnButtonStateChanged(window_system); - } - }, + .on_change = + [this](Core::HID::ControllerTriggerType type) { + if (type == Core::HID::ControllerTriggerType::Button) { + this->OnButtonStateChanged(); + } + }, .is_npad_service = true, }; @@ -53,35 +52,25 @@ ButtonPoller::ButtonPoller(Core::System& system, WindowSystem& window_system) { m_player1 = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); m_player1_key = m_player1->SetCallback(engine_callback); - m_thread = std::jthread([this, &window_system](std::stop_token stop_token) { - Common::SetCurrentThreadName("ButtonPoller"); - while (!stop_token.stop_requested()) { - using namespace std::chrono_literals; - std::unique_lock lk{m_mutex}; - m_cv.wait_for(lk, 50ms); - if (stop_token.stop_requested()) - break; - OnButtonStateChanged(window_system); - std::this_thread::sleep_for(5ms); - } - }); + m_thread = std::thread([this] { this->ThreadLoop(); }); } ButtonPoller::~ButtonPoller() { m_handheld->DeleteCallback(m_handheld_key); m_player1->DeleteCallback(m_player1_key); + m_stop = true; m_cv.notify_all(); if (m_thread.joinable()) { - m_thread.request_stop(); m_thread.join(); } } -void ButtonPoller::OnButtonStateChanged(WindowSystem& window_system) { - auto const home_button = m_handheld->GetHomeButtons().home.Value() - || m_player1->GetHomeButtons().home.Value(); - auto const capture_button = m_handheld->GetCaptureButtons().capture.Value() - || m_player1->GetCaptureButtons().capture.Value(); +void ButtonPoller::OnButtonStateChanged() { + std::lock_guard lk{m_mutex}; + const bool home_button = + m_handheld->GetHomeButtons().home.Value() || m_player1->GetHomeButtons().home.Value(); + const bool capture_button = m_handheld->GetCaptureButtons().capture.Value() || + m_player1->GetCaptureButtons().capture.Value(); // Buttons pressed which were not previously pressed if (home_button && !m_home_button_press_start) { @@ -101,7 +90,7 @@ void ButtonPoller::OnButtonStateChanged(WindowSystem& window_system) { if (home_button && m_home_button_press_start && !m_home_button_long_sent) { const auto duration = ClassifyPressDuration(*m_home_button_press_start); if (duration != ButtonPressDuration::ShortPressing) { - window_system.OnSystemButtonPress(SystemButtonType::HomeButtonLongPressing); + m_window_system.OnSystemButtonPress(SystemButtonType::HomeButtonLongPressing); m_home_button_long_sent = true; } } @@ -109,7 +98,7 @@ void ButtonPoller::OnButtonStateChanged(WindowSystem& window_system) { if (capture_button && m_capture_button_press_start && !m_capture_button_long_sent) { const auto duration = ClassifyPressDuration(*m_capture_button_press_start); if (duration != ButtonPressDuration::ShortPressing) { - window_system.OnSystemButtonPress(SystemButtonType::CaptureButtonLongPressing); + m_window_system.OnSystemButtonPress(SystemButtonType::CaptureButtonLongPressing); m_capture_button_long_sent = true; } } @@ -118,8 +107,9 @@ void ButtonPoller::OnButtonStateChanged(WindowSystem& window_system) { if (!home_button && m_home_button_press_start) { if(!m_home_button_long_sent) { const auto duration = ClassifyPressDuration(*m_home_button_press_start); - window_system.OnSystemButtonPress(duration == ButtonPressDuration::ShortPressing - ? SystemButtonType::HomeButtonShortPressing : SystemButtonType::HomeButtonLongPressing); + m_window_system.OnSystemButtonPress( + duration == ButtonPressDuration::ShortPressing ? SystemButtonType::HomeButtonShortPressing + : SystemButtonType::HomeButtonLongPressing); } m_home_button_press_start = std::nullopt; m_home_button_long_sent = false; @@ -127,8 +117,9 @@ void ButtonPoller::OnButtonStateChanged(WindowSystem& window_system) { if (!capture_button && m_capture_button_press_start) { if (!m_capture_button_long_sent) { const auto duration = ClassifyPressDuration(*m_capture_button_press_start); - window_system.OnSystemButtonPress(duration == ButtonPressDuration::ShortPressing - ? SystemButtonType::CaptureButtonShortPressing : SystemButtonType::CaptureButtonLongPressing); + m_window_system.OnSystemButtonPress( + duration == ButtonPressDuration::ShortPressing ? SystemButtonType::CaptureButtonShortPressing + : SystemButtonType::CaptureButtonLongPressing); } m_capture_button_press_start = std::nullopt; m_capture_button_long_sent = false; @@ -139,4 +130,16 @@ void ButtonPoller::OnButtonStateChanged(WindowSystem& window_system) { // } } +void ButtonPoller::ThreadLoop() { + using namespace std::chrono_literals; + std::unique_lock lk{m_mutex}; + while (!m_stop) { + m_cv.wait_for(lk, 50ms); + if (m_stop) break; + lk.unlock(); + OnButtonStateChanged(); + lk.lock(); + } +} + } // namespace Service::AM diff --git a/src/core/hle/service/am/button_poller.h b/src/core/hle/service/am/button_poller.h index 11d147d328..12e7035aa1 100644 --- a/src/core/hle/service/am/button_poller.h +++ b/src/core/hle/service/am/button_poller.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -30,23 +30,31 @@ class ButtonPoller { public: explicit ButtonPoller(Core::System& system, WindowSystem& window_system); ~ButtonPoller(); - void OnButtonStateChanged(WindowSystem& window_system); private: - std::mutex m_mutex; - std::condition_variable m_cv; - std::jthread m_thread; + void OnButtonStateChanged(); + void ThreadLoop(); + +private: + WindowSystem& m_window_system; + + Core::HID::EmulatedController* m_handheld{}; + int m_handheld_key{}; + Core::HID::EmulatedController* m_player1{}; + int m_player1_key{}; + std::optional m_home_button_press_start{}; std::optional m_capture_button_press_start{}; std::optional m_power_button_press_start{}; - Core::HID::EmulatedController* m_handheld{}; - Core::HID::EmulatedController* m_player1{}; - int32_t m_handheld_key{}; - int32_t m_player1_key{}; - bool m_home_button_long_sent : 1 = false; - bool m_capture_button_long_sent : 1 = false; - bool m_power_button_long_sent : 1 = false; + bool m_home_button_long_sent{}; + bool m_capture_button_long_sent{}; + bool m_power_button_long_sent{}; + + std::thread m_thread; + std::atomic m_stop{false}; + std::condition_variable m_cv; + std::mutex m_mutex; }; } // namespace Service::AM diff --git a/src/core/hle/service/am/event_observer.cpp b/src/core/hle/service/am/event_observer.cpp index 32cb35ee30..5d1d303ed3 100644 --- a/src/core/hle/service/am/event_observer.cpp +++ b/src/core/hle/service/am/event_observer.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -18,30 +15,18 @@ enum class UserDataTag : u32 { }; EventObserver::EventObserver(Core::System& system, WindowSystem& window_system) - : m_system(system), m_context(system, "am:EventObserver") - , m_window_system(window_system) - , m_wakeup_event(m_context) - , m_wakeup_holder(m_wakeup_event.GetHandle()) -{ + : m_system(system), m_context(system, "am:EventObserver"), m_window_system(window_system), + m_wakeup_event(m_context), m_wakeup_holder(m_wakeup_event.GetHandle()) { m_window_system.SetEventObserver(this); m_wakeup_holder.SetUserData(static_cast(UserDataTag::WakeupEvent)); m_wakeup_holder.LinkToMultiWait(std::addressof(m_multi_wait)); - m_thread = std::thread([this] { - Common::SetCurrentThreadName("am:EventObserver"); - while (true) { - auto* signaled_holder = this->WaitSignaled(); - if (!signaled_holder) { - break; - } - this->Process(signaled_holder); - } - }); + m_thread = std::thread([&] { this->ThreadFunc(); }); } EventObserver::~EventObserver() { // Signal thread and wait for processing to finish. m_stop_source.request_stop(); - m_wakeup_event.Signal(m_system.Kernel()); + m_wakeup_event.Signal(); m_thread.join(); // Free remaining owned sessions. @@ -76,11 +61,11 @@ void EventObserver::TrackAppletProcess(Applet& applet) { } // Signal wakeup. - m_wakeup_event.Signal(m_system.Kernel()); + m_wakeup_event.Signal(); } void EventObserver::RequestUpdate() { - m_wakeup_event.Signal(m_system.Kernel()); + m_wakeup_event.Signal(); } void EventObserver::LinkDeferred() { @@ -121,7 +106,7 @@ void EventObserver::Process(MultiWaitHolder* holder) { } void EventObserver::OnWakeupEvent(MultiWaitHolder* holder) { - m_wakeup_event.Clear(m_system.Kernel()); + m_wakeup_event.Clear(); // Perform recalculation. m_window_system.Update(); @@ -161,4 +146,17 @@ void EventObserver::DestroyAppletProcessHolderLocked(ProcessHolder* holder) { delete holder; } +void EventObserver::ThreadFunc() { + Common::SetCurrentThreadName("am:EventObserver"); + + while (true) { + auto* signaled_holder = this->WaitSignaled(); + if (!signaled_holder) { + break; + } + + this->Process(signaled_holder); + } +} + } // namespace Service::AM diff --git a/src/core/hle/service/am/event_observer.h b/src/core/hle/service/am/event_observer.h index a0fa13f823..3e52e8494d 100644 --- a/src/core/hle/service/am/event_observer.h +++ b/src/core/hle/service/am/event_observer.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -44,6 +41,9 @@ private: private: void DestroyAppletProcessHolderLocked(ProcessHolder* holder); +private: + void ThreadFunc(); + private: // System reference and context. Core::System& m_system; diff --git a/src/core/hle/service/am/frontend/applet_general.cpp b/src/core/hle/service/am/frontend/applet_general.cpp index 22cad54b66..5345fdec33 100644 --- a/src/core/hle/service/am/frontend/applet_general.cpp +++ b/src/core/hle/service/am/frontend/applet_general.cpp @@ -20,16 +20,16 @@ namespace Service::AM::Frontend { constexpr Result ERROR_INVALID_PIN{ErrorModule::PCTL, 221}; -static void LogCurrentStorage(Kernel::KernelCore& kernel, std::shared_ptr applet, std::string_view prefix) { +static void LogCurrentStorage(std::shared_ptr applet, std::string_view prefix) { std::shared_ptr storage; - while (R_SUCCEEDED(applet->caller_applet_broker->GetInData().Pop(kernel, &storage))) { + while (R_SUCCEEDED(applet->caller_applet_broker->GetInData().Pop(&storage))) { const auto data = storage->GetData(); LOG_INFO(Service_AM, "called (STUBBED), during {} received normal data with size={:08X}, data={}", prefix, data.size(), Common::HexToString(data)); } - while (R_SUCCEEDED(applet->caller_applet_broker->GetInteractiveInData().Pop(kernel, &storage))) { + while (R_SUCCEEDED(applet->caller_applet_broker->GetInteractiveInData().Pop(&storage))) { const auto data = storage->GetData(); LOG_INFO(Service_AM, "called (STUBBED), during {} received interactive data with size={:08X}, data={}", @@ -219,7 +219,7 @@ void StubApplet::Initialize() { LOG_WARNING(Service_AM, "called (STUBBED)"); FrontendApplet::Initialize(); - LogCurrentStorage(system.Kernel(), applet.lock(), "Initialize"); + LogCurrentStorage(applet.lock(), "Initialize"); } Result StubApplet::GetStatus() const { @@ -229,7 +229,7 @@ Result StubApplet::GetStatus() const { void StubApplet::ExecuteInteractive() { LOG_WARNING(Service_AM, "called (STUBBED)"); - LogCurrentStorage(system.Kernel(), applet.lock(), "ExecuteInteractive"); + LogCurrentStorage(applet.lock(), "ExecuteInteractive"); PushOutData(std::make_shared(system, std::vector(0x1000))); PushInteractiveOutData(std::make_shared(system, std::vector(0x1000))); @@ -238,7 +238,7 @@ void StubApplet::ExecuteInteractive() { void StubApplet::Execute() { LOG_WARNING(Service_AM, "called (STUBBED)"); - LogCurrentStorage(system.Kernel(), applet.lock(), "Execute"); + LogCurrentStorage(applet.lock(), "Execute"); PushOutData(std::make_shared(system, std::vector(0x1000))); PushInteractiveOutData(std::make_shared(system, std::vector(0x1000))); diff --git a/src/core/hle/service/am/frontend/applets.cpp b/src/core/hle/service/am/frontend/applets.cpp index 407ca10602..2ff2bcdbb6 100644 --- a/src/core/hle/service/am/frontend/applets.cpp +++ b/src/core/hle/service/am/frontend/applets.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #include @@ -52,22 +52,22 @@ void FrontendApplet::Initialize() { std::shared_ptr FrontendApplet::PopInData() { std::shared_ptr ret; - applet.lock()->caller_applet_broker->GetInData().Pop(system.Kernel(), &ret); + applet.lock()->caller_applet_broker->GetInData().Pop(&ret); return ret; } std::shared_ptr FrontendApplet::PopInteractiveInData() { std::shared_ptr ret; - applet.lock()->caller_applet_broker->GetInteractiveInData().Pop(system.Kernel(), &ret); + applet.lock()->caller_applet_broker->GetInteractiveInData().Pop(&ret); return ret; } void FrontendApplet::PushOutData(std::shared_ptr storage) { - applet.lock()->caller_applet_broker->GetOutData().Push(system.Kernel(), storage); + applet.lock()->caller_applet_broker->GetOutData().Push(storage); } void FrontendApplet::PushInteractiveOutData(std::shared_ptr storage) { - applet.lock()->caller_applet_broker->GetInteractiveOutData().Push(system.Kernel(), storage); + applet.lock()->caller_applet_broker->GetInteractiveOutData().Push(storage); } void FrontendApplet::Exit() { @@ -75,7 +75,7 @@ void FrontendApplet::Exit() { std::scoped_lock lk{applet_->lock}; applet_->is_completed = true; - applet_->state_changed_event.Signal(system.Kernel()); + applet_->state_changed_event.Signal(); } FrontendAppletSet::FrontendAppletSet() = default; diff --git a/src/core/hle/service/am/library_applet_storage.cpp b/src/core/hle/service/am/library_applet_storage.cpp index 8b14511c72..0412c215d5 100644 --- a/src/core/hle/service/am/library_applet_storage.cpp +++ b/src/core/hle/service/am/library_applet_storage.cpp @@ -1,11 +1,7 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include "core/hle/kernel/k_transfer_memory.h" -#include "core/hle/kernel/kernel.h" #include "core/hle/service/am/am_results.h" #include "core/hle/service/am/library_applet_storage.h" #include "core/memory.h" @@ -59,18 +55,15 @@ private: class TransferMemoryLibraryAppletStorage : public LibraryAppletStorage { public: - explicit TransferMemoryLibraryAppletStorage(Kernel::KernelCore& kernel, Core::Memory::Memory& memory, Kernel::KTransferMemory* trmem, bool is_writable, s64 size) - : m_kernel{kernel} - , m_memory(memory) - , m_trmem(trmem) - , m_is_writable(is_writable) - , m_size(size) - { - m_trmem->Open(m_kernel); + explicit TransferMemoryLibraryAppletStorage(Core::Memory::Memory& memory, + Kernel::KTransferMemory* trmem, bool is_writable, + s64 size) + : m_memory(memory), m_trmem(trmem), m_is_writable(is_writable), m_size(size) { + m_trmem->Open(); } ~TransferMemoryLibraryAppletStorage() { - m_trmem->Close(m_kernel); + m_trmem->Close(); m_trmem = nullptr; } @@ -100,7 +93,6 @@ public: } protected: - Kernel::KernelCore& m_kernel; Core::Memory::Memory& m_memory; Kernel::KTransferMemory* m_trmem; bool m_is_writable; @@ -109,9 +101,9 @@ protected: class HandleLibraryAppletStorage : public TransferMemoryLibraryAppletStorage { public: - explicit HandleLibraryAppletStorage(Kernel::KernelCore& kernel, Core::Memory::Memory& memory, Kernel::KTransferMemory* trmem, s64 size) - : TransferMemoryLibraryAppletStorage(kernel, memory, trmem, true, size) - {} + explicit HandleLibraryAppletStorage(Core::Memory::Memory& memory, + Kernel::KTransferMemory* trmem, s64 size) + : TransferMemoryLibraryAppletStorage(memory, trmem, true, size) {} ~HandleLibraryAppletStorage() = default; Kernel::KTransferMemory* GetHandle() override { @@ -133,12 +125,16 @@ std::shared_ptr CreateStorage(std::vector&& data) { return std::make_shared(std::move(data)); } -std::shared_ptr CreateTransferMemoryStorage(Kernel::KernelCore& kernel, Core::Memory::Memory& memory, Kernel::KTransferMemory* trmem, bool is_writable, s64 size) { - return std::make_shared(kernel, memory, trmem, is_writable, size); +std::shared_ptr CreateTransferMemoryStorage(Core::Memory::Memory& memory, + Kernel::KTransferMemory* trmem, + bool is_writable, s64 size) { + return std::make_shared(memory, trmem, is_writable, size); } -std::shared_ptr CreateHandleStorage(Kernel::KernelCore& kernel, Core::Memory::Memory& memory, Kernel::KTransferMemory* trmem, s64 size) { - return std::make_shared(kernel, memory, trmem, size); +std::shared_ptr CreateHandleStorage(Core::Memory::Memory& memory, + Kernel::KTransferMemory* trmem, + s64 size) { + return std::make_shared(memory, trmem, size); } } // namespace Service::AM diff --git a/src/core/hle/service/am/library_applet_storage.h b/src/core/hle/service/am/library_applet_storage.h index cfdbef96d0..7f53f3a9cd 100644 --- a/src/core/hle/service/am/library_applet_storage.h +++ b/src/core/hle/service/am/library_applet_storage.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -13,7 +10,6 @@ class Memory; } namespace Kernel { -class KernelCore; class KTransferMemory; } @@ -31,7 +27,10 @@ public: }; std::shared_ptr CreateStorage(std::vector&& data); -std::shared_ptr CreateTransferMemoryStorage(Kernel::KernelCore& kernel, Core::Memory::Memory& memory, Kernel::KTransferMemory* trmem, bool is_writable, s64 size); -std::shared_ptr CreateHandleStorage(Kernel::KernelCore& kernel, Core::Memory::Memory& memory, Kernel::KTransferMemory* trmem, s64 size); +std::shared_ptr CreateTransferMemoryStorage(Core::Memory::Memory& memory, + Kernel::KTransferMemory* trmem, + bool is_writable, s64 size); +std::shared_ptr CreateHandleStorage(Core::Memory::Memory& memory, + Kernel::KTransferMemory* trmem, s64 size); } // namespace Service::AM diff --git a/src/core/hle/service/am/lifecycle_manager.cpp b/src/core/hle/service/am/lifecycle_manager.cpp index 8d6965a06c..a79ef6f5f5 100644 --- a/src/core/hle/service/am/lifecycle_manager.cpp +++ b/src/core/hle/service/am/lifecycle_manager.cpp @@ -28,9 +28,9 @@ Event& LifecycleManager::GetHDCPStateChangedEvent() { return m_hdcp_state_changed_event; } -void LifecycleManager::PushUnorderedMessage(Kernel::KernelCore& kernel, AppletMessage message) { +void LifecycleManager::PushUnorderedMessage(AppletMessage message) { m_unordered_messages.push_back(message); - this->SignalSystemEventIfNeeded(kernel); + this->SignalSystemEventIfNeeded(); } AppletMessage LifecycleManager::PopMessageInOrderOfPriority() { @@ -144,36 +144,36 @@ bool LifecycleManager::ShouldSignalSystemEvent() { m_has_album_screen_shot_taken || m_has_album_recording_saved; } -void LifecycleManager::OnOperationAndPerformanceModeChanged(Kernel::KernelCore& kernel) { +void LifecycleManager::OnOperationAndPerformanceModeChanged() { if (m_operation_mode_changed_notification_enabled) { m_has_operation_mode_changed = true; } if (m_performance_mode_changed_notification_enabled) { m_has_performance_mode_changed = true; } - m_operation_mode_changed_system_event.Signal(kernel); - this->SignalSystemEventIfNeeded(kernel); + m_operation_mode_changed_system_event.Signal(); + this->SignalSystemEventIfNeeded(); } -void LifecycleManager::SignalSystemEventIfNeeded(Kernel::KernelCore& kernel) { +void LifecycleManager::SignalSystemEventIfNeeded() { // Check our cached value for the system event. const bool applet_message_available = m_applet_message_available; // If it's not current, we need to do an update, either clearing or signaling. if (applet_message_available != this->ShouldSignalSystemEvent()) { if (!applet_message_available) { - m_system_event.Signal(kernel); + m_system_event.Signal(); m_applet_message_available = true; } else { - m_system_event.Clear(kernel); + m_system_event.Clear(); m_applet_message_available = false; } } } -bool LifecycleManager::PopMessage(Kernel::KernelCore& kernel, AppletMessage* out_message) { +bool LifecycleManager::PopMessage(AppletMessage* out_message) { const auto message = this->PopMessageInOrderOfPriority(); - this->SignalSystemEventIfNeeded(kernel); + this->SignalSystemEventIfNeeded(); *out_message = message; return message != AppletMessage::None; diff --git a/src/core/hle/service/am/lifecycle_manager.h b/src/core/hle/service/am/lifecycle_manager.h index 615aeed591..a1ddb9e2df 100644 --- a/src/core/hle/service/am/lifecycle_manager.h +++ b/src/core/hle/service/am/lifecycle_manager.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -69,17 +66,17 @@ public: return m_acknowledged_focus_state; } - void SetFocusState(Kernel::KernelCore& kernel, FocusState state) { + void SetFocusState(FocusState state) { if (m_requested_focus_state != state) { m_has_focus_state_changed = true; } m_requested_focus_state = state; - this->SignalSystemEventIfNeeded(kernel); + this->SignalSystemEventIfNeeded(); } - void RequestExit(Kernel::KernelCore& kernel) { + void RequestExit() { m_has_requested_exit = true; - this->SignalSystemEventIfNeeded(kernel); + this->SignalSystemEventIfNeeded(); } void RequestResumeNotification() { @@ -92,22 +89,22 @@ public: } } - void OnOperationAndPerformanceModeChanged(Kernel::KernelCore& kernel); + void OnOperationAndPerformanceModeChanged(); public: - void SetFocusStateChangedNotificationEnabled(Kernel::KernelCore& kernel, bool enabled) { + void SetFocusStateChangedNotificationEnabled(bool enabled) { m_focus_state_changed_notification_enabled = enabled; - this->SignalSystemEventIfNeeded(kernel); + this->SignalSystemEventIfNeeded(); } - void SetOperationModeChangedNotificationEnabled(Kernel::KernelCore& kernel, bool enabled) { + void SetOperationModeChangedNotificationEnabled(bool enabled) { m_operation_mode_changed_notification_enabled = enabled; - this->SignalSystemEventIfNeeded(kernel); + this->SignalSystemEventIfNeeded(); } - void SetPerformanceModeChangedNotificationEnabled(Kernel::KernelCore& kernel, bool enabled) { + void SetPerformanceModeChangedNotificationEnabled(bool enabled) { m_performance_mode_changed_notification_enabled = enabled; - this->SignalSystemEventIfNeeded(kernel); + this->SignalSystemEventIfNeeded(); } void SetResumeNotificationEnabled(bool enabled) { @@ -132,11 +129,11 @@ public: void RemoveForceResumeIfPossible(); bool IsRunnable() const; bool UpdateRequestedFocusState(); - void SignalSystemEventIfNeeded(Kernel::KernelCore& kernel); + void SignalSystemEventIfNeeded(); public: - void PushUnorderedMessage(Kernel::KernelCore& kernel, AppletMessage message); - bool PopMessage(Kernel::KernelCore& kernel, AppletMessage* out_message); + void PushUnorderedMessage(AppletMessage message); + bool PopMessage(AppletMessage* out_message); private: FocusState GetFocusStateWhileForegroundObscured() const; diff --git a/src/core/hle/service/am/process_creation.cpp b/src/core/hle/service/am/process_creation.cpp index e34e86a82c..b5e31353a2 100644 --- a/src/core/hle/service/am/process_creation.cpp +++ b/src/core/hle/service/am/process_creation.cpp @@ -1,10 +1,6 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include #include "core/core.h" #include "core/file_sys/content_archive.h" #include "core/file_sys/nca_metadata.h" @@ -20,7 +16,7 @@ namespace Service::AM { namespace { -[[nodiscard]] FileSys::StorageId GetStorageIdForFrontendSlot( +FileSys::StorageId GetStorageIdForFrontendSlot( std::optional slot) { if (!slot.has_value()) { return FileSys::StorageId::None; @@ -40,23 +36,31 @@ namespace { } } -[[nodiscard]] inline std::optional CreateProcessImpl(std::unique_ptr& out_loader, Loader::ResultStatus& out_load_result, Core::System& system, FileSys::VirtualFile file, u64 program_id, u64 program_index) { +std::unique_ptr CreateProcessImpl(std::unique_ptr& out_loader, + Loader::ResultStatus& out_load_result, + Core::System& system, FileSys::VirtualFile file, + u64 program_id, u64 program_index) { // Get the appropriate loader to parse this NCA. out_loader = Loader::GetLoader(system, file, program_id, program_index); + // Ensure we have a loader which can parse the NCA. - if (out_loader) { - // Try to load the process. - auto process = std::make_optional(system); - if (process->Initialize(*out_loader, out_load_result)) { - return process; - } + if (!out_loader) { + return nullptr; } - return std::nullopt; + + // Try to load the process. + auto process = std::make_unique(system); + if (process->Initialize(*out_loader, out_load_result)) { + return process; + } + + return nullptr; } } // Anonymous namespace -std::optional CreateProcess(Core::System& system, u64 program_id, u8 minimum_key_generation, u8 maximum_key_generation) { +std::unique_ptr CreateProcess(Core::System& system, u64 program_id, + u8 minimum_key_generation, u8 maximum_key_generation) { // Attempt to load program NCA. FileSys::VirtualFile nca_raw{}; @@ -66,7 +70,7 @@ std::optional CreateProcess(Core::System& system, u64 program_id, u8 mi // Ensure we retrieved a program NCA. if (!nca_raw) { - return std::nullopt; + return nullptr; } // Ensure we have a suitable version. @@ -75,8 +79,9 @@ std::optional CreateProcess(Core::System& system, u64 program_id, u8 mi if (nca.GetStatus() == Loader::ResultStatus::Success && (nca.GetKeyGeneration() < minimum_key_generation || nca.GetKeyGeneration() > maximum_key_generation)) { - LOG_WARNING(Service_LDR, "Skipping program {:016X} with generation {}", program_id, nca.GetKeyGeneration()); - return std::nullopt; + LOG_WARNING(Service_LDR, "Skipping program {:016X} with generation {}", program_id, + nca.GetKeyGeneration()); + return nullptr; } } @@ -85,32 +90,42 @@ std::optional CreateProcess(Core::System& system, u64 program_id, u8 mi return CreateProcessImpl(loader, status, system, nca_raw, program_id, 0); } -std::optional CreateApplicationProcess(std::vector& out_control, std::unique_ptr& out_loader, Loader::ResultStatus& out_load_result, Core::System& system, FileSys::VirtualFile file, u64 program_id, u64 program_index) { - if (auto process = CreateProcessImpl(out_loader, out_load_result, system, file, program_id, program_index); process) { - FileSys::NACP nacp; - if (out_loader->ReadControlData(nacp) == Loader::ResultStatus::Success) { - out_control = nacp.GetRawBytes(); - } else { - out_control.resize(sizeof(FileSys::RawNACP)); - std::fill(out_control.begin(), out_control.end(), (u8) 0); - } - - auto& storage = system.GetContentProviderUnion(); - Service::Glue::ApplicationLaunchProperty launch{}; - launch.title_id = process->GetProgramId(); - - FileSys::PatchManager pm{launch.title_id, system.GetFileSystemController(), storage}; - launch.version = pm.GetGameVersion().value_or(0); - - // TODO(DarkLordZach): When FSController/Game Card Support is added, if - // current_process_game_card use correct StorageId - launch.base_game_storage_id = GetStorageIdForFrontendSlot(storage.GetSlotForEntry(launch.title_id, FileSys::ContentRecordType::Program)); - launch.update_storage_id = GetStorageIdForFrontendSlot(storage.GetSlotForEntry(FileSys::GetUpdateTitleID(launch.title_id), FileSys::ContentRecordType::Program)); - - system.GetARPManager().Register(launch.title_id, launch, out_control); - return process; +std::unique_ptr CreateApplicationProcess(std::vector& out_control, + std::unique_ptr& out_loader, + Loader::ResultStatus& out_load_result, + Core::System& system, FileSys::VirtualFile file, + u64 program_id, u64 program_index) { + auto process = + CreateProcessImpl(out_loader, out_load_result, system, file, program_id, program_index); + if (!process) { + return nullptr; } - return std::nullopt; + + FileSys::NACP nacp; + if (out_loader->ReadControlData(nacp) == Loader::ResultStatus::Success) { + out_control = nacp.GetRawBytes(); + } else { + out_control.resize(sizeof(FileSys::RawNACP)); + std::fill(out_control.begin(), out_control.end(), (u8) 0); + } + + auto& storage = system.GetContentProviderUnion(); + Service::Glue::ApplicationLaunchProperty launch{}; + launch.title_id = process->GetProgramId(); + + FileSys::PatchManager pm{launch.title_id, system.GetFileSystemController(), storage}; + launch.version = pm.GetGameVersion().value_or(0); + + // TODO(DarkLordZach): When FSController/Game Card Support is added, if + // current_process_game_card use correct StorageId + launch.base_game_storage_id = GetStorageIdForFrontendSlot( + storage.GetSlotForEntry(launch.title_id, FileSys::ContentRecordType::Program)); + launch.update_storage_id = GetStorageIdForFrontendSlot(storage.GetSlotForEntry( + FileSys::GetUpdateTitleID(launch.title_id), FileSys::ContentRecordType::Program)); + + system.GetARPManager().Register(launch.title_id, launch, out_control); + + return process; } } // namespace Service::AM diff --git a/src/core/hle/service/am/process_creation.h b/src/core/hle/service/am/process_creation.h index 57d8b8f815..8cfb9e0c9e 100644 --- a/src/core/hle/service/am/process_creation.h +++ b/src/core/hle/service/am/process_creation.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -27,7 +24,12 @@ class Process; namespace Service::AM { -std::optional CreateProcess(Core::System& system, u64 program_id, u8 minimum_key_generation, u8 maximum_key_generation); -std::optional CreateApplicationProcess(std::vector& out_control, std::unique_ptr& out_loader, Loader::ResultStatus& out_load_result, Core::System& system, FileSys::VirtualFile file, u64 program_id, u64 program_index); +std::unique_ptr CreateProcess(Core::System& system, u64 program_id, + u8 minimum_key_generation, u8 maximum_key_generation); +std::unique_ptr CreateApplicationProcess(std::vector& out_control, + std::unique_ptr& out_loader, + Loader::ResultStatus& out_load_result, + Core::System& system, FileSys::VirtualFile file, + u64 program_id, u64 program_index); } // namespace Service::AM diff --git a/src/core/hle/service/am/service/application_accessor.cpp b/src/core/hle/service/am/service/application_accessor.cpp index f357871706..88a1724fc6 100644 --- a/src/core/hle/service/am/service/application_accessor.cpp +++ b/src/core/hle/service/am/service/application_accessor.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -69,7 +69,7 @@ Result IApplicationAccessor::RequestExit() { std::scoped_lock lk{m_applet->lock}; if (m_applet->exit_locked) { - m_applet->lifecycle_manager.RequestExit(system.Kernel()); + m_applet->lifecycle_manager.RequestExit(); m_applet->UpdateSuspensionStateLocked(true); } else { m_applet->process->Terminate(); diff --git a/src/core/hle/service/am/service/application_creator.cpp b/src/core/hle/service/am/service/application_creator.cpp index 983ac700bc..81620a5067 100644 --- a/src/core/hle/service/am/service/application_creator.cpp +++ b/src/core/hle/service/am/service/application_creator.cpp @@ -21,7 +21,8 @@ namespace Service::AM { namespace { -Result CreateGuestApplication(SharedPointer* out_application_accessor, Core::System& system, WindowSystem& window_system, u64 program_id) { +Result CreateGuestApplication(SharedPointer* out_application_accessor, + Core::System& system, WindowSystem& window_system, u64 program_id) { FileSys::VirtualFile nca_raw{}; // Get the program NCA from storage. @@ -34,10 +35,11 @@ Result CreateGuestApplication(SharedPointer* out_applicati std::vector control; std::unique_ptr loader; Loader::ResultStatus result; - auto process = CreateApplicationProcess(control, loader, result, system, nca_raw, program_id, 0); - R_UNLESS(process != std::nullopt, ResultUnknown); + auto process = + CreateApplicationProcess(control, loader, result, system, nca_raw, program_id, 0); + R_UNLESS(process != nullptr, ResultUnknown); - const auto applet = std::make_shared(system, std::make_unique(*std::move(process)), true); + const auto applet = std::make_shared(system, std::move(process), true); applet->program_id = program_id; applet->applet_id = AppletId::Application; applet->type = AppletType::Application; @@ -45,7 +47,8 @@ Result CreateGuestApplication(SharedPointer* out_applicati window_system.TrackApplet(applet, true); - *out_application_accessor = std::make_shared(system, applet, window_system); + *out_application_accessor = + std::make_shared(system, applet, window_system); R_SUCCEED(); } @@ -87,10 +90,12 @@ Result IApplicationCreator::CreateSystemApplication( std::vector control; std::unique_ptr loader; - auto process = CreateProcess(system, application_id, 1, 22); - R_UNLESS(process != std::nullopt, ResultUnknown); - const auto applet = std::make_shared(system, std::make_unique(*std::move(process)), true); + auto process = + CreateProcess(system, application_id, 1, 22); + R_UNLESS(process != nullptr, ResultUnknown); + + const auto applet = std::make_shared(system, std::move(process), true); applet->program_id = application_id; applet->applet_id = AppletId::Starter; applet->type = AppletType::LibraryApplet; @@ -98,7 +103,8 @@ Result IApplicationCreator::CreateSystemApplication( m_window_system.TrackApplet(applet, true); - *out_application_accessor = std::make_shared(system, applet, m_window_system); + *out_application_accessor = + std::make_shared(system, applet, m_window_system); Core::LaunchTimestampCache::SaveLaunchTimestamp(application_id); R_SUCCEED(); } diff --git a/src/core/hle/service/am/service/common_state_getter.cpp b/src/core/hle/service/am/service/common_state_getter.cpp index 23f67dcf17..5b5e21b8e0 100644 --- a/src/core/hle/service/am/service/common_state_getter.cpp +++ b/src/core/hle/service/am/service/common_state_getter.cpp @@ -99,7 +99,7 @@ Result ICommonStateGetter::GetEventHandle(OutCopyHandle Result ICommonStateGetter::ReceiveMessage(Out out_applet_message) { LOG_DEBUG(Service_AM, "called"); - if (!m_applet->lifecycle_manager.PopMessage(system.Kernel(), out_applet_message)) { + if (!m_applet->lifecycle_manager.PopMessage(out_applet_message)) { LOG_ERROR(Service_AM, "Tried to pop message but none was available!"); R_THROW(AM::ResultNoMessages); } @@ -123,21 +123,21 @@ Result ICommonStateGetter::RequestToAcquireSleepLock() { LOG_WARNING(Service_AM, "(STUBBED) called"); // Sleep lock is acquired immediately. - m_applet->sleep_lock_event.Signal(system.Kernel()); + m_applet->sleep_lock_event.Signal(); R_SUCCEED(); } Result ICommonStateGetter::ReleaseSleepLock() { LOG_WARNING(Service_AM, "(STUBBED) called"); - m_applet->sleep_lock_event.Clear(system.Kernel()); + m_applet->sleep_lock_event.Clear(); R_SUCCEED(); } Result ICommonStateGetter::ReleaseSleepLockTransiently() { LOG_WARNING(Service_AM, "(STUBBED) called"); - m_applet->sleep_lock_event.Clear(system.Kernel()); + m_applet->sleep_lock_event.Clear(); R_SUCCEED(); } @@ -281,25 +281,25 @@ Result ICommonStateGetter::PerformSystemButtonPressingIfInFocus(SystemButtonType switch (type) { case SystemButtonType::HomeButtonShortPressing: if (!m_applet->home_button_short_pressed_blocked) { - m_applet->lifecycle_manager.PushUnorderedMessage(system.Kernel(), + m_applet->lifecycle_manager.PushUnorderedMessage( AppletMessage::DetectShortPressingHomeButton); } break; case SystemButtonType::HomeButtonLongPressing: if (!m_applet->home_button_long_pressed_blocked) { - m_applet->lifecycle_manager.PushUnorderedMessage(system.Kernel(), + m_applet->lifecycle_manager.PushUnorderedMessage( AppletMessage::DetectLongPressingHomeButton); } break; case SystemButtonType::CaptureButtonShortPressing: if (m_applet->handling_capture_button_short_pressed_message_enabled_for_applet) { - m_applet->lifecycle_manager.PushUnorderedMessage(system.Kernel(), + m_applet->lifecycle_manager.PushUnorderedMessage( AppletMessage::DetectShortPressingCaptureButton); } break; case SystemButtonType::CaptureButtonLongPressing: if (m_applet->handling_capture_button_long_pressed_message_enabled_for_applet) { - m_applet->lifecycle_manager.PushUnorderedMessage(system.Kernel(), + m_applet->lifecycle_manager.PushUnorderedMessage( AppletMessage::DetectLongPressingCaptureButton); } break; diff --git a/src/core/hle/service/am/service/library_applet_accessor.cpp b/src/core/hle/service/am/service/library_applet_accessor.cpp index 366a26de0a..ef91f69c23 100644 --- a/src/core/hle/service/am/service/library_applet_accessor.cpp +++ b/src/core/hle/service/am/service/library_applet_accessor.cpp @@ -123,7 +123,7 @@ Result ILibraryAppletAccessor::RequestExit() { LOG_DEBUG(Service_AM, "called"); { std::scoped_lock lk{m_applet->lock}; - m_applet->lifecycle_manager.RequestExit(system.Kernel()); + m_applet->lifecycle_manager.RequestExit(); } FrontendRequestExit(); R_SUCCEED(); @@ -157,7 +157,7 @@ Result ILibraryAppletAccessor::PushInData(SharedPointer storage) { } } - m_broker->GetInData().Push(system.Kernel(), storage); + m_broker->GetInData().Push(storage); R_SUCCEED(); } @@ -165,13 +165,13 @@ Result ILibraryAppletAccessor::PopOutData(Out> out_stora LOG_DEBUG(Service_AM, "called"); if (auto caller_applet = m_applet->caller_applet.lock(); caller_applet) { - caller_applet->lifecycle_manager.GetSystemEvent().Signal(system.Kernel()); + caller_applet->lifecycle_manager.GetSystemEvent().Signal(); caller_applet->lifecycle_manager.RequestResumeNotification(); - caller_applet->lifecycle_manager.GetSystemEvent().Clear(system.Kernel()); + caller_applet->lifecycle_manager.GetSystemEvent().Clear(); caller_applet->lifecycle_manager.UpdateRequestedFocusState(); } - R_TRY(m_broker->GetOutData().Pop(system.Kernel(), out_storage.Get())); + R_TRY(m_broker->GetOutData().Pop(out_storage.Get())); if (m_applet->applet_id == AppletId::ProfileSelect && *out_storage) { auto impl = (*out_storage)->GetImpl(); @@ -186,14 +186,14 @@ Result ILibraryAppletAccessor::PopOutData(Out> out_stora Result ILibraryAppletAccessor::PushInteractiveInData(SharedPointer storage) { LOG_DEBUG(Service_AM, "called"); - m_broker->GetInteractiveInData().Push(system.Kernel(), storage); + m_broker->GetInteractiveInData().Push(storage); FrontendExecuteInteractive(); R_SUCCEED(); } Result ILibraryAppletAccessor::PopInteractiveOutData(Out> out_storage) { LOG_DEBUG(Service_AM, "called"); - R_RETURN(m_broker->GetInteractiveOutData().Pop(system.Kernel(), out_storage.Get())); + R_RETURN(m_broker->GetInteractiveOutData().Pop(out_storage.Get())); } Result ILibraryAppletAccessor::GetPopOutDataEvent(OutCopyHandle out_event) { diff --git a/src/core/hle/service/am/service/library_applet_creator.cpp b/src/core/hle/service/am/service/library_applet_creator.cpp index 92c9fd4ad9..3de5740237 100644 --- a/src/core/hle/service/am/service/library_applet_creator.cpp +++ b/src/core/hle/service/am/service/library_applet_creator.cpp @@ -122,23 +122,26 @@ std::shared_ptr CreateGuestApplet(Core::System& system, }; auto process = CreateProcess(system, program_id, Firmware1400, Firmware2200); - if (process) { - const auto applet = std::make_shared(system, std::make_unique(*std::move(process)), false); - applet->program_id = program_id; - applet->applet_id = applet_id; - applet->type = AppletType::LibraryApplet; - applet->library_applet_mode = mode; - applet->window_visible = mode != LibraryAppletMode::AllForegroundInitiallyHidden; - - auto broker = std::make_shared(system); - applet->caller_applet = caller_applet; - applet->caller_applet_broker = broker; - caller_applet->child_applets.push_back(applet); - window_system.TrackApplet(applet, false); - return std::make_shared(system, broker, applet); + if (!process) { + // Couldn't initialize the guest process + return {}; } - // Couldn't initialize the guest process - return {}; + + const auto applet = std::make_shared(system, std::move(process), false); + applet->program_id = program_id; + applet->applet_id = applet_id; + applet->type = AppletType::LibraryApplet; + applet->library_applet_mode = mode; + applet->window_visible = mode != LibraryAppletMode::AllForegroundInitiallyHidden; + + auto broker = std::make_shared(system); + applet->caller_applet = caller_applet; + applet->caller_applet_broker = broker; + caller_applet->child_applets.push_back(applet); + + window_system.TrackApplet(applet, false); + + return std::make_shared(system, broker, applet); } std::shared_ptr CreateFrontendApplet(Core::System& system, @@ -207,7 +210,7 @@ Result ILibraryAppletCreator::CreateLibraryApplet( } // Applet is created, can now be launched. - m_applet->library_applet_launchable_event.Signal(system.Kernel()); + m_applet->library_applet_launchable_event.Signal(); *out_library_applet_accessor = library_applet; R_SUCCEED(); } @@ -233,7 +236,7 @@ Result ILibraryAppletCreator::CreateLibraryAppletEx( } // Applet is created, can now be launched. - m_applet->library_applet_launchable_event.Signal(system.Kernel()); + m_applet->library_applet_launchable_event.Signal(); *out_library_applet_accessor = library_applet; R_SUCCEED(); } @@ -266,7 +269,7 @@ Result ILibraryAppletCreator::CreateTransferMemoryStorage( } *out_storage = std::make_shared( - system, AM::CreateTransferMemoryStorage(system.Kernel(), transfer_memory_handle->GetOwner()->GetMemory(), + system, AM::CreateTransferMemoryStorage(transfer_memory_handle->GetOwner()->GetMemory(), transfer_memory_handle.Get(), is_writable, size)); R_SUCCEED(); } @@ -287,7 +290,7 @@ Result ILibraryAppletCreator::CreateHandleStorage( } *out_storage = std::make_shared( - system, AM::CreateHandleStorage(system.Kernel(), transfer_memory_handle->GetOwner()->GetMemory(), + system, AM::CreateHandleStorage(transfer_memory_handle->GetOwner()->GetMemory(), transfer_memory_handle.Get(), size)); R_SUCCEED(); } diff --git a/src/core/hle/service/am/service/library_applet_self_accessor.cpp b/src/core/hle/service/am/service/library_applet_self_accessor.cpp index 473a4bc955..4a1d1f97d3 100644 --- a/src/core/hle/service/am/service/library_applet_self_accessor.cpp +++ b/src/core/hle/service/am/service/library_applet_self_accessor.cpp @@ -93,23 +93,23 @@ ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default; Result ILibraryAppletSelfAccessor::PopInData(Out> out_storage) { LOG_INFO(Service_AM, "called"); - R_RETURN(m_broker->GetInData().Pop(system.Kernel(), out_storage)); + R_RETURN(m_broker->GetInData().Pop(out_storage)); } Result ILibraryAppletSelfAccessor::PushOutData(SharedPointer storage) { LOG_INFO(Service_AM, "called"); - m_broker->GetOutData().Push(system.Kernel(), storage); + m_broker->GetOutData().Push(storage); R_SUCCEED(); } Result ILibraryAppletSelfAccessor::PopInteractiveInData(Out> out_storage) { LOG_INFO(Service_AM, "called"); - R_RETURN(m_broker->GetInteractiveInData().Pop(system.Kernel(), out_storage)); + R_RETURN(m_broker->GetInteractiveInData().Pop(out_storage)); } Result ILibraryAppletSelfAccessor::PushInteractiveOutData(SharedPointer storage) { LOG_INFO(Service_AM, "called"); - m_broker->GetInteractiveOutData().Push(system.Kernel(), storage); + m_broker->GetInteractiveOutData().Push(storage); R_SUCCEED(); } diff --git a/src/core/hle/service/am/service/lock_accessor.cpp b/src/core/hle/service/am/service/lock_accessor.cpp index 0341254449..8e556fdd68 100644 --- a/src/core/hle/service/am/service/lock_accessor.cpp +++ b/src/core/hle/service/am/service/lock_accessor.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -23,7 +20,7 @@ ILockAccessor::ILockAccessor(Core::System& system_) RegisterHandlers(functions); - m_event.Signal(system.Kernel()); + m_event.Signal(); } ILockAccessor::~ILockAccessor() = default; @@ -58,7 +55,7 @@ Result ILockAccessor::Unlock() { m_is_locked = false; } - m_event.Signal(system.Kernel()); + m_event.Signal(); R_SUCCEED(); } diff --git a/src/core/hle/service/am/service/self_controller.cpp b/src/core/hle/service/am/service/self_controller.cpp index 4279483727..89e393bb97 100644 --- a/src/core/hle/service/am/service/self_controller.cpp +++ b/src/core/hle/service/am/service/self_controller.cpp @@ -151,7 +151,7 @@ Result ISelfController::GetLibraryAppletLaunchableEvent( OutCopyHandle out_event) { LOG_WARNING(Service_AM, "(STUBBED) called"); - m_applet->library_applet_launchable_event.Signal(system.Kernel()); + m_applet->library_applet_launchable_event.Signal(); *out_event = m_applet->library_applet_launchable_event.GetHandle(); R_SUCCEED(); @@ -170,7 +170,7 @@ Result ISelfController::SetOperationModeChangedNotification(bool enabled) { LOG_INFO(Service_AM, "called, enabled={}", enabled); std::scoped_lock lk{m_applet->lock}; - m_applet->lifecycle_manager.SetOperationModeChangedNotificationEnabled(system.Kernel(), enabled); + m_applet->lifecycle_manager.SetOperationModeChangedNotificationEnabled(enabled); R_SUCCEED(); } @@ -179,7 +179,7 @@ Result ISelfController::SetPerformanceModeChangedNotification(bool enabled) { LOG_INFO(Service_AM, "called, enabled={}", enabled); std::scoped_lock lk{m_applet->lock}; - m_applet->lifecycle_manager.SetPerformanceModeChangedNotificationEnabled(system.Kernel(), enabled); + m_applet->lifecycle_manager.SetPerformanceModeChangedNotificationEnabled(enabled); R_SUCCEED(); } @@ -188,7 +188,7 @@ Result ISelfController::SetFocusHandlingMode(bool notify, bool background, bool LOG_INFO(Service_AM, "called, notify={} background={} suspend={}", notify, background, suspend); std::scoped_lock lk{m_applet->lock}; - m_applet->lifecycle_manager.SetFocusStateChangedNotificationEnabled(system.Kernel(), notify); + m_applet->lifecycle_manager.SetFocusStateChangedNotificationEnabled(notify); m_applet->lifecycle_manager.SetFocusHandlingMode(suspend); m_applet->UpdateSuspensionStateLocked(true); diff --git a/src/core/hle/service/am/window_system.cpp b/src/core/hle/service/am/window_system.cpp index 90115d73be..5f20a98322 100644 --- a/src/core/hle/service/am/window_system.cpp +++ b/src/core/hle/service/am/window_system.cpp @@ -154,7 +154,7 @@ void WindowSystem::OnOperationModeChanged() { for (const auto& [aruid, applet] : m_applets) { std::scoped_lock lk2{applet->lock}; - applet->lifecycle_manager.OnOperationAndPerformanceModeChanged(m_system.Kernel()); + applet->lifecycle_manager.OnOperationAndPerformanceModeChanged(); } } @@ -163,22 +163,22 @@ void WindowSystem::OnExitRequested() { for (const auto& [aruid, applet] : m_applets) { std::scoped_lock lk2{applet->lock}; - applet->lifecycle_manager.RequestExit(m_system.Kernel()); + applet->lifecycle_manager.RequestExit(); } } void WindowSystem::SendButtonAppletMessageLocked(AppletMessage message) { if (m_home_menu) { std::scoped_lock lk_home{m_home_menu->lock}; - m_home_menu->lifecycle_manager.PushUnorderedMessage(m_system.Kernel(), message); + m_home_menu->lifecycle_manager.PushUnorderedMessage(message); } if (m_overlay_display) { std::scoped_lock lk_overlay{m_overlay_display->lock}; - m_overlay_display->lifecycle_manager.PushUnorderedMessage(m_system.Kernel(), message); + m_overlay_display->lifecycle_manager.PushUnorderedMessage(message); } if (m_application) { std::scoped_lock lk_application{m_application->lock}; - m_application->lifecycle_manager.PushUnorderedMessage(m_system.Kernel(), message); + m_application->lifecycle_manager.PushUnorderedMessage(message); } if (m_event_observer) { m_event_observer->RequestUpdate(); @@ -277,7 +277,8 @@ void WindowSystem::PruneTerminatedAppletsLocked() { // If we have a home menu, send it the application exited message. if (m_home_menu) { - m_home_menu->lifecycle_manager.PushUnorderedMessage(m_system.Kernel(), AppletMessage::ApplicationExited); + m_home_menu->lifecycle_manager.PushUnorderedMessage( + AppletMessage::ApplicationExited); } } diff --git a/src/core/hle/service/audio/audio_device.cpp b/src/core/hle/service/audio/audio_device.cpp index e9f7e074a1..eb64892ed8 100644 --- a/src/core/hle/service/audio/audio_device.cpp +++ b/src/core/hle/service/audio/audio_device.cpp @@ -42,7 +42,7 @@ IAudioDevice::IAudioDevice(Core::System& system_, u64 applet_resource_user_id, u }; RegisterHandlers(functions); - event->Signal(system.Kernel()); + event->Signal(); } IAudioDevice::~IAudioDevice() { @@ -128,7 +128,7 @@ Result IAudioDevice::GetActiveAudioDeviceNameAuto( Result IAudioDevice::QueryAudioDeviceSystemEvent(OutCopyHandle out_event) { LOG_DEBUG(Service_Audio, "(STUBBED) called"); - event->Signal(system.Kernel()); + event->Signal(); *out_event = &event->GetReadableEvent(); R_SUCCEED(); } diff --git a/src/core/hle/service/audio/audio_in.cpp b/src/core/hle/service/audio/audio_in.cpp index 6208c2d104..416803acc3 100644 --- a/src/core/hle/service/audio/audio_in.cpp +++ b/src/core/hle/service/audio/audio_in.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -40,7 +37,7 @@ IAudioIn::IAudioIn(Core::System& system_, Manager& manager, size_t session_id, RegisterHandlers(functions); - process->Open(system.Kernel()); + process->Open(); if (impl->GetSystem() .Initialize(device_name, in_params, handle, applet_resource_user_id) @@ -52,7 +49,7 @@ IAudioIn::IAudioIn(Core::System& system_, Manager& manager, size_t session_id, IAudioIn::~IAudioIn() { impl->Free(); service_context.CloseEvent(event); - process->Close(system.Kernel()); + process->Close(); } Result IAudioIn::GetAudioInState(Out out_state) { diff --git a/src/core/hle/service/audio/audio_out.cpp b/src/core/hle/service/audio/audio_out.cpp index 996eeede58..53009d5d74 100644 --- a/src/core/hle/service/audio/audio_out.cpp +++ b/src/core/hle/service/audio/audio_out.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -42,13 +39,13 @@ IAudioOut::IAudioOut(Core::System& system_, Manager& manager, size_t session_id, // clang-format on RegisterHandlers(functions); - process->Open(system.Kernel()); + process->Open(); } IAudioOut::~IAudioOut() { impl->Free(); service_context.CloseEvent(event); - process->Close(system.Kernel()); + process->Close(); } Result IAudioOut::GetAudioOutState(Out out_state) { diff --git a/src/core/hle/service/audio/audio_out_manager.cpp b/src/core/hle/service/audio/audio_out_manager.cpp index 3b2087932c..0a8e1ec256 100644 --- a/src/core/hle/service/audio/audio_out_manager.cpp +++ b/src/core/hle/service/audio/audio_out_manager.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project @@ -14,9 +14,7 @@ namespace Service::Audio { using namespace AudioCore::AudioOut; IAudioOutManager::IAudioOutManager(Core::System& system_) - : ServiceFramework{system_, "audout:u"} - , impl(system_) -{ + : ServiceFramework{system_, "audout:u"}, impl{std::make_unique(system_)} { // clang-format off static const FunctionInfo functions[] = { {0, D<&IAudioOutManager::ListAudioOuts>, "ListAudioOuts"}, diff --git a/src/core/hle/service/audio/audio_out_manager.h b/src/core/hle/service/audio/audio_out_manager.h index ec974aaba4..791274d5e9 100644 --- a/src/core/hle/service/audio/audio_out_manager.h +++ b/src/core/hle/service/audio/audio_out_manager.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project @@ -43,7 +43,7 @@ private: AudioCore::AudioOut::AudioOutParameter parameter, InCopyHandle process_handle, ClientAppletResourceUserId aruid); - std::optional impl; + std::unique_ptr impl; }; } // namespace Service::Audio diff --git a/src/core/hle/service/audio/audio_renderer.cpp b/src/core/hle/service/audio/audio_renderer.cpp index 49c6083109..21cc742b69 100644 --- a/src/core/hle/service/audio/audio_renderer.cpp +++ b/src/core/hle/service/audio/audio_renderer.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -39,7 +39,7 @@ IAudioRenderer::IAudioRenderer(Core::System& system_, Manager& manager_, // clang-format on RegisterHandlers(functions); - process_handle->Open(system_.Kernel()); + process_handle->Open(); impl->Initialize(params, transfer_memory, transfer_memory_size, process_handle, applet_resource_user_id, session_id); } @@ -47,7 +47,7 @@ IAudioRenderer::IAudioRenderer(Core::System& system_, Manager& manager_, IAudioRenderer::~IAudioRenderer() { impl->Finalize(); service_context.CloseEvent(rendered_event); - process_handle->Close(system.Kernel()); + process_handle->Close(); } Result IAudioRenderer::GetSampleRate(Out out_sample_rate) { diff --git a/src/core/hle/service/audio/audio_renderer_manager.cpp b/src/core/hle/service/audio/audio_renderer_manager.cpp index 972e930a89..6a1345c074 100644 --- a/src/core/hle/service/audio/audio_renderer_manager.cpp +++ b/src/core/hle/service/audio/audio_renderer_manager.cpp @@ -1,6 +1,3 @@ -// 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 @@ -18,9 +15,7 @@ namespace Service::Audio { using namespace AudioCore::Renderer; IAudioRendererManager::IAudioRendererManager(Core::System& system_) - : ServiceFramework{system_, "audren:u"} - , impl(system_) -{ + : ServiceFramework{system_, "audren:u"}, impl{std::make_unique(system_)} { // clang-format off static const FunctionInfo functions[] = { {0, D<&IAudioRendererManager::OpenAudioRenderer>, "OpenAudioRenderer"}, diff --git a/src/core/hle/service/audio/audio_renderer_manager.h b/src/core/hle/service/audio/audio_renderer_manager.h index fdce8b6ffa..69eee664c3 100644 --- a/src/core/hle/service/audio/audio_renderer_manager.h +++ b/src/core/hle/service/audio/audio_renderer_manager.h @@ -1,6 +1,3 @@ -// 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 @@ -33,7 +30,7 @@ private: Result GetAudioDeviceServiceWithRevisionInfo(Out> out_audio_device, u32 revision, ClientAppletResourceUserId aruid); - std::optional impl; + std::unique_ptr impl; u32 num_audio_devices{0}; }; diff --git a/src/core/hle/service/bcat/backend/backend.cpp b/src/core/hle/service/bcat/backend/backend.cpp index 3ef70aaacc..491416254c 100644 --- a/src/core/hle/service/bcat/backend/backend.cpp +++ b/src/core/hle/service/bcat/backend/backend.cpp @@ -13,9 +13,9 @@ namespace Service::BCAT { ProgressServiceBackend::ProgressServiceBackend(Core::System& system, std::string_view event_name) - : service_context{system, "ProgressServiceBackend"} -{ - update_event = service_context.CreateEvent("ProgressServiceBackend:UpdateEvent:" + std::string(event_name)); + : service_context{system, "ProgressServiceBackend"} { + update_event = service_context.CreateEvent("ProgressServiceBackend:UpdateEvent:" + + std::string(event_name)); } ProgressServiceBackend::~ProgressServiceBackend() { @@ -30,90 +30,103 @@ DeliveryCacheProgressImpl& ProgressServiceBackend::GetImpl() { return impl; } -void ProgressServiceBackend::SetTotalSize(Kernel::KernelCore& kernel, u64 size) { +void ProgressServiceBackend::SetTotalSize(u64 size) { impl.total_bytes = size; - SignalUpdate(kernel); + SignalUpdate(); } -void ProgressServiceBackend::StartConnecting(Kernel::KernelCore& kernel) { +void ProgressServiceBackend::StartConnecting() { impl.status = DeliveryCacheProgressStatus::Connecting; - SignalUpdate(kernel); + SignalUpdate(); } -void ProgressServiceBackend::StartProcessingDataList(Kernel::KernelCore& kernel) { +void ProgressServiceBackend::StartProcessingDataList() { impl.status = DeliveryCacheProgressStatus::ProcessingDataList; - SignalUpdate(kernel); + SignalUpdate(); } -void ProgressServiceBackend::StartDownloadingFile(Kernel::KernelCore& kernel, std::string_view dir_name, std::string_view file_name, u64 file_size) { +void ProgressServiceBackend::StartDownloadingFile(std::string_view dir_name, + std::string_view file_name, u64 file_size) { impl.status = DeliveryCacheProgressStatus::Downloading; impl.current_downloaded_bytes = 0; impl.current_total_bytes = file_size; - std::memcpy(impl.current_directory.data(), dir_name.data(), std::min(dir_name.size(), 0x31ull)); - std::memcpy(impl.current_file.data(), file_name.data(), std::min(file_name.size(), 0x31ull)); - SignalUpdate(kernel); + std::memcpy(impl.current_directory.data(), dir_name.data(), + std::min(dir_name.size(), 0x31ull)); + std::memcpy(impl.current_file.data(), file_name.data(), + std::min(file_name.size(), 0x31ull)); + SignalUpdate(); } -void ProgressServiceBackend::UpdateFileProgress(Kernel::KernelCore& kernel, u64 downloaded) { +void ProgressServiceBackend::UpdateFileProgress(u64 downloaded) { impl.current_downloaded_bytes = downloaded; - SignalUpdate(kernel); + SignalUpdate(); } -void ProgressServiceBackend::FinishDownloadingFile(Kernel::KernelCore& kernel) { +void ProgressServiceBackend::FinishDownloadingFile() { impl.total_downloaded_bytes += impl.current_total_bytes; - SignalUpdate(kernel); + SignalUpdate(); } -void ProgressServiceBackend::CommitDirectory(Kernel::KernelCore& kernel, std::string_view dir_name) { +void ProgressServiceBackend::CommitDirectory(std::string_view dir_name) { impl.status = DeliveryCacheProgressStatus::Committing; impl.current_file.fill(0); impl.current_downloaded_bytes = 0; impl.current_total_bytes = 0; - std::memcpy(impl.current_directory.data(), dir_name.data(), std::min(dir_name.size(), 0x31ull)); - SignalUpdate(kernel); + std::memcpy(impl.current_directory.data(), dir_name.data(), + std::min(dir_name.size(), 0x31ull)); + SignalUpdate(); } -void ProgressServiceBackend::FinishDownload(Kernel::KernelCore& kernel, Result result) { +void ProgressServiceBackend::FinishDownload(Result result) { impl.total_downloaded_bytes = impl.total_bytes; impl.status = DeliveryCacheProgressStatus::Done; impl.result = result; - SignalUpdate(kernel); + SignalUpdate(); } -void ProgressServiceBackend::SignalUpdate(Kernel::KernelCore& kernel) { - update_event->Signal(kernel); +void ProgressServiceBackend::SignalUpdate() { + update_event->Signal(); } BcatBackend::BcatBackend(DirectoryGetter getter) : dir_getter(std::move(getter)) {} + BcatBackend::~BcatBackend() = default; NullBcatBackend::NullBcatBackend(DirectoryGetter getter) : BcatBackend(std::move(getter)) {} + NullBcatBackend::~NullBcatBackend() = default; -bool NullBcatBackend::Synchronize(Kernel::KernelCore& kernel, TitleIDVersion title, ProgressServiceBackend& progress) { - LOG_DEBUG(Service_BCAT, "called, title_id={:016X}, build_id={:016X}", title.title_id, title.build_id); - progress.FinishDownload(kernel, ResultSuccess); +bool NullBcatBackend::Synchronize(TitleIDVersion title, ProgressServiceBackend& progress) { + LOG_DEBUG(Service_BCAT, "called, title_id={:016X}, build_id={:016X}", title.title_id, + title.build_id); + + progress.FinishDownload(ResultSuccess); return true; } -bool NullBcatBackend::SynchronizeDirectory(Kernel::KernelCore& kernel, TitleIDVersion title, std::string name, ProgressServiceBackend& progress) { - LOG_DEBUG(Service_BCAT, "called, title_id={:016X}, build_id={:016X}, name={}", title.title_id, title.build_id, name); - progress.FinishDownload(kernel, ResultSuccess); +bool NullBcatBackend::SynchronizeDirectory(TitleIDVersion title, std::string name, + ProgressServiceBackend& progress) { + LOG_DEBUG(Service_BCAT, "called, title_id={:016X}, build_id={:016X}, name={}", title.title_id, + title.build_id, name); + + progress.FinishDownload(ResultSuccess); return true; } -bool NullBcatBackend::Clear(Kernel::KernelCore& kernel, u64 title_id) { +bool NullBcatBackend::Clear(u64 title_id) { LOG_DEBUG(Service_BCAT, "called, title_id={:016X}", title_id); return true; } -void NullBcatBackend::SetPassphrase(Kernel::KernelCore& kernel, u64 title_id, const Passphrase& passphrase) { - LOG_DEBUG(Service_BCAT, "called, title_id={:016X}, passphrase={}", title_id, Common::HexToString(passphrase)); +void NullBcatBackend::SetPassphrase(u64 title_id, const Passphrase& passphrase) { + LOG_DEBUG(Service_BCAT, "called, title_id={:016X}, passphrase={}", title_id, + Common::HexToString(passphrase)); } -std::optional> NullBcatBackend::GetLaunchParameter(Kernel::KernelCore& kernel, TitleIDVersion title) { - LOG_DEBUG(Service_BCAT, "called, title_id={:016X}, build_id={:016X}", title.title_id, title.build_id); +std::optional> NullBcatBackend::GetLaunchParameter(TitleIDVersion title) { + LOG_DEBUG(Service_BCAT, "called, title_id={:016X}, build_id={:016X}", title.title_id, + title.build_id); return std::nullopt; } diff --git a/src/core/hle/service/bcat/backend/backend.h b/src/core/hle/service/bcat/backend/backend.h index 8419399a62..3680f6c9c8 100644 --- a/src/core/hle/service/bcat/backend/backend.h +++ b/src/core/hle/service/bcat/backend/backend.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -37,26 +34,26 @@ public: ~ProgressServiceBackend(); // Sets the number of bytes total in the entire download. - void SetTotalSize(Kernel::KernelCore& kernel, u64 size); + void SetTotalSize(u64 size); // Notifies the application that the backend has started connecting to the server. - void StartConnecting(Kernel::KernelCore& kernel); + void StartConnecting(); // Notifies the application that the backend has begun accumulating and processing metadata. - void StartProcessingDataList(Kernel::KernelCore& kernel); + void StartProcessingDataList(); // Notifies the application that a file is starting to be downloaded. - void StartDownloadingFile(Kernel::KernelCore& kernel, std::string_view dir_name, std::string_view file_name, u64 file_size); + void StartDownloadingFile(std::string_view dir_name, std::string_view file_name, u64 file_size); // Updates the progress of the current file to the size passed. - void UpdateFileProgress(Kernel::KernelCore& kernel, u64 downloaded); + void UpdateFileProgress(u64 downloaded); // Notifies the application that the current file has completed download. - void FinishDownloadingFile(Kernel::KernelCore& kernel); + void FinishDownloadingFile(); // Notifies the application that all files in this directory have completed and are being // finalized. - void CommitDirectory(Kernel::KernelCore& kernel, std::string_view dir_name); + void CommitDirectory(std::string_view dir_name); // Notifies the application that the operation completed with result code result. - void FinishDownload(Kernel::KernelCore& kernel, Result result); + void FinishDownload(Result result); private: explicit ProgressServiceBackend(Core::System& system, std::string_view event_name); @@ -64,7 +61,7 @@ private: Kernel::KReadableEvent& GetEvent(); DeliveryCacheProgressImpl& GetImpl(); - void SignalUpdate(Kernel::KernelCore& kernel); + void SignalUpdate(); KernelHelpers::ServiceContext service_context; @@ -77,19 +74,25 @@ class BcatBackend { public: explicit BcatBackend(DirectoryGetter getter); virtual ~BcatBackend(); + // Called when the backend is needed to synchronize the data for the game with title ID and // version in title. A ProgressServiceBackend object is provided to alert the application of // status. - virtual bool Synchronize(Kernel::KernelCore& kernel, TitleIDVersion title, ProgressServiceBackend& progress) = 0; + virtual bool Synchronize(TitleIDVersion title, ProgressServiceBackend& progress) = 0; // Very similar to Synchronize, but only for the directory provided. Backends should not alter // the data for any other directories. - virtual bool SynchronizeDirectory(Kernel::KernelCore& kernel, TitleIDVersion title, std::string name, ProgressServiceBackend& progress) = 0; + virtual bool SynchronizeDirectory(TitleIDVersion title, std::string name, + ProgressServiceBackend& progress) = 0; + // Removes all cached data associated with title id provided. - virtual bool Clear(Kernel::KernelCore& kernel, u64 title_id) = 0; + virtual bool Clear(u64 title_id) = 0; + // Sets the BCAT Passphrase to be used with the associated title ID. - virtual void SetPassphrase(Kernel::KernelCore& kernel, u64 title_id, const Passphrase& passphrase) = 0; + virtual void SetPassphrase(u64 title_id, const Passphrase& passphrase) = 0; + // Gets the launch parameter used by AM associated with the title ID and version provided. - virtual std::optional> GetLaunchParameter(Kernel::KernelCore& kernel, TitleIDVersion title) = 0; + virtual std::optional> GetLaunchParameter(TitleIDVersion title) = 0; + protected: DirectoryGetter dir_getter; }; @@ -100,13 +103,18 @@ public: explicit NullBcatBackend(DirectoryGetter getter); ~NullBcatBackend() override; - bool Synchronize(Kernel::KernelCore& kernel, TitleIDVersion title, ProgressServiceBackend& progress) override; - bool SynchronizeDirectory(Kernel::KernelCore& kernel, TitleIDVersion title, std::string name, ProgressServiceBackend& progress) override; - bool Clear(Kernel::KernelCore& kernel, u64 title_id) override; - void SetPassphrase(Kernel::KernelCore& kernel, u64 title_id, const Passphrase& passphrase) override; - std::optional> GetLaunchParameter(Kernel::KernelCore& kernel, TitleIDVersion title) override; + bool Synchronize(TitleIDVersion title, ProgressServiceBackend& progress) override; + bool SynchronizeDirectory(TitleIDVersion title, std::string name, + ProgressServiceBackend& progress) override; + + bool Clear(u64 title_id) override; + + void SetPassphrase(u64 title_id, const Passphrase& passphrase) override; + + std::optional> GetLaunchParameter(TitleIDVersion title) override; }; -std::unique_ptr CreateBackendFromSettings(Core::System& system, DirectoryGetter getter); +std::unique_ptr CreateBackendFromSettings(Core::System& system, + DirectoryGetter getter); } // namespace Service::BCAT diff --git a/src/core/hle/service/bcat/bcat_service.cpp b/src/core/hle/service/bcat/bcat_service.cpp index 210fd77094..849bf8d0d9 100644 --- a/src/core/hle/service/bcat/bcat_service.cpp +++ b/src/core/hle/service/bcat/bcat_service.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project @@ -70,7 +70,7 @@ Result IBcatService::RequestSyncDeliveryCache( LOG_DEBUG(Service_BCAT, "called"); auto& progress_backend{GetProgressBackend(SyncType::Normal)}; - backend.Synchronize(system.Kernel(), {system.GetApplicationProcessProgramID(), + backend.Synchronize({system.GetApplicationProcessProgramID(), GetCurrentBuildID(system.GetApplicationProcessBuildID())}, GetProgressBackend(SyncType::Normal)); @@ -86,7 +86,7 @@ Result IBcatService::RequestSyncDeliveryCacheWithDirectoryName( LOG_DEBUG(Service_BCAT, "called, name={}", name); auto& progress_backend{GetProgressBackend(SyncType::Directory)}; - backend.SynchronizeDirectory(system.Kernel(), {system.GetApplicationProcessProgramID(), + backend.SynchronizeDirectory({system.GetApplicationProcessProgramID(), GetCurrentBuildID(system.GetApplicationProcessBuildID())}, name, progress_backend); @@ -107,7 +107,7 @@ Result IBcatService::SetPassphrase(u64 application_id, std::memcpy(passphrase.data(), passphrase_buffer.data(), (std::min)(passphrase.size(), passphrase_buffer.size())); - backend.SetPassphrase(system.Kernel(), application_id, passphrase); + backend.SetPassphrase(application_id, passphrase); R_SUCCEED(); } @@ -120,7 +120,7 @@ Result IBcatService::ClearDeliveryCacheStorage(u64 application_id) { LOG_DEBUG(Service_BCAT, "called, title_id={:016X}", application_id); R_UNLESS(application_id != 0, ResultInvalidArgument); - R_UNLESS(backend.Clear(system.Kernel(), application_id), FileSys::ResultPermissionDenied); + R_UNLESS(backend.Clear(application_id), FileSys::ResultPermissionDenied); R_SUCCEED(); } diff --git a/src/core/hle/service/friend/friend.cpp b/src/core/hle/service/friend/friend.cpp index 6885a7be7d..79578956b1 100644 --- a/src/core/hle/service/friend/friend.cpp +++ b/src/core/hle/service/friend/friend.cpp @@ -183,7 +183,7 @@ private: auto& readable_event = completion_event->GetReadableEvent(); IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(readable_event.Signal(system.Kernel())); + rb.Push(readable_event.Signal()); rb.PushCopyObjects(readable_event); } diff --git a/src/core/hle/service/glue/time/alarm_worker.cpp b/src/core/hle/service/glue/time/alarm_worker.cpp index 770dc62f5c..3ff071f4a0 100644 --- a/src/core/hle/service/glue/time/alarm_worker.cpp +++ b/src/core/hle/service/glue/time/alarm_worker.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -31,7 +28,7 @@ void AlarmWorker::Initialize(std::shared_ptr "Glue:AlarmWorker::AlarmTimer", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional { - m_timer_event->Signal(m_system.Kernel()); + m_timer_event->Signal(); return std::nullopt; }); @@ -60,7 +57,7 @@ void AlarmWorker::OnPowerStateChanged() { s64 closest_time{}; if (!GetClosestAlarmInfo(closest_alarm_info, closest_time)) { m_system.CoreTiming().UnscheduleEvent(m_timer_timing_event); - m_timer_event->Clear(m_system.Kernel()); + m_timer_event->Clear(); return; } @@ -70,7 +67,7 @@ void AlarmWorker::OnPowerStateChanged() { auto next_time{closest_alarm_info.alert_time - closest_time}; m_system.CoreTiming().UnscheduleEvent(m_timer_timing_event); - m_timer_event->Clear(m_system.Kernel()); + m_timer_event->Clear(); m_system.CoreTiming().ScheduleEvent(std::chrono::nanoseconds(next_time), m_timer_timing_event); diff --git a/src/core/hle/service/glue/time/time_zone.cpp b/src/core/hle/service/glue/time/time_zone.cpp index 3543e1938b..c358cfbf28 100644 --- a/src/core/hle/service/glue/time/time_zone.cpp +++ b/src/core/hle/service/glue/time/time_zone.cpp @@ -89,7 +89,7 @@ Result TimeZoneService::SetDeviceLocationName( std::scoped_lock m{m_list_mutex}; for (auto& operation_event : m_list_nodes) { - operation_event.m_event->Signal(m_system.Kernel()); + operation_event.m_event->Signal(); } R_SUCCEED(); } diff --git a/src/core/hle/service/glue/time/worker.cpp b/src/core/hle/service/glue/time/worker.cpp index 5025efc717..1dab3e9dcb 100644 --- a/src/core/hle/service/glue/time/worker.cpp +++ b/src/core/hle/service/glue/time/worker.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -33,7 +30,7 @@ TimeWorker::TimeWorker(Core::System& system, StandardSteadyClockResource& steady "Time::SteadyClockEvent", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional { - m_timer_steady_clock->Signal(m_system.Kernel()); + m_timer_steady_clock->Signal(); return std::nullopt; }); @@ -41,19 +38,19 @@ TimeWorker::TimeWorker(Core::System& system, StandardSteadyClockResource& steady "Time::SteadyClockEvent", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional { - m_timer_file_system->Signal(m_system.Kernel()); + m_timer_file_system->Signal(); return std::nullopt; }); } TimeWorker::~TimeWorker() { - m_local_clock_event->Signal(m_system.Kernel()); - m_network_clock_event->Signal(m_system.Kernel()); - m_ephemeral_clock_event->Signal(m_system.Kernel()); + m_local_clock_event->Signal(); + m_network_clock_event->Signal(); + m_ephemeral_clock_event->Signal(); std::this_thread::sleep_for(std::chrono::milliseconds(16)); m_thread.request_stop(); - m_event->Signal(m_system.Kernel()); + m_event->Signal(); m_thread.join(); m_ctx.CloseEvent(m_event); @@ -170,19 +167,19 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) { return; case EventType::PowerStateChange: - m_alarm_worker.GetEvent().Clear(m_system.Kernel()); + m_alarm_worker.GetEvent().Clear(); if (m_pm_state_change_handler.m_priority <= 1) { m_alarm_worker.OnPowerStateChanged(); } break; case EventType::SignalAlarms: - m_alarm_worker.GetTimerEvent().Clear(m_system.Kernel()); + m_alarm_worker.GetTimerEvent().Clear(); m_time_m->CheckAndSignalAlarms(); break; case EventType::UpdateLocalSystemClock: { - m_local_clock_event->Clear(m_system.Kernel()); + m_local_clock_event->Clear(); Service::PSC::Time::SystemClockContext context{}; R_ASSERT(m_local_clock->GetSystemClockContext(&context)); @@ -193,7 +190,7 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) { } case EventType::UpdateNetworkSystemClock: { - m_network_clock_event->Clear(m_system.Kernel()); + m_network_clock_event->Clear(); Service::PSC::Time::SystemClockContext context{}; R_ASSERT(m_network_clock->GetSystemClockContext(&context)); @@ -221,7 +218,7 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) { } case EventType::UpdateEphemeralSystemClock: { - m_ephemeral_clock_event->Clear(m_system.Kernel()); + m_ephemeral_clock_event->Clear(); Service::PSC::Time::SystemClockContext context{}; auto res = m_ephemeral_clock->GetSystemClockContext(&context); @@ -250,20 +247,20 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) { } case EventType::UpdateSteadyClock: - m_timer_steady_clock->Clear(m_system.Kernel()); + m_timer_steady_clock->Clear(); m_steady_clock_resource.UpdateTime(); m_time_m->SetStandardSteadyClockBaseTime(m_steady_clock_resource.GetTime()); break; case EventType::UpdateFileTimestamp: - m_timer_file_system->Clear(m_system.Kernel()); + m_timer_file_system->Clear(); m_file_timestamp_worker.SetFilesystemPosixTime(); break; case EventType::AutoCorrect: { - m_standard_user_auto_correct_clock_event->Clear(m_system.Kernel()); + m_standard_user_auto_correct_clock_event->Clear(); bool automatic_correction{}; R_ASSERT(m_time_sm->IsStandardUserSystemClockAutomaticCorrectionEnabled( diff --git a/src/core/hle/service/hid/hid_server.cpp b/src/core/hle/service/hid/hid_server.cpp index cd69829472..f29cf4e3d7 100644 --- a/src/core/hle/service/hid/hid_server.cpp +++ b/src/core/hle/service/hid/hid_server.cpp @@ -650,7 +650,8 @@ Result IHidServer::SetSupportedNpadStyleSet(Core::HID::NpadStyleSet supported_st LOG_DEBUG(Service_HID, "called, supported_style_set={}, applet_resource_user_id={}", supported_style_set, aruid.pid); - R_TRY(GetResourceManager()->GetNpad()->SetSupportedNpadStyleSet(system.Kernel(), aruid.pid, supported_style_set)); + R_TRY( + GetResourceManager()->GetNpad()->SetSupportedNpadStyleSet(aruid.pid, supported_style_set)); Core::HID::NpadStyleTag style_tag{supported_style_set}; const auto revision = GetResourceManager()->GetNpad()->GetRevision(aruid.pid); @@ -666,7 +667,7 @@ Result IHidServer::GetSupportedNpadStyleSet(Out out_sup ClientAppletResourceUserId aruid) { LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", aruid.pid); - R_RETURN(GetResourceManager()->GetNpad()->GetSupportedNpadStyleSet(system.Kernel(), aruid.pid, + R_RETURN(GetResourceManager()->GetNpad()->GetSupportedNpadStyleSet(aruid.pid, *out_supported_style_set)); } @@ -676,7 +677,7 @@ Result IHidServer::SetSupportedNpadIdType( LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", aruid.pid); R_RETURN( - GetResourceManager()->GetNpad()->SetSupportedNpadIdType(system.Kernel(), aruid.pid, supported_npad_list)); + GetResourceManager()->GetNpad()->SetSupportedNpadIdType(aruid.pid, supported_npad_list)); } Result IHidServer::ActivateNpad(ClientAppletResourceUserId aruid) { @@ -701,13 +702,14 @@ Result IHidServer::AcquireNpadStyleSetUpdateEventHandle( LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}, unknown={}", npad_id, aruid.pid, unknown); - R_RETURN(GetResourceManager()->GetNpad()->AcquireNpadStyleSetUpdateEventHandle(system.Kernel(), aruid.pid, out_event, npad_id)); + R_RETURN(GetResourceManager()->GetNpad()->AcquireNpadStyleSetUpdateEventHandle( + aruid.pid, out_event, npad_id)); } Result IHidServer::DisconnectNpad(Core::HID::NpadIdType npad_id, ClientAppletResourceUserId aruid) { LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", npad_id, aruid.pid); - R_RETURN(GetResourceManager()->GetNpad()->DisconnectNpad(system.Kernel(), aruid.pid, npad_id)); + R_RETURN(GetResourceManager()->GetNpad()->DisconnectNpad(aruid.pid, npad_id)); } Result IHidServer::GetPlayerLedPattern(Out out_led_pattern, @@ -777,7 +779,7 @@ Result IHidServer::SetNpadJoyAssignmentModeSingleByDefault(Core::HID::NpadIdType LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", npad_id, aruid.pid); Core::HID::NpadIdType new_npad_id{}; - GetResourceManager()->GetNpad()->SetNpadMode(system.Kernel(), + GetResourceManager()->GetNpad()->SetNpadMode( aruid.pid, new_npad_id, npad_id, NpadJoyDeviceType::Left, NpadJoyAssignmentMode::Single); R_SUCCEED(); } @@ -789,7 +791,7 @@ Result IHidServer::SetNpadJoyAssignmentModeSingle(Core::HID::NpadIdType npad_id, npad_id, aruid.pid, npad_joy_device_type); Core::HID::NpadIdType new_npad_id{}; - GetResourceManager()->GetNpad()->SetNpadMode(system.Kernel(), + GetResourceManager()->GetNpad()->SetNpadMode( aruid.pid, new_npad_id, npad_id, npad_joy_device_type, NpadJoyAssignmentMode::Single); R_SUCCEED(); } @@ -799,7 +801,7 @@ Result IHidServer::SetNpadJoyAssignmentModeDual(Core::HID::NpadIdType npad_id, LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", npad_id, aruid.pid); Core::HID::NpadIdType new_npad_id{}; - GetResourceManager()->GetNpad()->SetNpadMode(system.Kernel(), aruid.pid, new_npad_id, npad_id, {}, + GetResourceManager()->GetNpad()->SetNpadMode(aruid.pid, new_npad_id, npad_id, {}, NpadJoyAssignmentMode::Dual); R_SUCCEED(); } @@ -811,7 +813,7 @@ Result IHidServer::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1, npad_id_1, npad_id_2, aruid.pid); R_RETURN( - GetResourceManager()->GetNpad()->MergeSingleJoyAsDualJoy(system.Kernel(), aruid.pid, npad_id_1, npad_id_2)); + GetResourceManager()->GetNpad()->MergeSingleJoyAsDualJoy(aruid.pid, npad_id_1, npad_id_2)); } Result IHidServer::StartLrAssignmentMode(ClientAppletResourceUserId aruid) { @@ -838,40 +840,67 @@ Result IHidServer::SetNpadHandheldActivationMode(ClientAppletResourceUserId arui ASSERT_MSG(false, "Activation mode should be always None, Single or Dual"); R_SUCCEED(); } - R_RETURN(GetResourceManager()->GetNpad()->SetNpadHandheldActivationMode(system.Kernel(), aruid.pid, activation_mode)); + + R_RETURN( + GetResourceManager()->GetNpad()->SetNpadHandheldActivationMode(aruid.pid, activation_mode)); } Result IHidServer::GetNpadHandheldActivationMode( Out out_activation_mode, ClientAppletResourceUserId aruid) { LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", aruid.pid); - R_RETURN(GetResourceManager()->GetNpad()->GetNpadHandheldActivationMode(system.Kernel(), aruid.pid, *out_activation_mode)); + + R_RETURN(GetResourceManager()->GetNpad()->GetNpadHandheldActivationMode(aruid.pid, + *out_activation_mode)); } -Result IHidServer::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2, ClientAppletResourceUserId aruid) { - LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}", npad_id_1, npad_id_2, aruid.pid); - R_RETURN(GetResourceManager()->GetNpad()->SwapNpadAssignment(system.Kernel(), aruid.pid, npad_id_1, npad_id_2)) +Result IHidServer::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1, + Core::HID::NpadIdType npad_id_2, + ClientAppletResourceUserId aruid) { + LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}", + npad_id_1, npad_id_2, aruid.pid); + + R_RETURN(GetResourceManager()->GetNpad()->SwapNpadAssignment(aruid.pid, npad_id_1, npad_id_2)) } -Result IHidServer::IsUnintendedHomeButtonInputProtectionEnabled(Out out_is_enabled, Core::HID::NpadIdType npad_id, ClientAppletResourceUserId aruid) { +Result IHidServer::IsUnintendedHomeButtonInputProtectionEnabled(Out out_is_enabled, + Core::HID::NpadIdType npad_id, + ClientAppletResourceUserId aruid) { LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", npad_id, aruid.pid); + R_UNLESS(IsNpadIdValid(npad_id), ResultInvalidNpadId); - R_RETURN(GetResourceManager()->GetNpad()->IsUnintendedHomeButtonInputProtectionEnabled(*out_is_enabled, aruid.pid, npad_id)); + R_RETURN(GetResourceManager()->GetNpad()->IsUnintendedHomeButtonInputProtectionEnabled( + *out_is_enabled, aruid.pid, npad_id)); } -Result IHidServer::EnableUnintendedHomeButtonInputProtection(bool is_enabled, Core::HID::NpadIdType npad_id, ClientAppletResourceUserId aruid) { - LOG_DEBUG(Service_HID, "called, is_enabled={}, npad_id={}, applet_resource_user_id={}",is_enabled, npad_id, aruid.pid); +Result IHidServer::EnableUnintendedHomeButtonInputProtection(bool is_enabled, + Core::HID::NpadIdType npad_id, + ClientAppletResourceUserId aruid) { + LOG_DEBUG(Service_HID, "called, is_enabled={}, npad_id={}, applet_resource_user_id={}", + is_enabled, npad_id, aruid.pid); + R_UNLESS(IsNpadIdValid(npad_id), ResultInvalidNpadId); - R_RETURN(GetResourceManager()->GetNpad()->EnableUnintendedHomeButtonInputProtection(aruid.pid, npad_id, is_enabled)); + R_RETURN(GetResourceManager()->GetNpad()->EnableUnintendedHomeButtonInputProtection( + aruid.pid, npad_id, is_enabled)); } -Result IHidServer::SetNpadJoyAssignmentModeSingleWithDestination(Out out_is_reassigned, Out out_new_npad_id, Core::HID::NpadIdType npad_id, ClientAppletResourceUserId aruid, NpadJoyDeviceType npad_joy_device_type) { - LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}", npad_id, aruid.pid, npad_joy_device_type); - *out_is_reassigned = GetResourceManager()->GetNpad()->SetNpadMode(system.Kernel(), aruid.pid, *out_new_npad_id, npad_id, npad_joy_device_type, NpadJoyAssignmentMode::Single); +Result IHidServer::SetNpadJoyAssignmentModeSingleWithDestination( + Out out_is_reassigned, Out out_new_npad_id, + Core::HID::NpadIdType npad_id, ClientAppletResourceUserId aruid, + NpadJoyDeviceType npad_joy_device_type) { + LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}", + npad_id, aruid.pid, npad_joy_device_type); + + *out_is_reassigned = GetResourceManager()->GetNpad()->SetNpadMode( + aruid.pid, *out_new_npad_id, npad_id, npad_joy_device_type, NpadJoyAssignmentMode::Single); + R_SUCCEED(); } -Result IHidServer::SetNpadAnalogStickUseCenterClamp(bool use_center_clamp, ClientAppletResourceUserId aruid) { - LOG_INFO(Service_HID, "called, use_center_clamp={}, applet_resource_user_id={}", use_center_clamp, aruid.pid); +Result IHidServer::SetNpadAnalogStickUseCenterClamp(bool use_center_clamp, + ClientAppletResourceUserId aruid) { + LOG_INFO(Service_HID, "called, use_center_clamp={}, applet_resource_user_id={}", + use_center_clamp, aruid.pid); + GetResourceManager()->GetNpad()->SetNpadAnalogStickUseCenterClamp(aruid.pid, use_center_clamp); R_SUCCEED(); } diff --git a/src/core/hle/service/hid/hid_system_server.cpp b/src/core/hle/service/hid/hid_system_server.cpp index dbc8310c08..1de5dd6f28 100644 --- a/src/core/hle/service/hid/hid_system_server.cpp +++ b/src/core/hle/service/hid/hid_system_server.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -281,7 +281,7 @@ void IHidSystemServer::ApplyNpadSystemCommonPolicy(HLERequestContext& ctx) { LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); - GetResourceManager()->GetNpad()->ApplyNpadSystemCommonPolicy(system.Kernel(), applet_resource_user_id); + GetResourceManager()->GetNpad()->ApplyNpadSystemCommonPolicy(applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -328,7 +328,7 @@ void IHidSystemServer::ApplyNpadSystemCommonPolicyFull(HLERequestContext& ctx) { LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); - GetResourceManager()->GetNpad()->ApplyNpadSystemCommonPolicyFull(system.Kernel(), applet_resource_user_id); + GetResourceManager()->GetNpad()->ApplyNpadSystemCommonPolicyFull(applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -358,8 +358,9 @@ void IHidSystemServer::GetMaskedSupportedNpadStyleSet(HLERequestContext& ctx) { LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); Core::HID::NpadStyleSet supported_styleset{}; - const auto npad = GetResourceManager()->GetNpad(); - const Result result = npad->GetMaskedSupportedNpadStyleSet(system.Kernel(), applet_resource_user_id, supported_styleset); + const auto& npad = GetResourceManager()->GetNpad(); + const Result result = + npad->GetMaskedSupportedNpadStyleSet(applet_resource_user_id, supported_styleset); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(result); @@ -372,8 +373,9 @@ void IHidSystemServer::SetSupportedNpadStyleSetAll(HLERequestContext& ctx) { LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); - const auto npad = GetResourceManager()->GetNpad(); - const auto result = npad->SetSupportedNpadStyleSet(system.Kernel(), applet_resource_user_id, Core::HID::NpadStyleSet::All); + const auto& npad = GetResourceManager()->GetNpad(); + const auto result = + npad->SetSupportedNpadStyleSet(applet_resource_user_id, Core::HID::NpadStyleSet::All); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result); diff --git a/src/core/hle/service/hle_ipc.cpp b/src/core/hle/service/hle_ipc.cpp index ce7591656a..8db8f8538c 100644 --- a/src/core/hle/service/hle_ipc.cpp +++ b/src/core/hle/service/hle_ipc.cpp @@ -275,17 +275,17 @@ Result HLERequestContext::WriteToOutgoingCommandBuffer() { for (auto& object : outgoing_copy_objects) { Handle handle{}; if (object) { - R_TRY(handle_table.Add(kernel, &handle, object)); + R_TRY(handle_table.Add(&handle, object)); } cmd_buf[current_offset++] = handle; } for (auto& object : outgoing_move_objects) { Handle handle{}; if (object) { - R_TRY(handle_table.Add(kernel, &handle, object)); + R_TRY(handle_table.Add(&handle, object)); // Close our reference to the object, as it is being moved to the caller. - object->Close(kernel); + object->Close(); } cmd_buf[current_offset++] = handle; } @@ -503,10 +503,11 @@ bool HLERequestContext::CanWriteBuffer(std::size_t buffer_index) const { } void HLERequestContext::AddMoveInterface(SessionRequestHandlerPtr s) { - ASSERT(Kernel::GetCurrentProcess(kernel).GetResourceLimit()->Reserve(kernel, Kernel::LimitableResource::SessionCountMax, 1)); + ASSERT(Kernel::GetCurrentProcess(kernel).GetResourceLimit()->Reserve( + Kernel::LimitableResource::SessionCountMax, 1)); auto* session = Kernel::KSession::Create(kernel); - session->Initialize(kernel, nullptr, 0); + session->Initialize(nullptr, 0); Kernel::KSession::Register(kernel, session); auto& server = manager.lock()->GetServerManager(); diff --git a/src/core/hle/service/hle_ipc.h b/src/core/hle/service/hle_ipc.h index eeb5bf3547..ec8185a09e 100644 --- a/src/core/hle/service/hle_ipc.h +++ b/src/core/hle/service/hle_ipc.h @@ -373,10 +373,11 @@ public: template Kernel::KScopedAutoObject GetObjectFromHandle(u32 handle) { - auto obj = client_handle_table->GetObjectForIpc(kernel, handle, thread); - if (obj.IsNotNull()) - return {kernel, obj->DynamicCast()}; - return {kernel, nullptr}; + auto obj = client_handle_table->GetObjectForIpc(handle, thread); + if (obj.IsNotNull()) { + return obj->DynamicCast(); + } + return nullptr; } [[nodiscard]] std::shared_ptr GetManager() const { diff --git a/src/core/hle/service/ipc_helpers.h b/src/core/hle/service/ipc_helpers.h index c37b0c2e05..8aee17db8d 100644 --- a/src/core/hle/service/ipc_helpers.h +++ b/src/core/hle/service/ipc_helpers.h @@ -151,10 +151,11 @@ public: if (manager->IsDomain()) { context->AddDomainObject(std::move(iface)); } else { - ASSERT(Kernel::GetCurrentProcess(kernel).GetResourceLimit()->Reserve(kernel, Kernel::LimitableResource::SessionCountMax, 1)); + ASSERT(Kernel::GetCurrentProcess(kernel).GetResourceLimit()->Reserve( + Kernel::LimitableResource::SessionCountMax, 1)); auto* session = Kernel::KSession::Create(kernel); - session->Initialize(kernel, nullptr, 0); + session->Initialize(nullptr, 0); Kernel::KSession::Register(kernel, session); auto next_manager = std::make_shared( diff --git a/src/core/hle/service/jit/jit.cpp b/src/core/hle/service/jit/jit.cpp index 626b643c00..1179e8b61d 100644 --- a/src/core/hle/service/jit/jit.cpp +++ b/src/core/hle/service/jit/jit.cpp @@ -30,13 +30,12 @@ static_assert(sizeof(Struct32) == 32, "Struct32 has wrong size"); class IJitEnvironment final : public ServiceFramework { public: - explicit IJitEnvironment(Core::System& system_, Kernel::KProcess* process_, CodeMemory&& user_rx_, CodeMemory&& user_ro_) - : ServiceFramework{system_, "IJitEnvironment"} - , process{kernel, process_} - , user_rx{std::move(user_rx_)} - , user_ro{std::move(user_ro_)} - , context{system_.ApplicationMemory()} - { + explicit IJitEnvironment(Core::System& system_, + Kernel::KScopedAutoObject process_, + CodeMemory&& user_rx_, CodeMemory&& user_ro_) + : ServiceFramework{system_, "IJitEnvironment"}, process{std::move(process_)}, + user_rx{std::move(user_rx_)}, user_ro{std::move(user_ro_)}, + context{system_.ApplicationMemory()} { // clang-format off static const FunctionInfo functions[] = { @@ -59,11 +58,6 @@ public: configuration.sys_ro_memory = configuration.user_ro_memory; } - ~IJitEnvironment() { - user_rx.Finalize(system.Kernel()); - user_ro.Finalize(system.Kernel()); - } - Result GenerateCode(Out out_return_value, Out out_range0, Out out_range1, OutBuffer out_buffer, u32 data_size, u64 command, CodeRange range0, CodeRange range1, @@ -287,9 +281,14 @@ private: } CodeMemory rx, ro; - R_TRY(rx.Initialize(system.Kernel(), *process, *rx_mem, rx_size, Kernel::Svc::MemoryPermission::ReadExecute, generate_random)); - R_TRY(ro.Initialize(system.Kernel(), *process, *ro_mem, ro_size, Kernel::Svc::MemoryPermission::Read, generate_random)); - *out_jit_environment = std::make_shared(system, process.Get(), std::move(rx), std::move(ro)); + + R_TRY(rx.Initialize(*process, *rx_mem, rx_size, Kernel::Svc::MemoryPermission::ReadExecute, + generate_random)); + R_TRY(ro.Initialize(*process, *ro_mem, ro_size, Kernel::Svc::MemoryPermission::Read, + generate_random)); + + *out_jit_environment = + std::make_shared(system, process.Get(), std::move(rx), std::move(ro)); R_SUCCEED(); } diff --git a/src/core/hle/service/jit/jit_code_memory.cpp b/src/core/hle/service/jit/jit_code_memory.cpp index 3218512af4..2b480488a8 100644 --- a/src/core/hle/service/jit/jit_code_memory.cpp +++ b/src/core/hle/service/jit/jit_code_memory.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -8,9 +5,12 @@ namespace Service::JIT { -Result CodeMemory::Initialize(Kernel::KernelCore& kernel, Kernel::KProcess& process, Kernel::KCodeMemory& code_memory, size_t size, Kernel::Svc::MemoryPermission perm, std::mt19937_64& generate_random) { +Result CodeMemory::Initialize(Kernel::KProcess& process, Kernel::KCodeMemory& code_memory, + size_t size, Kernel::Svc::MemoryPermission perm, + std::mt19937_64& generate_random) { auto& page_table = process.GetPageTable(); - const u64 alias_code_start = GetInteger(page_table.GetAliasCodeRegionStart()) / Kernel::PageSize; + const u64 alias_code_start = + GetInteger(page_table.GetAliasCodeRegionStart()) / Kernel::PageSize; const u64 alias_code_size = page_table.GetAliasCodeRegionSize() / Kernel::PageSize; // NOTE: This will retry indefinitely until mapping the code memory succeeds. @@ -20,7 +20,7 @@ Result CodeMemory::Initialize(Kernel::KernelCore& kernel, Kernel::KProcess& proc (alias_code_start + (generate_random() % alias_code_size)) * Kernel::PageSize; // Try to map the address - R_TRY_CATCH(code_memory.MapToOwner(kernel, mapped_address, size, perm)) { + R_TRY_CATCH(code_memory.MapToOwner(mapped_address, size, perm)) { R_CATCH(Kernel::ResultInvalidMemoryRegion) { // If we could not map here, retry. continue; @@ -35,17 +35,17 @@ Result CodeMemory::Initialize(Kernel::KernelCore& kernel, Kernel::KProcess& proc m_perm = perm; // Open a new reference to the code memory. - m_code_memory->Open(kernel); + m_code_memory->Open(); // We succeeded. R_SUCCEED(); } } -void CodeMemory::Finalize(Kernel::KernelCore& kernel) { +void CodeMemory::Finalize() { if (m_code_memory) { - R_ASSERT(m_code_memory->UnmapFromOwner(kernel, m_address, m_size)); - m_code_memory->Close(kernel); + R_ASSERT(m_code_memory->UnmapFromOwner(m_address, m_size)); + m_code_memory->Close(); } m_code_memory = nullptr; diff --git a/src/core/hle/service/jit/jit_code_memory.h b/src/core/hle/service/jit/jit_code_memory.h index d741520aeb..6376d4c4eb 100644 --- a/src/core/hle/service/jit/jit_code_memory.h +++ b/src/core/hle/service/jit/jit_code_memory.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -10,16 +7,29 @@ #include "core/hle/kernel/k_code_memory.h" -namespace Kernel { -class KernelCore; -} - namespace Service::JIT { class CodeMemory { public: - Result Initialize(Kernel::KernelCore& kernel, Kernel::KProcess& process, Kernel::KCodeMemory& code_memory, size_t size, Kernel::Svc::MemoryPermission perm, std::mt19937_64& generate_random); - void Finalize(Kernel::KernelCore& kernel); + YUZU_NON_COPYABLE(CodeMemory); + + explicit CodeMemory() = default; + + CodeMemory(CodeMemory&& rhs) { + std::swap(m_code_memory, rhs.m_code_memory); + std::swap(m_size, rhs.m_size); + std::swap(m_address, rhs.m_address); + std::swap(m_perm, rhs.m_perm); + } + + ~CodeMemory() { + this->Finalize(); + } + +public: + Result Initialize(Kernel::KProcess& process, Kernel::KCodeMemory& code_memory, size_t size, + Kernel::Svc::MemoryPermission perm, std::mt19937_64& generate_random); + void Finalize(); size_t GetSize() const { return m_size; @@ -29,6 +39,7 @@ public: return m_address; } +private: Kernel::KCodeMemory* m_code_memory{}; size_t m_size{}; u64 m_address{}; diff --git a/src/core/hle/service/kernel_helpers.cpp b/src/core/hle/service/kernel_helpers.cpp index f7a5cb7049..f080f7ffa2 100644 --- a/src/core/hle/service/kernel_helpers.cpp +++ b/src/core/hle/service/kernel_helpers.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -17,15 +14,15 @@ namespace Service::KernelHelpers { ServiceContext::ServiceContext(Core::System& system_, std::string name_) - : kernel(system_.Kernel()) -{ + : kernel(system_.Kernel()) { if (process = Kernel::GetCurrentProcessPointer(kernel); process != nullptr) { return; } // Create the process. process = Kernel::KProcess::Create(kernel); - ASSERT(R_SUCCEEDED(process->Initialize(kernel, Kernel::Svc::CreateProcessParameter{}, kernel.GetSystemResourceLimit(), false))); + ASSERT(R_SUCCEEDED(process->Initialize(Kernel::Svc::CreateProcessParameter{}, + kernel.GetSystemResourceLimit(), false))); // Register the process. Kernel::KProcess::Register(kernel, process); @@ -34,14 +31,14 @@ ServiceContext::ServiceContext(Core::System& system_, std::string name_) ServiceContext::~ServiceContext() { if (process_created) { - process->Close(kernel); + process->Close(); process = nullptr; } } Kernel::KEvent* ServiceContext::CreateEvent(std::string&& name) { // Reserve a new event from the process resource limit - Kernel::KScopedResourceReservation event_reservation(kernel, process, + Kernel::KScopedResourceReservation event_reservation(process, Kernel::LimitableResource::EventCountMax); if (!event_reservation.Succeeded()) { LOG_CRITICAL(Service, "Resource limit reached!"); @@ -56,7 +53,7 @@ Kernel::KEvent* ServiceContext::CreateEvent(std::string&& name) { } // Initialize the event. - event->Initialize(kernel, process); + event->Initialize(process); // Commit the thread reservation. event_reservation.Commit(); @@ -68,10 +65,11 @@ Kernel::KEvent* ServiceContext::CreateEvent(std::string&& name) { } void ServiceContext::CloseEvent(Kernel::KEvent* event) { - if (event) { - event->GetReadableEvent().Close(kernel); - event->Close(kernel); + if (!event) { + return; } + event->GetReadableEvent().Close(); + event->Close(); } } // namespace Service::KernelHelpers diff --git a/src/core/hle/service/kernel_helpers.h b/src/core/hle/service/kernel_helpers.h index 4e21c8857f..eca9aefb52 100644 --- a/src/core/hle/service/kernel_helpers.h +++ b/src/core/hle/service/kernel_helpers.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -29,6 +26,7 @@ public: void CloseEvent(Kernel::KEvent* event); +private: Kernel::KernelCore& kernel; Kernel::KProcess* process{}; bool process_created{false}; diff --git a/src/core/hle/service/ldn/user_local_communication_service.cpp b/src/core/hle/service/ldn/user_local_communication_service.cpp index 572aea6314..1e984a9782 100644 --- a/src/core/hle/service/ldn/user_local_communication_service.cpp +++ b/src/core/hle/service/ldn/user_local_communication_service.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -322,7 +322,7 @@ void IUserLocalCommunicationService::OnLDNPacketReceived(const Network::LDNPacke } void IUserLocalCommunicationService::OnEventFired() { - state_change_event->Signal(system.Kernel()); + state_change_event->Signal(); } } // namespace Service::LDN diff --git a/src/core/hle/service/nfc/common/device.cpp b/src/core/hle/service/nfc/common/device.cpp index 2876c6f739..faa2b1f584 100644 --- a/src/core/hle/service/nfc/common/device.cpp +++ b/src/core/hle/service/nfc/common/device.cpp @@ -71,13 +71,13 @@ NfcDevice::~NfcDevice() { void NfcDevice::NpadUpdate(Core::HID::ControllerTriggerType type) { if (type == Core::HID::ControllerTriggerType::Connected) { Initialize(); - availability_change_event->Signal(system.Kernel()); + availability_change_event->Signal(); return; } if (type == Core::HID::ControllerTriggerType::Disconnected) { Finalize(); - availability_change_event->Signal(system.Kernel()); + availability_change_event->Signal(); return; } @@ -138,8 +138,8 @@ bool NfcDevice::LoadNfcTag(u8 protocol, u8 tag_type, u8 uuid_length, UniqueSeria }; device_state = DeviceState::TagFound; - deactivate_event->GetReadableEvent().Clear(system.Kernel()); - activate_event->Signal(system.Kernel()); + deactivate_event->GetReadableEvent().Clear(); + activate_event->Signal(); return true; } @@ -192,8 +192,8 @@ void NfcDevice::CloseNfcTag() { device_state = DeviceState::TagRemoved; encrypted_tag_data = {}; tag_data = {}; - activate_event->GetReadableEvent().Clear(system.Kernel()); - deactivate_event->Signal(system.Kernel()); + activate_event->GetReadableEvent().Clear(); + deactivate_event->Signal(); } Kernel::KReadableEvent& NfcDevice::GetActivateEvent() const { diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp index 87e806d86b..7bd06e2e0f 100644 --- a/src/core/hle/service/nifm/nifm.cpp +++ b/src/core/hle/service/nifm/nifm.cpp @@ -275,7 +275,7 @@ private: } state.store(State::Processing); - evt_processing->Signal(system.Kernel()); + evt_processing->Signal(); worker = std::thread([this]() { using namespace std::chrono_literals; @@ -321,7 +321,7 @@ private: void Finish(Result rc) { worker_result.store(rc); state.store(State::Finished); - evt_scan_complete->Signal(system.Kernel()); + evt_scan_complete->Signal(); } KernelHelpers::ServiceContext svc_ctx; @@ -486,7 +486,7 @@ private: void UpdateState(RequestState new_state) { LOG_DEBUG(Service_NIFM, "(STUBBED) called"); state = new_state; - event1->Signal(system.Kernel()); + event1->Signal(); } KernelHelpers::ServiceContext service_context; diff --git a/src/core/hle/service/nim/nim.cpp b/src/core/hle/service/nim/nim.cpp index 5f85302713..4f465c5da7 100644 --- a/src/core/hle/service/nim/nim.cpp +++ b/src/core/hle/service/nim/nim.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project @@ -429,7 +429,7 @@ private: void StartTask(HLERequestContext& ctx) { // No need to connect to the internet, just finish the task straight away. LOG_DEBUG(Service_NIM, "called"); - finished_event->Signal(system.Kernel()); + finished_event->Signal(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } @@ -451,7 +451,7 @@ private: void Cancel(HLERequestContext& ctx) { LOG_DEBUG(Service_NIM, "called"); - finished_event->Clear(system.Kernel()); + finished_event->Clear(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } diff --git a/src/core/hle/service/ns/application_manager_interface.cpp b/src/core/hle/service/ns/application_manager_interface.cpp index 485eac0afa..5490c09d03 100644 --- a/src/core/hle/service/ns/application_manager_interface.cpp +++ b/src/core/hle/service/ns/application_manager_interface.cpp @@ -610,7 +610,7 @@ Result IApplicationManagerInterface::GetApplicationRecordUpdateSystemEvent( OutCopyHandle out_event) { LOG_WARNING(Service_NS, "(STUBBED) called"); - record_update_system_event.Signal(system.Kernel()); + record_update_system_event.Signal(); *out_event = record_update_system_event.GetHandle(); R_SUCCEED(); @@ -820,14 +820,14 @@ Result IApplicationManagerInterface::RequestDownloadApplicationControlDataInBack LOG_INFO(Service_NS, "called, control_source={} app={:016X}", control_source, application_id); - unknown_event.Signal(system.Kernel()); + unknown_event.Signal(); R_SUCCEED(); } Result IApplicationManagerInterface::Unknown4022( OutCopyHandle out_event) { LOG_WARNING(Service_NS, "(STUBBED) called"); - unknown_event.Signal(system.Kernel()); + unknown_event.Signal(); *out_event = unknown_event.GetHandle(); R_SUCCEED(); } diff --git a/src/core/hle/service/ns/read_only_application_control_data_interface.cpp b/src/core/hle/service/ns/read_only_application_control_data_interface.cpp index f12d9b03d2..03f0a17865 100644 --- a/src/core/hle/service/ns/read_only_application_control_data_interface.cpp +++ b/src/core/hle/service/ns/read_only_application_control_data_interface.cpp @@ -87,7 +87,7 @@ public: RegisterHandlers(functions); completion_event = service_context.CreateEvent("IAsyncValue:Completion"); - completion_event->GetReadableEvent().Signal(system.Kernel()); + completion_event->GetReadableEvent().Signal(); } ~IAsyncValueForListApplicationTitle() override { diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp index 1238a21f85..3bfef0c29c 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp @@ -138,7 +138,8 @@ NvResult nvhost_as_gpu::AllocAsEx(IoctlAllocAsEx& params) { static_cast((vm.va_range_end - vm.va_range_split) >> vm.big_page_size_bits)}; vm.big_page_allocator.emplace(start_big_pages, end_big_pages); - gmmu = std::make_unique(system, max_big_page_bits, vm.va_range_split, vm.big_page_size_bits, VM::PAGE_SIZE_BITS); + gmmu = std::make_shared(system, max_big_page_bits, vm.va_range_split, + vm.big_page_size_bits, VM::PAGE_SIZE_BITS); system.GPU().InitAddressSpace(*gmmu); vm.initialised = true; @@ -415,7 +416,7 @@ NvResult nvhost_as_gpu::BindChannel(IoctlBindChannel& params) { LOG_DEBUG(Service_NVDRV, "called, fd={:X}", params.fd); auto gpu_channel_device = module.GetDevice(params.fd); - gpu_channel_device->channel_state->memory_manager = gmmu.get(); + gpu_channel_device->channel_state->memory_manager = gmmu; return NvResult::Success; } diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h index b8ae57e1b4..44892ee368 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h @@ -219,7 +219,7 @@ private: bool initialised{}; } vm; - std::unique_ptr gmmu; + std::shared_ptr gmmu; }; } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index 6ef32b890f..b2580f2bb9 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp @@ -203,7 +203,7 @@ NvResult nvhost_ctrl::IocCtrlEventWait(IocCtrlEventWaitParams& params, bool is_a auto& event_ = events[slot]; if (event_.status.exchange(EventState::Signalling, std::memory_order_acq_rel) == EventState::Waiting) { - event_.kevent->Signal(system.Kernel()); + event_.kevent->Signal(); } event_.status.store(EventState::Signalled, std::memory_order_release); }); @@ -292,7 +292,7 @@ NvResult nvhost_ctrl::IocCtrlClearEventWait(IocCtrlEventClearParams& params) { } event.fails++; event.status.store(EventState::Cancelled, std::memory_order_release); - event.kevent->Clear(system.Kernel()); + event.kevent->Clear(); return NvResult::Success; } diff --git a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp index c3eb2796e3..5bd53fb99e 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp +++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp @@ -111,7 +111,7 @@ Status BufferQueueProducer::SetBufferCount(s32 buffer_count) { core->override_max_buffer_count = buffer_count; core->SignalDequeueCondition(); - buffer_wait_event->Signal(service_context.kernel); + buffer_wait_event->Signal(); listener = core->consumer_listener; } @@ -576,7 +576,7 @@ void BufferQueueProducer::CancelBuffer(s32 slot, const Fence& fence) { slots[slot].fence = fence; core->SignalDequeueCondition(); - buffer_wait_event->Signal(service_context.kernel); + buffer_wait_event->Signal(); } Status BufferQueueProducer::Query(NativeWindow what, s32* out_value) { @@ -714,7 +714,7 @@ Status BufferQueueProducer::Disconnect(NativeWindowApi api) { core->connected_producer_listener = nullptr; core->connected_api = NativeWindowApi::NoConnectedApi; core->SignalDequeueCondition(); - buffer_wait_event->Signal(service_context.kernel); + buffer_wait_event->Signal(); listener = core->consumer_listener; } else { LOG_ERROR(Service_Nvnflinger, @@ -764,7 +764,7 @@ Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot, } core->SignalDequeueCondition(); - buffer_wait_event->Signal(service_context.kernel); + buffer_wait_event->Signal(); return Status::NoError; } diff --git a/src/core/hle/service/olsc/native_handle_holder.cpp b/src/core/hle/service/olsc/native_handle_holder.cpp index 1e50195539..d381714bc3 100644 --- a/src/core/hle/service/olsc/native_handle_holder.cpp +++ b/src/core/hle/service/olsc/native_handle_holder.cpp @@ -32,7 +32,7 @@ INativeHandleHolder::~INativeHandleHolder() { Result INativeHandleHolder::GetNativeHandle(OutCopyHandle out_event) { LOG_WARNING(Service_OLSC, "(STUBBED) called"); if (event) { - event->Signal(system.Kernel()); + event->Signal(); *out_event = std::addressof(event->GetReadableEvent()); } else { *out_event = nullptr; diff --git a/src/core/hle/service/os/event.cpp b/src/core/hle/service/os/event.cpp index 8808c5b4f0..ec52c17fd8 100644 --- a/src/core/hle/service/os/event.cpp +++ b/src/core/hle/service/os/event.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -10,27 +7,25 @@ namespace Service { -Event::Event(KernelHelpers::ServiceContext& ctx_) - : ctx{ctx_} -{ +Event::Event(KernelHelpers::ServiceContext& ctx) { m_event = ctx.CreateEvent("Event"); } Event::~Event() { - m_event->GetReadableEvent().Close(ctx.kernel); - m_event->Close(ctx.kernel); + m_event->GetReadableEvent().Close(); + m_event->Close(); } -void Event::Signal(Kernel::KernelCore& kernel) noexcept { - m_event->Signal(kernel); +void Event::Signal() { + m_event->Signal(); } -void Event::Clear(Kernel::KernelCore& kernel) noexcept { - m_event->Clear(kernel); +void Event::Clear() { + m_event->Clear(); } -Kernel::KReadableEvent* Event::GetHandle() noexcept { - return std::addressof(m_event->GetReadableEvent()); +Kernel::KReadableEvent* Event::GetHandle() { + return &m_event->GetReadableEvent(); } } // namespace Service diff --git a/src/core/hle/service/os/event.h b/src/core/hle/service/os/event.h index bc23598b58..cdbc4635a6 100644 --- a/src/core/hle/service/os/event.h +++ b/src/core/hle/service/os/event.h @@ -1,13 +1,9 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once namespace Kernel { -class KernelCore; class KEvent; class KReadableEvent; } // namespace Kernel @@ -23,12 +19,12 @@ public: explicit Event(KernelHelpers::ServiceContext& ctx); ~Event(); - void Signal(Kernel::KernelCore& kernel) noexcept; - void Clear(Kernel::KernelCore& kernel) noexcept; - Kernel::KReadableEvent* GetHandle() noexcept; + void Signal(); + void Clear(); + + Kernel::KReadableEvent* GetHandle(); private: - KernelHelpers::ServiceContext& ctx; Kernel::KEvent* m_event; }; diff --git a/src/core/hle/service/os/mutex.cpp b/src/core/hle/service/os/mutex.cpp index 12b872b57f..6009f48668 100644 --- a/src/core/hle/service/os/mutex.cpp +++ b/src/core/hle/service/os/mutex.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -13,22 +10,22 @@ namespace Service { Mutex::Mutex(Core::System& system) : m_system(system) { m_event = Kernel::KEvent::Create(system.Kernel()); - m_event->Initialize(system.Kernel(), nullptr); + m_event->Initialize(nullptr); // Register the event. Kernel::KEvent::Register(system.Kernel(), m_event); - ASSERT(R_SUCCEEDED(m_event->Signal(system.Kernel()))); + ASSERT(R_SUCCEEDED(m_event->Signal())); } Mutex::~Mutex() { - m_event->GetReadableEvent().Close(m_system.Kernel()); - m_event->Close(m_system.Kernel()); + m_event->GetReadableEvent().Close(); + m_event->Close(); } void Mutex::lock() { // Infinitely retry until we successfully clear the event. - while (R_FAILED(m_event->GetReadableEvent().Reset(m_system.Kernel()))) { + while (R_FAILED(m_event->GetReadableEvent().Reset())) { s32 index; Kernel::KSynchronizationObject* obj = &m_event->GetReadableEvent(); @@ -43,7 +40,7 @@ void Mutex::lock() { void Mutex::unlock() { // Unlock. - ASSERT(R_SUCCEEDED(m_event->Signal(m_system.Kernel()))); + ASSERT(R_SUCCEEDED(m_event->Signal())); } } // namespace Service diff --git a/src/core/hle/service/os/process.cpp b/src/core/hle/service/os/process.cpp index 5e46de245d..0dbadc315e 100644 --- a/src/core/hle/service/os/process.cpp +++ b/src/core/hle/service/os/process.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -13,6 +10,14 @@ namespace Service { +Process::Process(Core::System& system) + : m_system(system), m_process(), m_main_thread_priority(), m_main_thread_stack_size(), + m_process_started() {} + +Process::~Process() { + this->Finalize(); +} + bool Process::Initialize(Loader::AppLoader& loader, Loader::ResultStatus& out_load_result) { // First, ensure we are not holding another process. this->Finalize(); @@ -23,7 +28,7 @@ bool Process::Initialize(Loader::AppLoader& loader, Loader::ResultStatus& out_lo // On exit, ensure we free the additional reference to the process. SCOPE_EXIT { - process->Close(m_system.Kernel()); + process->Close(); }; // Insert process modules into memory. @@ -47,7 +52,7 @@ bool Process::Initialize(Loader::AppLoader& loader, Loader::ResultStatus& out_lo // Take ownership of the process object. m_process = process; - m_process->Open(m_system.Kernel()); + m_process->Open(); // We succeeded. return true; @@ -59,7 +64,8 @@ void Process::Finalize() { // Close the process. if (m_process) { - m_process->Close(m_system.Kernel()); + m_process->Close(); + // TODO: remove this, kernel already tracks this m_system.Kernel().RemoveProcess(m_process); } @@ -79,7 +85,7 @@ bool Process::Run() { // Start. if (m_process) { - m_process->Run(m_system.Kernel(), m_main_thread_priority, m_main_thread_stack_size); + m_process->Run(m_main_thread_priority, m_main_thread_stack_size); } // Mark as started. @@ -91,13 +97,13 @@ bool Process::Run() { void Process::Terminate() { if (m_process) { - m_process->Terminate(m_system.Kernel()); + m_process->Terminate(); } } void Process::ResetSignal() { if (m_process) { - m_process->Reset(m_system.Kernel()); + m_process->Reset(); } } @@ -138,7 +144,8 @@ u64 Process::GetProgramId() const { void Process::Suspend(bool suspended) { if (m_process) { - m_process->SetActivity(m_system.Kernel(), suspended ? Kernel::Svc::ProcessActivity::Paused : Kernel::Svc::ProcessActivity::Runnable); + m_process->SetActivity(suspended ? Kernel::Svc::ProcessActivity::Paused + : Kernel::Svc::ProcessActivity::Runnable); } } diff --git a/src/core/hle/service/os/process.h b/src/core/hle/service/os/process.h index ca10945f84..9109b7d0a5 100644 --- a/src/core/hle/service/os/process.h +++ b/src/core/hle/service/os/process.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -25,8 +22,8 @@ namespace Service { class Process { public: - inline explicit Process(Core::System& system) noexcept : m_system(system) {} - inline ~Process() { this->Finalize(); } + explicit Process(Core::System& system); + ~Process(); bool Initialize(Loader::AppLoader& loader, Loader::ResultStatus& out_load_result); void Finalize(); @@ -53,8 +50,8 @@ public: private: Core::System& m_system; Kernel::KProcess* m_process{}; - u64 m_main_thread_stack_size{}; s32 m_main_thread_priority{}; + u64 m_main_thread_stack_size{}; bool m_process_started{}; }; diff --git a/src/core/hle/service/pm/pm.cpp b/src/core/hle/service/pm/pm.cpp index 5f94984f4e..b52468e419 100644 --- a/src/core/hle/service/pm/pm.cpp +++ b/src/core/hle/service/pm/pm.cpp @@ -1,6 +1,3 @@ -// 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 @@ -28,15 +25,19 @@ constexpr u64 NO_PROCESS_FOUND_PID{0}; using ProcessList = std::list>; template -Kernel::KScopedAutoObject SearchProcessList(Kernel::KernelCore& kernel, ProcessList& process_list, F&& predicate) { - auto const it = std::find_if(process_list.begin(), process_list.end(), predicate); - if (it == process_list.end()) - return {kernel, nullptr}; - return {kernel, it->GetPointerUnsafe()}; +Kernel::KScopedAutoObject SearchProcessList(ProcessList& process_list, + F&& predicate) { + const auto iter = std::find_if(process_list.begin(), process_list.end(), predicate); + + if (iter == process_list.end()) { + return nullptr; + } + + return iter->GetPointerUnsafe(); } -void GetApplicationPidGeneric(Kernel::KernelCore& kernel, HLERequestContext& ctx, ProcessList& process_list) { - auto process = SearchProcessList(kernel, process_list, [](auto& p) { return p->IsApplication(); }); +void GetApplicationPidGeneric(HLERequestContext& ctx, ProcessList& process_list) { + auto process = SearchProcessList(process_list, [](auto& p) { return p->IsApplication(); }); IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); @@ -104,7 +105,7 @@ private: LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id); auto list = kernel.GetProcessList(); - auto process = SearchProcessList(system.Kernel(), + auto process = SearchProcessList( list, [program_id](auto& p) { return p->GetProgramId() == program_id; }); if (process.IsNull()) { @@ -121,7 +122,7 @@ private: void GetApplicationProcessId(HLERequestContext& ctx) { LOG_DEBUG(Service_PM, "called"); auto list = kernel.GetProcessList(); - GetApplicationPidGeneric(system.Kernel(), ctx, list); + GetApplicationPidGeneric(ctx, list); } void AtmosphereGetProcessInfo(HLERequestContext& ctx) { @@ -133,7 +134,7 @@ private: LOG_WARNING(Service_PM, "(Partial Implementation) called, pid={:016X}", pid); auto list = kernel.GetProcessList(); - auto process = SearchProcessList(system.Kernel(), list, [pid](auto& p) { return p->GetProcessId() == pid; }); + auto process = SearchProcessList(list, [pid](auto& p) { return p->GetProcessId() == pid; }); if (process.IsNull()) { IPC::ResponseBuilder rb{ctx, 2}; @@ -187,7 +188,7 @@ private: LOG_DEBUG(Service_PM, "called, process_id={:016X}", process_id); auto list = kernel.GetProcessList(); - auto process = SearchProcessList(system.Kernel(), + auto process = SearchProcessList( list, [process_id](auto& p) { return p->GetProcessId() == process_id; }); if (process.IsNull()) { @@ -208,7 +209,7 @@ private: LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id); auto list = system.Kernel().GetProcessList(); - auto process = SearchProcessList(system.Kernel(), + auto process = SearchProcessList( list, [program_id](auto& p) { return p->GetProgramId() == program_id; }); if (process.IsNull()) { @@ -248,7 +249,7 @@ private: void GetApplicationProcessIdForShell(HLERequestContext& ctx) { LOG_DEBUG(Service_PM, "called"); auto list = kernel.GetProcessList(); - GetApplicationPidGeneric(system.Kernel(), ctx, list); + GetApplicationPidGeneric(ctx, list); } }; diff --git a/src/core/hle/service/psc/ovln/receiver.cpp b/src/core/hle/service/psc/ovln/receiver.cpp index f43d705126..f7d3882a05 100644 --- a/src/core/hle/service/psc/ovln/receiver.cpp +++ b/src/core/hle/service/psc/ovln/receiver.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -100,7 +100,7 @@ Result IReceiver::ReceiveWithTick(Out out_notification, } } if (!has_messages) { - receive_event->Clear(system.Kernel()); + receive_event->Clear(); } R_SUCCEED(); diff --git a/src/core/hle/service/psc/time/alarms.cpp b/src/core/hle/service/psc/time/alarms.cpp index c2de95f653..5e52c19f82 100644 --- a/src/core/hle/service/psc/time/alarms.cpp +++ b/src/core/hle/service/psc/time/alarms.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -10,10 +7,8 @@ namespace Service::PSC::Time { Alarm::Alarm(Core::System& system, KernelHelpers::ServiceContext& ctx, AlarmType type) - : m_ctx{ctx} - , m_event{ctx.CreateEvent("Psc:Alarm:Event")} -{ - m_event->Clear(system.Kernel()); + : m_ctx{ctx}, m_event{ctx.CreateEvent("Psc:Alarm:Event")} { + m_event->Clear(); switch (type) { case WakeupAlarm: @@ -42,7 +37,7 @@ Alarms::~Alarms() { m_ctx.CloseEvent(m_event); } -Result Alarms::Enable(Kernel::KernelCore& kernel, Alarm& alarm, s64 time) { +Result Alarms::Enable(Alarm& alarm, s64 time) { R_UNLESS(m_steady_clock.IsInitialized(), ResultClockUninitialized); std::scoped_lock l{m_mutex}; @@ -54,21 +49,21 @@ Result Alarms::Enable(Kernel::KernelCore& kernel, Alarm& alarm, s64 time) { time_ns = Common::AlignUp(time_ns, one_second_ns); alarm.SetAlertTime(time_ns); - Insert(kernel, alarm); - R_RETURN(UpdateClosestAndSignal(kernel)); + Insert(alarm); + R_RETURN(UpdateClosestAndSignal()); } -void Alarms::Disable(Kernel::KernelCore& kernel, Alarm& alarm) { +void Alarms::Disable(Alarm& alarm) { std::scoped_lock l{m_mutex}; if (!alarm.IsLinked()) { return; } - Erase(kernel, alarm); - UpdateClosestAndSignal(kernel); + Erase(alarm); + UpdateClosestAndSignal(); } -void Alarms::CheckAndSignal(Kernel::KernelCore& kernel) { +void Alarms::CheckAndSignal() { std::scoped_lock l{m_mutex}; if (m_alarms.empty()) { return; @@ -77,9 +72,9 @@ void Alarms::CheckAndSignal(Kernel::KernelCore& kernel) { bool alarm_signalled{false}; for (auto& alarm : m_alarms) { if (m_steady_clock.GetRawTime() >= alarm.GetAlertTime()) { - alarm.Signal(kernel); + alarm.Signal(); alarm.Lock(); - Erase(kernel, alarm); + Erase(alarm); m_power_state_request_manager.UpdatePendingPowerStateRequestPriority( alarm.GetPriority()); @@ -92,7 +87,7 @@ void Alarms::CheckAndSignal(Kernel::KernelCore& kernel) { } m_power_state_request_manager.SignalPowerStateRequestAvailability(); - UpdateClosestAndSignal(kernel); + UpdateClosestAndSignal(); } bool Alarms::GetClosestAlarm(Alarm** out_alarm) { @@ -102,7 +97,7 @@ bool Alarms::GetClosestAlarm(Alarm** out_alarm) { return alarm != nullptr; } -void Alarms::Insert(Kernel::KernelCore& kernel, Alarm& alarm) { +void Alarms::Insert(Alarm& alarm) { // Alarms are sorted by alert time, then priority auto it{m_alarms.begin()}; while (it != m_alarms.end()) { @@ -118,15 +113,15 @@ void Alarms::Insert(Kernel::KernelCore& kernel, Alarm& alarm) { m_alarms.push_back(alarm); } -void Alarms::Erase(Kernel::KernelCore& kernel, Alarm& alarm) { +void Alarms::Erase(Alarm& alarm) { m_alarms.erase(m_alarms.iterator_to(alarm)); } -Result Alarms::UpdateClosestAndSignal(Kernel::KernelCore& kernel) { +Result Alarms::UpdateClosestAndSignal() { m_closest_alarm = m_alarms.empty() ? nullptr : std::addressof(m_alarms.front()); R_SUCCEED_IF(m_closest_alarm == nullptr); - m_event->Signal(kernel); + m_event->Signal(); R_SUCCEED(); } @@ -188,7 +183,7 @@ void ISteadyClockAlarm::Enable(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; auto time{rp.Pop()}; - auto res = m_alarms.Enable(system.Kernel(), m_alarm, time); + auto res = m_alarms.Enable(m_alarm, time); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(res); @@ -197,7 +192,7 @@ void ISteadyClockAlarm::Enable(HLERequestContext& ctx) { void ISteadyClockAlarm::Disable(HLERequestContext& ctx) { LOG_DEBUG(Service_Time, "called."); - m_alarms.Disable(system.Kernel(), m_alarm); + m_alarms.Disable(m_alarm); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); diff --git a/src/core/hle/service/psc/time/alarms.h b/src/core/hle/service/psc/time/alarms.h index 79b66c06ea..597770028b 100644 --- a/src/core/hle/service/psc/time/alarms.h +++ b/src/core/hle/service/psc/time/alarms.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -51,8 +48,8 @@ struct Alarm : public Common::IntrusiveListBaseNode { return m_priority; } - void Signal(Kernel::KernelCore& kernel) { - m_event->Signal(kernel); + void Signal() { + m_event->Signal(); } Result Lock() { @@ -86,15 +83,15 @@ public: return m_steady_clock.GetRawTime(); } - Result Enable(Kernel::KernelCore& kernel, Alarm& alarm, s64 time); - void Disable(Kernel::KernelCore& kernel, Alarm& alarm); - void CheckAndSignal(Kernel::KernelCore& kernel); + Result Enable(Alarm& alarm, s64 time); + void Disable(Alarm& alarm); + void CheckAndSignal(); bool GetClosestAlarm(Alarm** out_alarm); private: - void Insert(Kernel::KernelCore& kernel, Alarm& alarm); - void Erase(Kernel::KernelCore& kernel, Alarm& alarm); - Result UpdateClosestAndSignal(Kernel::KernelCore& kernel); + void Insert(Alarm& alarm); + void Erase(Alarm& alarm); + Result UpdateClosestAndSignal(); Core::System& m_system; KernelHelpers::ServiceContext m_ctx; diff --git a/src/core/hle/service/psc/time/clocks/context_writers.cpp b/src/core/hle/service/psc/time/clocks/context_writers.cpp index 4e54a07a37..a44486b438 100644 --- a/src/core/hle/service/psc/time/clocks/context_writers.cpp +++ b/src/core/hle/service/psc/time/clocks/context_writers.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -9,10 +6,10 @@ namespace Service::PSC::Time { -void ContextWriter::SignalAllNodes(Kernel::KernelCore& kernel) { +void ContextWriter::SignalAllNodes() { std::scoped_lock l{m_mutex}; for (auto& operation : m_operation_events) { - operation.m_event->Signal(kernel); + operation.m_event->Signal(); } } @@ -36,7 +33,7 @@ Result LocalSystemClockContextWriter::Write(const SystemClockContext& context) { m_shared_memory.SetLocalSystemContext(context); - SignalAllNodes(m_system.Kernel()); + SignalAllNodes(); R_SUCCEED(); } @@ -60,7 +57,7 @@ Result NetworkSystemClockContextWriter::Write(const SystemClockContext& context) m_shared_memory.SetNetworkSystemContext(context); - SignalAllNodes(m_system.Kernel()); + SignalAllNodes(); R_SUCCEED(); } @@ -78,7 +75,7 @@ Result EphemeralNetworkSystemClockContextWriter::Write(const SystemClockContext& m_in_use = true; } - SignalAllNodes(m_system.Kernel()); + SignalAllNodes(); R_SUCCEED(); } diff --git a/src/core/hle/service/psc/time/clocks/context_writers.h b/src/core/hle/service/psc/time/clocks/context_writers.h index 2adc7d2546..6643fc9f2a 100644 --- a/src/core/hle/service/psc/time/clocks/context_writers.h +++ b/src/core/hle/service/psc/time/clocks/context_writers.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -14,9 +11,6 @@ #include "core/hle/service/psc/time/common.h" #include "core/hle/service/psc/time/shared_memory.h" -namespace Kernel { -class KernelCore; -} namespace Core { class System; } @@ -31,7 +25,7 @@ public: virtual ~ContextWriter() = default; virtual Result Write(const SystemClockContext& context) = 0; - void SignalAllNodes(Kernel::KernelCore& kernel); + void SignalAllNodes(); void Link(OperationEvent& operation_event); private: diff --git a/src/core/hle/service/psc/time/clocks/standard_user_system_clock_core.cpp b/src/core/hle/service/psc/time/clocks/standard_user_system_clock_core.cpp index 7a51e51f3c..31ed273966 100644 --- a/src/core/hle/service/psc/time/clocks/standard_user_system_clock_core.cpp +++ b/src/core/hle/service/psc/time/clocks/standard_user_system_clock_core.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -60,7 +57,7 @@ Result StandardUserSystemClockCore::GetTimePoint(SteadyClockTimePoint& out_time_ void StandardUserSystemClockCore::SetTimePointAndSignal(SteadyClockTimePoint& time_point) { m_time_point = time_point; - m_event->Signal(m_system.Kernel()); + m_event->Signal(); } } // namespace Service::PSC::Time diff --git a/src/core/hle/service/psc/time/power_state_request_manager.cpp b/src/core/hle/service/psc/time/power_state_request_manager.cpp index 7a494f47cb..b28b513649 100644 --- a/src/core/hle/service/psc/time/power_state_request_manager.cpp +++ b/src/core/hle/service/psc/time/power_state_request_manager.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -35,7 +35,7 @@ void PowerStateRequestManager::SignalPowerStateRequestAvailability() { } m_has_pending_request = false; m_available_request_priority = m_pending_request_priority; - m_event->Signal(m_system.Kernel()); + m_event->Signal(); } } @@ -45,7 +45,7 @@ bool PowerStateRequestManager::GetAndClearPowerStateRequest(u32& out_priority) { if (m_has_available_request) { out_priority = m_available_request_priority; m_has_available_request = false; - m_event->Clear(m_system.Kernel()); + m_event->Clear(); } return had_request; } diff --git a/src/core/hle/service/psc/time/service_manager.cpp b/src/core/hle/service/psc/time/service_manager.cpp index 4646def3db..ed9fb32cdf 100644 --- a/src/core/hle/service/psc/time/service_manager.cpp +++ b/src/core/hle/service/psc/time/service_manager.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -241,7 +238,7 @@ Result ServiceManager::GetClosestAlarmUpdatedEvent( Result ServiceManager::CheckAndSignalAlarms() { LOG_DEBUG(Service_Time, "called."); - m_alarms.CheckAndSignal(m_system.Kernel()); + m_alarms.CheckAndSignal(); R_SUCCEED(); } diff --git a/src/core/hle/service/psc/time/static.cpp b/src/core/hle/service/psc/time/static.cpp index 488731565d..9a0adb2955 100644 --- a/src/core/hle/service/psc/time/static.cpp +++ b/src/core/hle/service/psc/time/static.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -174,7 +171,7 @@ Result StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled( R_TRY(m_time->m_standard_steady_clock.GetCurrentTimePoint(time_point)); m_user_system_clock.SetTimePointAndSignal(time_point); - m_user_system_clock.GetEvent().Signal(system.Kernel()); + m_user_system_clock.GetEvent().Signal(); R_SUCCEED(); } diff --git a/src/core/hle/service/ptm/psm.cpp b/src/core/hle/service/ptm/psm.cpp index 211f380171..06396bbb4c 100644 --- a/src/core/hle/service/ptm/psm.cpp +++ b/src/core/hle/service/ptm/psm.cpp @@ -43,19 +43,19 @@ public: void SignalChargerTypeChanged() { if (should_signal && should_signal_charger_type) { - state_change_event->Signal(system.Kernel()); + state_change_event->Signal(); } } void SignalPowerSupplyChanged() { if (should_signal && should_signal_power_supply) { - state_change_event->Signal(system.Kernel()); + state_change_event->Signal(); } } void SignalBatteryVoltageStateChanged() { if (should_signal && should_signal_battery_voltage) { - state_change_event->Signal(system.Kernel()); + state_change_event->Signal(); } } diff --git a/src/core/hle/service/ro/ro.cpp b/src/core/hle/service/ro/ro.cpp index 879e51c65e..895bcad864 100644 --- a/src/core/hle/service/ro/ro.cpp +++ b/src/core/hle/service/ro/ro.cpp @@ -57,7 +57,7 @@ struct NrrInfo { struct ProcessContext { constexpr ProcessContext() = default; - void Initialize(Kernel::KernelCore& kernel, Kernel::KProcess* process, u64 process_id) { + void Initialize(Kernel::KProcess* process, u64 process_id) { ASSERT(!m_in_use); m_nro_in_use = {}; @@ -70,15 +70,15 @@ struct ProcessContext { m_in_use = true; if (m_process) { - m_process->Open(kernel); + m_process->Open(); } } - void Finalize(Kernel::KernelCore& kernel) { + void Finalize() { ASSERT(m_in_use); if (m_process) { - m_process->Close(kernel); + m_process->Close(); } m_nro_in_use = {}; @@ -307,7 +307,7 @@ class RoContext { public: explicit RoContext() = default; - Result RegisterProcess(Kernel::KernelCore& kernel, size_t* out_context_id, Kernel::KProcess* process, u64 process_id) { + Result RegisterProcess(size_t* out_context_id, Kernel::KProcess* process, u64 process_id) { // Validate process id. R_UNLESS(process->GetProcessId() == process_id, RO::ResultInvalidProcess); @@ -315,7 +315,7 @@ public: R_UNLESS(this->GetContextByProcessId(process_id) == nullptr, RO::ResultInvalidSession); // Allocate a context to manage the process handle. - *out_context_id = this->AllocateContext(kernel, process, process_id); + *out_context_id = this->AllocateContext(process, process_id); R_SUCCEED(); } @@ -327,8 +327,8 @@ public: R_SUCCEED(); } - void UnregisterProcess(Kernel::KernelCore& kernel, size_t context_id) { - this->FreeContext(kernel, context_id); + void UnregisterProcess(size_t context_id) { + this->FreeContext(context_id); } Result RegisterModuleInfo(size_t context_id, u64 nrr_address, u64 nrr_size, NrrKind nrr_kind, @@ -481,13 +481,13 @@ private: return nullptr; } - size_t AllocateContext(Kernel::KernelCore& kernel, Kernel::KProcess* process, u64 process_id) { + size_t AllocateContext(Kernel::KProcess* process, u64 process_id) { // Find a free process context. for (size_t i = 0; i < MaxSessions; i++) { ProcessContext* context = std::addressof(process_contexts[i]); if (context->IsFree()) { - context->Initialize(kernel, process, process_id); + context->Initialize(process, process_id); return i; } } @@ -496,9 +496,9 @@ private: UNREACHABLE(); } - void FreeContext(Kernel::KernelCore& kernel, size_t context_id) { + void FreeContext(size_t context_id) { if (ProcessContext* context = GetContextById(context_id); context != nullptr) { - context->Finalize(kernel); + context->Finalize(); } } }; @@ -525,7 +525,7 @@ public: } ~RoInterface() { - m_ro->UnregisterProcess(system.Kernel(), m_context_id); + m_ro->UnregisterProcess(m_context_id); } Result MapManualLoadModuleMemory(Out out_load_address, ClientProcessId client_pid, @@ -551,16 +551,20 @@ public: R_RETURN(m_ro->UnregisterModuleInfo(m_context_id, nrr_address)); } - Result RegisterProcessHandle(ClientProcessId client_pid, InCopyHandle process) { + Result RegisterProcessHandle(ClientProcessId client_pid, + InCopyHandle process) { // Register the process. - R_RETURN(m_ro->RegisterProcess(system.Kernel(), std::addressof(m_context_id), process.Get(), *client_pid)); + R_RETURN(m_ro->RegisterProcess(std::addressof(m_context_id), process.Get(), *client_pid)); } - Result RegisterProcessModuleInfo(ClientProcessId client_pid, u64 nrr_address, u64 nrr_size, InCopyHandle process) { + Result RegisterProcessModuleInfo(ClientProcessId client_pid, u64 nrr_address, u64 nrr_size, + InCopyHandle process) { // Validate the process. R_TRY(m_ro->ValidateProcess(m_context_id, *client_pid)); + // Register the module. - R_RETURN(m_ro->RegisterModuleInfo(m_context_id, nrr_address, nrr_size, m_nrr_kind, m_nrr_kind == NrrKind::JitPlugin)); + R_RETURN(m_ro->RegisterModuleInfo(m_context_id, nrr_address, nrr_size, m_nrr_kind, + m_nrr_kind == NrrKind::JitPlugin)); } private: diff --git a/src/core/hle/service/server_manager.cpp b/src/core/hle/service/server_manager.cpp index ee0dc83ee8..3d898725e8 100644 --- a/src/core/hle/service/server_manager.cpp +++ b/src/core/hle/service/server_manager.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -31,15 +28,13 @@ enum class UserDataTag { class Port : public MultiWaitHolder, public Common::IntrusiveListBaseNode { public: - explicit Port(Kernel::KernelCore& kernel, Kernel::KServerPort* server_port, SessionRequestHandlerFactory&& handler_factory) - : MultiWaitHolder(server_port), m_handler_factory(std::move(handler_factory)) - , m_kernel{kernel} - { + explicit Port(Kernel::KServerPort* server_port, SessionRequestHandlerFactory&& handler_factory) + : MultiWaitHolder(server_port), m_handler_factory(std::move(handler_factory)) { this->SetUserData(static_cast(UserDataTag::Port)); } ~Port() { - this->GetNativeHandle()->Close(m_kernel); + this->GetNativeHandle()->Close(); } SessionRequestHandlerPtr CreateHandler() { @@ -48,20 +43,18 @@ public: private: const SessionRequestHandlerFactory m_handler_factory; - Kernel::KernelCore& m_kernel; }; class Session : public MultiWaitHolder, public Common::IntrusiveListBaseNode { public: - explicit Session(Kernel::KernelCore& kernel, Kernel::KServerSession* server_session, std::shared_ptr&& manager) - : MultiWaitHolder(server_session), m_manager(std::move(manager)) - , m_kernel{kernel} - { + explicit Session(Kernel::KServerSession* server_session, + std::shared_ptr&& manager) + : MultiWaitHolder(server_session), m_manager(std::move(manager)) { this->SetUserData(static_cast(UserDataTag::Session)); } ~Session() { - this->GetNativeHandle()->Close(m_kernel); + this->GetNativeHandle()->Close(); } std::shared_ptr& GetManager() { @@ -75,16 +68,12 @@ public: private: std::shared_ptr m_manager; std::shared_ptr m_context; - Kernel::KernelCore& m_kernel; }; -ServerManager::ServerManager(Core::System& system) - : m_system{system} - , m_selection_mutex{system} -{ +ServerManager::ServerManager(Core::System& system) : m_system{system}, m_selection_mutex{system} { // Initialize event. m_wakeup_event = Kernel::KEvent::Create(system.Kernel()); - m_wakeup_event->Initialize(m_system.Kernel(), nullptr); + m_wakeup_event->Initialize(nullptr); // Register event. Kernel::KEvent::Register(system.Kernel(), m_wakeup_event); @@ -97,7 +86,7 @@ ServerManager::ServerManager(Core::System& system) ServerManager::~ServerManager() { // Signal stop. m_stop_source.request_stop(); - m_wakeup_event->Signal(m_system.Kernel()); + m_wakeup_event->Signal(); // Wait for processing to stop. m_stopped.Wait(); @@ -120,11 +109,11 @@ ServerManager::~ServerManager() { } // Close wakeup event. - m_wakeup_event->GetReadableEvent().Close(m_system.Kernel()); - m_wakeup_event->Close(m_system.Kernel()); + m_wakeup_event->GetReadableEvent().Close(); + m_wakeup_event->Close(); if (m_deferral_event) { - m_deferral_event->GetReadableEvent().Close(m_system.Kernel()); + m_deferral_event->GetReadableEvent().Close(); // Write event is owned by ServiceManager } } @@ -136,7 +125,7 @@ void ServerManager::RunServer(std::unique_ptr&& server_manager) { Result ServerManager::RegisterSession(Kernel::KServerSession* server_session, std::shared_ptr manager) { // We are taking ownership of the server session, so don't open it. - auto* session = new Session(m_system.Kernel(), server_session, std::move(manager)); + auto* session = new Session(server_session, std::move(manager)); // Begin tracking the server session. { @@ -159,7 +148,7 @@ Result ServerManager::RegisterNamedService(const std::string& service_name, max_sessions, handler_factory)); // We are taking ownership of the server port, so don't open it. - auto* server = new Port(m_system.Kernel(), server_port, std::move(handler_factory)); + auto* server = new Port(server_port, std::move(handler_factory)); // Begin tracking the server port. { @@ -188,15 +177,15 @@ Result ServerManager::ManageNamedPort(const std::string& service_name, u32 max_sessions) { // Create a new port. auto* port = Kernel::KPort::Create(m_system.Kernel()); - port->Initialize(m_system.Kernel(), max_sessions, false, 0); + port->Initialize(max_sessions, false, 0); // Register the port. Kernel::KPort::Register(m_system.Kernel(), port); // Ensure that our reference to the port is closed if we fail to register it. SCOPE_EXIT { - port->GetClientPort().Close(m_system.Kernel()); - port->GetServerPort().Close(m_system.Kernel()); + port->GetClientPort().Close(); + port->GetServerPort().Close(); }; // Register the object name with the kernel. @@ -204,10 +193,10 @@ Result ServerManager::ManageNamedPort(const std::string& service_name, service_name.c_str())); // Open a new reference to the server port. - port->GetServerPort().Open(m_system.Kernel()); + port->GetServerPort().Open(); // Transfer ownership into a new port object. - auto* server = new Port(m_system.Kernel(), std::addressof(port->GetServerPort()), std::move(handler_factory)); + auto* server = new Port(std::addressof(port->GetServerPort()), std::move(handler_factory)); // Begin tracking the port. { @@ -228,7 +217,7 @@ Result ServerManager::ManageDeferral(Kernel::KEvent** out_event) { ASSERT(m_deferral_event != nullptr); // Initialize the event. - m_deferral_event->Initialize(m_system.Kernel(), nullptr); + m_deferral_event->Initialize(nullptr); // Register the event. Kernel::KEvent::Register(m_system.Kernel(), m_deferral_event); @@ -269,7 +258,7 @@ void ServerManager::LinkToDeferredList(MultiWaitHolder* holder) { } // Signal the wakeup event. - m_wakeup_event->Signal(m_system.Kernel()); + m_wakeup_event->Signal(); } void ServerManager::LinkDeferred() { @@ -292,7 +281,7 @@ MultiWaitHolder* ServerManager::WaitSignaled() { auto* selected = m_multi_wait.WaitAny(m_system.Kernel()); if (selected == std::addressof(*m_wakeup_holder)) { // Clear and restart if we were woken up. - m_wakeup_event->Clear(m_system.Kernel()); + m_wakeup_event->Clear(); } else { // Unlink and handle the event. selected->UnlinkFromMultiWait(); @@ -334,7 +323,7 @@ Result ServerManager::LoopProcessImpl() { Result ServerManager::OnPortEvent(Port* server) { // Accept a new server session. auto* server_port = static_cast(server->GetNativeHandle()); - Kernel::KServerSession* server_session = server_port->AcceptSession(m_system.Kernel()); + Kernel::KServerSession* server_session = server_port->AcceptSession(); ASSERT(server_session != nullptr); // Create the session manager and install the handler. @@ -356,7 +345,7 @@ Result ServerManager::OnSessionEvent(Session* session) { // Try to receive a message. auto* server_session = static_cast(session->GetNativeHandle()); - res = server_session->ReceiveRequestHLE(m_system.Kernel(), &session->GetContext(), session->GetManager()); + res = server_session->ReceiveRequestHLE(&session->GetContext(), session->GetManager()); // If the session has been closed, we're done. if (res == Kernel::ResultSessionClosed) { @@ -393,7 +382,7 @@ Result ServerManager::CompleteSyncRequest(Session* session) { } // Send the reply. - res = server_session->SendReplyHLE(m_system.Kernel()); + res = server_session->SendReplyHLE(); // If the session has been closed, we're done. if (res == Kernel::ResultSessionClosed || service_res == IPC::ResultSessionClosed) { @@ -412,7 +401,7 @@ Result ServerManager::CompleteSyncRequest(Session* session) { Result ServerManager::OnDeferralEvent() { // Clear event before grabbing the list. - m_deferral_event->Clear(m_system.Kernel()); + m_deferral_event->Clear(); // Get and clear list. const auto deferrals = [&] { diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp index 241533d53b..5332fa3615 100644 --- a/src/core/hle/service/sm/sm.cpp +++ b/src/core/hle/service/sm/sm.cpp @@ -33,11 +33,11 @@ ServiceManager::ServiceManager(Kernel::KernelCore& kernel_) : kernel{kernel_} { ServiceManager::~ServiceManager() { for (auto& [name, port] : service_ports) { - port->Close(kernel); + port->Close(); } if (deferral_event) { - deferral_event->Close(kernel); + deferral_event->Close(); } } @@ -64,7 +64,7 @@ Result ServiceManager::RegisterService(Kernel::KServerPort** out_server_port, st } auto* port = Kernel::KPort::Create(kernel); - port->Initialize(kernel, ServerSessionCountMax, false, 0); + port->Initialize(ServerSessionCountMax, false, 0); // Register the port. Kernel::KPort::Register(kernel, port); @@ -72,7 +72,7 @@ Result ServiceManager::RegisterService(Kernel::KServerPort** out_server_port, st service_ports.emplace(name, std::addressof(port->GetClientPort())); registered_services.emplace(name, handler); if (deferral_event) { - deferral_event->Signal(kernel); + deferral_event->Signal(); } // Set our output. @@ -195,7 +195,7 @@ Result SM::GetServiceImpl(Kernel::KClientSession** out_client_session, HLEReques // Create a new session. Kernel::KClientSession* session{}; - if (const auto result = client_port->CreateSession(kernel, &session); result.IsError()) { + if (const auto result = client_port->CreateSession(&session); result.IsError()) { LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, result.raw); return result; } diff --git a/src/core/hle/service/sm/sm_controller.cpp b/src/core/hle/service/sm/sm_controller.cpp index 7d7ef38152..00c88f6de1 100644 --- a/src/core/hle/service/sm/sm_controller.cpp +++ b/src/core/hle/service/sm/sm_controller.cpp @@ -37,7 +37,8 @@ void Controller::CloneCurrentObject(HLERequestContext& ctx) { // once this is a proper process // Reserve a new session from the process resource limit. - Kernel::KScopedResourceReservation session_reservation(system.Kernel(), Kernel::GetCurrentProcessPointer(kernel), Kernel::LimitableResource::SessionCountMax); + Kernel::KScopedResourceReservation session_reservation( + Kernel::GetCurrentProcessPointer(kernel), Kernel::LimitableResource::SessionCountMax); ASSERT(session_reservation.Succeeded()); // Create the session. @@ -45,7 +46,7 @@ void Controller::CloneCurrentObject(HLERequestContext& ctx) { ASSERT(session != nullptr); // Initialize the session. - session->Initialize(kernel, nullptr, 0); + session->Initialize(nullptr, 0); // Commit the session reservation. session_reservation.Commit(); diff --git a/src/core/hle/service/vi/conductor.cpp b/src/core/hle/service/vi/conductor.cpp index 002c653b8c..801a135dd7 100644 --- a/src/core/hle/service/vi/conductor.cpp +++ b/src/core/hle/service/vi/conductor.cpp @@ -70,7 +70,7 @@ void Conductor::UnlinkVsyncEvent(u64 display_id, Event* event) { void Conductor::ProcessVsync() { for (auto& [display_id, manager] : m_vsync_managers) { m_container.ComposeOnDisplay(&m_swap_interval, &m_compose_speed_scale, display_id); - manager.SignalVsync(m_system.Kernel()); + manager.SignalVsync(); } } diff --git a/src/core/hle/service/vi/vsync_manager.cpp b/src/core/hle/service/vi/vsync_manager.cpp index 59d0b82e0a..bdc4dfa966 100644 --- a/src/core/hle/service/vi/vsync_manager.cpp +++ b/src/core/hle/service/vi/vsync_manager.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -12,10 +9,18 @@ namespace Service::VI { VsyncManager::VsyncManager() = default; VsyncManager::~VsyncManager() = default; -void VsyncManager::SignalVsync(Kernel::KernelCore& kernel) { +void VsyncManager::SignalVsync() { for (auto* event : m_vsync_events) { - event->Signal(kernel); + event->Signal(); } } +void VsyncManager::LinkVsyncEvent(Event* event) { + m_vsync_events.insert(event); +} + +void VsyncManager::UnlinkVsyncEvent(Event* event) { + m_vsync_events.erase(event); +} + } // namespace Service::VI diff --git a/src/core/hle/service/vi/vsync_manager.h b/src/core/hle/service/vi/vsync_manager.h index 9c04516749..5d45bb5eec 100644 --- a/src/core/hle/service/vi/vsync_manager.h +++ b/src/core/hle/service/vi/vsync_manager.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -8,10 +5,6 @@ #include -namespace Kernel { -class KernelCore; -} - namespace Service { class Event; } @@ -25,13 +18,9 @@ public: explicit VsyncManager(); ~VsyncManager(); - void SignalVsync(Kernel::KernelCore& kernel); - void LinkVsyncEvent(Event* event) { - m_vsync_events.insert(event); - } - void UnlinkVsyncEvent(Event* event) { - m_vsync_events.erase(event); - } + void SignalVsync(); + void LinkVsyncEvent(Event* event); + void UnlinkVsyncEvent(Event* event); private: std::set m_vsync_events; diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp index 3286606c5e..74b2ff7018 100644 --- a/src/core/loader/deconstructed_rom_directory.cpp +++ b/src/core/loader/deconstructed_rom_directory.cpp @@ -235,7 +235,7 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect ? ::Settings::values.rng_seed.GetValue() : Common::Random::Random64(0)) << 12) & 0xfff000; // Setup the process code layout - if (process.LoadFromMetadata(system.Kernel(), metadata, code_size, fastmem_base, aslr_offset).IsError()) { + if (process.LoadFromMetadata(metadata, code_size, fastmem_base, aslr_offset).IsError()) { return {ResultStatus::ErrorUnableToParseKernelMetadata, {}}; } diff --git a/src/core/loader/kip.cpp b/src/core/loader/kip.cpp index 62bcbc9579..fdfbac0a20 100644 --- a/src/core/loader/kip.cpp +++ b/src/core/loader/kip.cpp @@ -93,11 +93,11 @@ AppLoader::LoadResult AppLoader_KIP::Load(Kernel::KProcess& process, ? ::Settings::values.rng_seed.GetValue() : Common::Random::Random64(0)) << 12) & 0xfff000; // Setup the process code layout - if (process.LoadFromMetadata(system.Kernel(), FileSys::ProgramMetadata::GetDefault(), codeset.memory.size(), 0, aslr_offset).IsError()) { + if (process.LoadFromMetadata(FileSys::ProgramMetadata::GetDefault(), codeset.memory.size(), 0, aslr_offset).IsError()) { return {ResultStatus::ErrorNotInitialized, {}}; } const VAddr base_address = GetInteger(process.GetEntryPoint()); - process.LoadModule(system.Kernel(), std::move(codeset), base_address); + process.LoadModule(std::move(codeset), base_address); LOG_DEBUG(Loader, "loaded module {} @ {:#X}", kip->GetName(), base_address); diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp index 4ba4bde0bb..21640b7330 100644 --- a/src/core/loader/nro.cpp +++ b/src/core/loader/nro.cpp @@ -280,7 +280,7 @@ static bool LoadNroImpl(Core::System& system, Kernel::KProcess& process, // Setup the process code layout if (process - .LoadFromMetadata(system.Kernel(), FileSys::ProgramMetadata::GetDefault(), image_size, fastmem_base, aslr_offset) + .LoadFromMetadata(FileSys::ProgramMetadata::GetDefault(), image_size, fastmem_base, aslr_offset) .IsError()) { return false; } @@ -296,7 +296,7 @@ static bool LoadNroImpl(Core::System& system, Kernel::KProcess& process, // Load codeset for current process codeset.memory = std::move(program_image); - process.LoadModule(system.Kernel(), std::move(codeset), process.GetEntryPoint()); + process.LoadModule(std::move(codeset), process.GetEntryPoint()); if (!argv_string.empty()) { constexpr u32 kEntryEndOfList = 0; constexpr u32 kEntryMainThreadHandle = 1; @@ -314,14 +314,19 @@ static bool LoadNroImpl(Core::System& system, Kernel::KProcess& process, {kEntryArgv, 0, {0, argv_addr}}, {kEntryEndOfList, 0, {0, 0}}, }; - process.GetMemory().WriteBlock(Common::ProcessAddress{config_addr}, entries, sizeof(entries)); - process.GetMemory().WriteBlock(Common::ProcessAddress{argv_addr}, argv_string.data(), argv_string.size()); + process.GetMemory().WriteBlock(Common::ProcessAddress{config_addr}, entries, + sizeof(entries)); + process.GetMemory().WriteBlock(Common::ProcessAddress{argv_addr}, + argv_string.data(), argv_string.size()); + constexpr size_t kMainThreadHandleValueOffset = offsetof(ConfigEntry, value); process.SetArgPointer(Kernel::KProcessAddress{config_addr}); if (exit_process_offset_in_image) { - process.SetArgReturnAddress(Kernel::KProcessAddress{base + *exit_process_offset_in_image}); + process.SetArgReturnAddress( + Kernel::KProcessAddress{base + *exit_process_offset_in_image}); } - process.SetMainThreadHandleAddr(Kernel::KProcessAddress{config_addr + kMainThreadHandleValueOffset}); + process.SetMainThreadHandleAddr( + Kernel::KProcessAddress{config_addr + kMainThreadHandleValueOffset}); } return true; diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp index a831f44a40..482c853542 100644 --- a/src/core/loader/nso.cpp +++ b/src/core/loader/nso.cpp @@ -217,7 +217,7 @@ std::optional AppLoader_NSO::LoadModule(Kernel::KProcess& process, Core:: } // Load codeset for current process - process.LoadModule(system.Kernel(), std::move(codeset), load_base); + process.LoadModule(std::move(codeset), load_base); return load_base + image_size; } diff --git a/src/core/memory/cheat_engine.cpp b/src/core/memory/cheat_engine.cpp index 8e23a54a0d..dcfd23644f 100644 --- a/src/core/memory/cheat_engine.cpp +++ b/src/core/memory/cheat_engine.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project @@ -91,15 +91,17 @@ u64 StandardVmCallbacks::HidKeysDown() { } void StandardVmCallbacks::PauseProcess() { - if (!system.ApplicationProcess()->IsSuspended()) { - system.ApplicationProcess()->SetActivity(system.Kernel(), Kernel::Svc::ProcessActivity::Paused); + if (system.ApplicationProcess()->IsSuspended()) { + return; } + system.ApplicationProcess()->SetActivity(Kernel::Svc::ProcessActivity::Paused); } void StandardVmCallbacks::ResumeProcess() { - if (system.ApplicationProcess()->IsSuspended()) { - system.ApplicationProcess()->SetActivity(system.Kernel(), Kernel::Svc::ProcessActivity::Runnable); + if (!system.ApplicationProcess()->IsSuspended()) { + return; } + system.ApplicationProcess()->SetActivity(Kernel::Svc::ProcessActivity::Runnable); } void StandardVmCallbacks::DebugLog(u8 id, u64 value) { diff --git a/src/hid_core/hid_core.cpp b/src/hid_core/hid_core.cpp index 12cd0c1f27..410c84afbc 100644 --- a/src/hid_core/hid_core.cpp +++ b/src/hid_core/hid_core.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -13,20 +10,18 @@ namespace Core::HID { -HIDCore::HIDCore(Kernel::KernelCore& kernel_) - : player_1{std::make_unique(NpadIdType::Player1)} - , player_2{std::make_unique(NpadIdType::Player2)} - , player_3{std::make_unique(NpadIdType::Player3)} - , player_4{std::make_unique(NpadIdType::Player4)} - , player_5{std::make_unique(NpadIdType::Player5)} - , player_6{std::make_unique(NpadIdType::Player6)} - , player_7{std::make_unique(NpadIdType::Player7)} - , player_8{std::make_unique(NpadIdType::Player8)} - , other{std::make_unique(NpadIdType::Other)} - , handheld{std::make_unique(NpadIdType::Handheld)} - , console{std::make_unique()}, devices{std::make_unique()} - , kernel{kernel_} -{} +HIDCore::HIDCore() + : player_1{std::make_unique(NpadIdType::Player1)}, + player_2{std::make_unique(NpadIdType::Player2)}, + player_3{std::make_unique(NpadIdType::Player3)}, + player_4{std::make_unique(NpadIdType::Player4)}, + player_5{std::make_unique(NpadIdType::Player5)}, + player_6{std::make_unique(NpadIdType::Player6)}, + player_7{std::make_unique(NpadIdType::Player7)}, + player_8{std::make_unique(NpadIdType::Player8)}, + other{std::make_unique(NpadIdType::Other)}, + handheld{std::make_unique(NpadIdType::Handheld)}, + console{std::make_unique()}, devices{std::make_unique()} {} HIDCore::~HIDCore() = default; diff --git a/src/hid_core/hid_core.h b/src/hid_core/hid_core.h index 7da11897ca..dae29c5062 100644 --- a/src/hid_core/hid_core.h +++ b/src/hid_core/hid_core.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -11,10 +8,6 @@ #include "common/common_funcs.h" #include "hid_core/hid_types.h" -namespace Kernel { -class KernelCore; -} - namespace Core::HID { class EmulatedConsole; class EmulatedController; @@ -25,7 +18,7 @@ namespace Core::HID { class HIDCore { public: - explicit HIDCore(Kernel::KernelCore& kernel); + explicit HIDCore(); ~HIDCore(); YUZU_NON_COPYABLE(HIDCore); @@ -76,6 +69,7 @@ public: /// Number of emulated controllers static constexpr std::size_t available_controllers{10}; +private: std::unique_ptr player_1; std::unique_ptr player_2; std::unique_ptr player_3; @@ -88,7 +82,6 @@ public: std::unique_ptr handheld; std::unique_ptr console; std::unique_ptr devices; - Kernel::KernelCore& kernel; NpadStyleTag supported_style_tag{NpadStyleSet::All}; NpadIdType last_active_controller{NpadIdType::Handheld}; }; diff --git a/src/hid_core/hidbus/ringcon.cpp b/src/hid_core/hidbus/ringcon.cpp index b942cad480..1927a6f856 100644 --- a/src/hid_core/hidbus/ringcon.cpp +++ b/src/hid_core/hidbus/ringcon.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project @@ -141,12 +141,12 @@ bool RingController::SetCommand(std::span data) { case RingConCommands::ReadRepCount: case RingConCommands::ReadTotalPushCount: ASSERT_MSG(data.size() == 0x4, "data.size is not 0x4 bytes"); - send_command_async_event->Signal(system.Kernel()); + send_command_async_event->Signal(); return true; case RingConCommands::ResetRepCount: ASSERT_MSG(data.size() == 0x4, "data.size is not 0x4 bytes"); total_rep_count = 0; - send_command_async_event->Signal(system.Kernel()); + send_command_async_event->Signal(); return true; case RingConCommands::SaveCalData: { ASSERT_MSG(data.size() == 0x14, "data.size is not 0x14 bytes"); @@ -154,14 +154,14 @@ bool RingController::SetCommand(std::span data) { SaveCalData save_info{}; std::memcpy(&save_info, data.data(), sizeof(SaveCalData)); user_calibration = save_info.calibration; - send_command_async_event->Signal(system.Kernel()); + send_command_async_event->Signal(); return true; } default: LOG_ERROR(Service_HID, "Command not implemented {}", command); command = RingConCommands::Error; // Signal a reply to avoid softlocking the game - send_command_async_event->Signal(system.Kernel()); + send_command_async_event->Signal(); return false; } } diff --git a/src/hid_core/resource_manager.cpp b/src/hid_core/resource_manager.cpp index d4d62ea4ba..0c10d1bec9 100644 --- a/src/hid_core/resource_manager.cpp +++ b/src/hid_core/resource_manager.cpp @@ -91,7 +91,7 @@ ResourceManager::~ResourceManager() { system.CoreTiming().UnscheduleEvent(mouse_keyboard_update_event); system.CoreTiming().UnscheduleEvent(motion_update_event); system.CoreTiming().UnscheduleEvent(touch_update_event); - input_event->Finalize(system.Kernel()); + input_event->Finalize(); }; void ResourceManager::Initialize() { @@ -486,7 +486,7 @@ void ResourceManager::UpdateControllers(std::chrono::nanoseconds ns_late) { void ResourceManager::UpdateNpad(std::chrono::nanoseconds ns_late) { auto& core_timing = system.CoreTiming(); - npad->OnUpdate(system.Kernel(), core_timing); + npad->OnUpdate(core_timing); } void ResourceManager::UpdateMouseKeyboard(std::chrono::nanoseconds ns_late) { diff --git a/src/hid_core/resources/abstracted_pad/abstract_battery_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_battery_handler.cpp index a80f8271f9..d5f37247e1 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_battery_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_battery_handler.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -16,9 +16,7 @@ namespace Service::HID { -NpadAbstractBatteryHandler::NpadAbstractBatteryHandler(Kernel::KernelCore& kernel_) - : kernel{kernel_} -{} +NpadAbstractBatteryHandler::NpadAbstractBatteryHandler() {} NpadAbstractBatteryHandler::~NpadAbstractBatteryHandler() = default; diff --git a/src/hid_core/resources/abstracted_pad/abstract_battery_handler.h b/src/hid_core/resources/abstracted_pad/abstract_battery_handler.h index 9c270aa92d..85ac5eb72f 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_battery_handler.h +++ b/src/hid_core/resources/abstracted_pad/abstract_battery_handler.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -10,10 +7,6 @@ #include "core/hle/result.h" #include "hid_core/hid_types.h" -namespace Kernel { -class KernelCore; -} - namespace Service::HID { struct AppletResourceHolder; class NpadAbstractedPadHolder; @@ -22,7 +15,7 @@ class NpadAbstractPropertiesHandler; /// Handles Npad request from HID interfaces class NpadAbstractBatteryHandler final { public: - explicit NpadAbstractBatteryHandler(Kernel::KernelCore& kernel_); + explicit NpadAbstractBatteryHandler(); ~NpadAbstractBatteryHandler(); void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); @@ -51,7 +44,6 @@ private: Core::HID::NpadPowerInfo left_battery{}; Core::HID::NpadPowerInfo right_battery{}; bool has_new_battery_data{}; - Kernel::KernelCore& kernel; }; } // namespace Service::HID diff --git a/src/hid_core/resources/abstracted_pad/abstract_button_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_button_handler.cpp index 239fc7656e..36deb25c94 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_button_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_button_handler.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -16,9 +16,7 @@ namespace Service::HID { -NpadAbstractButtonHandler::NpadAbstractButtonHandler(Kernel::KernelCore& kernel_) - : kernel{kernel_} -{} +NpadAbstractButtonHandler::NpadAbstractButtonHandler() {} NpadAbstractButtonHandler::~NpadAbstractButtonHandler() = default; diff --git a/src/hid_core/resources/abstracted_pad/abstract_button_handler.h b/src/hid_core/resources/abstracted_pad/abstract_button_handler.h index 6e49471b5e..01eafe96df 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_button_handler.h +++ b/src/hid_core/resources/abstracted_pad/abstract_button_handler.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -10,10 +7,6 @@ #include "core/hle/result.h" #include "hid_core/hid_types.h" -namespace Kernel { -class KernelCore; -} - namespace Service::HID { struct NpadSharedMemoryEntry; @@ -24,7 +17,7 @@ class NpadAbstractPropertiesHandler; /// Handles Npad request from HID interfaces class NpadAbstractButtonHandler final { public: - explicit NpadAbstractButtonHandler(Kernel::KernelCore& kernel_); + explicit NpadAbstractButtonHandler(); ~NpadAbstractButtonHandler(); void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); @@ -77,7 +70,6 @@ private: u64 gc_sampling_number{}; GcTrigger gc_trigger_state{}; - Kernel::KernelCore& kernel; }; } // namespace Service::HID diff --git a/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp index a2aaa1d8ec..16ec2257fb 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -14,9 +14,7 @@ namespace Service::HID { -NpadAbstractIrSensorHandler::NpadAbstractIrSensorHandler(Kernel::KernelCore& kernel_) - : kernel{kernel_} -{} +NpadAbstractIrSensorHandler::NpadAbstractIrSensorHandler() {} NpadAbstractIrSensorHandler::~NpadAbstractIrSensorHandler() = default; @@ -54,7 +52,7 @@ void NpadAbstractIrSensorHandler::UpdateIrSensorState() { if (sensor_state == previous_state) { return; } - ir_sensor_event->Signal(kernel); + ir_sensor_event->Signal(); return; } @@ -79,7 +77,7 @@ void NpadAbstractIrSensorHandler::UpdateIrSensorState() { if (sensor_state == previous_state) { return; } - ir_sensor_event->Signal(kernel); + ir_sensor_event->Signal(); return; } @@ -88,7 +86,7 @@ void NpadAbstractIrSensorHandler::UpdateIrSensorState() { return; } - ir_sensor_event->Signal(kernel); + ir_sensor_event->Signal(); return; } @@ -107,7 +105,7 @@ Result NpadAbstractIrSensorHandler::ActivateIrSensor(bool is_enabled) { } sensor_state = NpadIrSensorState::Available; } - ir_sensor_event->Signal(kernel); + ir_sensor_event->Signal(); return ResultSuccess; } diff --git a/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h b/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h index 799d83e82f..9978115116 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h +++ b/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -15,7 +12,6 @@ class EmulatedController; } namespace Kernel { -class KernelCore; class KEvent; class KReadableEvent; } // namespace Kernel @@ -34,7 +30,7 @@ class NpadAbstractPropertiesHandler; /// Handles Npad request from HID interfaces class NpadAbstractIrSensorHandler final { public: - explicit NpadAbstractIrSensorHandler(Kernel::KernelCore& kernel_); + explicit NpadAbstractIrSensorHandler(); ~NpadAbstractIrSensorHandler(); void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); @@ -60,6 +56,5 @@ private: Kernel::KEvent* ir_sensor_event{nullptr}; Core::HID::EmulatedController* xcd_handle{}; NpadIrSensorState sensor_state{}; - Kernel::KernelCore& kernel; }; } // namespace Service::HID diff --git a/src/hid_core/resources/abstracted_pad/abstract_led_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_led_handler.cpp index 94d895509b..813d3d3188 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_led_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_led_handler.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -15,9 +15,7 @@ namespace Service::HID { -NpadAbstractLedHandler::NpadAbstractLedHandler(Kernel::KernelCore& kernel_) - : kernel{kernel_} -{} +NpadAbstractLedHandler::NpadAbstractLedHandler() {} NpadAbstractLedHandler::~NpadAbstractLedHandler() = default; diff --git a/src/hid_core/resources/abstracted_pad/abstract_led_handler.h b/src/hid_core/resources/abstracted_pad/abstract_led_handler.h index 7ff12a9e75..09528129b6 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_led_handler.h +++ b/src/hid_core/resources/abstracted_pad/abstract_led_handler.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -10,10 +7,6 @@ #include "core/hle/result.h" #include "hid_core/hid_types.h" -namespace Kernel { -class KernelCore; -} - namespace Service::HID { struct AppletResourceHolder; class NpadAbstractedPadHolder; @@ -22,7 +15,7 @@ class NpadAbstractPropertiesHandler; /// Handles Npad request from HID interfaces class NpadAbstractLedHandler final { public: - explicit NpadAbstractLedHandler(Kernel::KernelCore& kernel_); + explicit NpadAbstractLedHandler(); ~NpadAbstractLedHandler(); void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); @@ -46,6 +39,5 @@ private: Core::HID::LedPattern left_pattern{0, 0, 0, 0}; Core::HID::LedPattern right_pattern{0, 0, 0, 0}; u64 led_interval{}; - Kernel::KernelCore& kernel; }; } // namespace Service::HID diff --git a/src/hid_core/resources/abstracted_pad/abstract_mcu_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_mcu_handler.cpp index d87446030a..2b763d8e0f 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_mcu_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_mcu_handler.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -12,9 +12,7 @@ namespace Service::HID { -NpadAbstractMcuHandler::NpadAbstractMcuHandler(Kernel::KernelCore& kernel_) - : kernel{kernel_} -{} +NpadAbstractMcuHandler::NpadAbstractMcuHandler() {} NpadAbstractMcuHandler::~NpadAbstractMcuHandler() = default; diff --git a/src/hid_core/resources/abstracted_pad/abstract_mcu_handler.h b/src/hid_core/resources/abstracted_pad/abstract_mcu_handler.h index 44be82cd43..9902dd03a7 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_mcu_handler.h +++ b/src/hid_core/resources/abstracted_pad/abstract_mcu_handler.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -10,10 +7,6 @@ #include "core/hle/result.h" #include "hid_core/hid_types.h" -namespace Kernel { -class KernelCore; -} - namespace Service::HID { struct IAbstractedPad; class NpadAbstractedPadHolder; @@ -35,7 +28,7 @@ static_assert(sizeof(NpadMcuHolder) == 0x10, "NpadMcuHolder is an invalid size") /// Handles Npad request from HID interfaces class NpadAbstractMcuHandler final { public: - explicit NpadAbstractMcuHandler(Kernel::KernelCore& kernel_); + explicit NpadAbstractMcuHandler(); ~NpadAbstractMcuHandler(); void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); @@ -55,6 +48,5 @@ private: s32 ref_counter{}; std::array mcu_holder{}; - Kernel::KernelCore& kernel; }; } // namespace Service::HID diff --git a/src/hid_core/resources/abstracted_pad/abstract_nfc_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_nfc_handler.cpp index 9990add4cc..80f5f3ba62 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_nfc_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_nfc_handler.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -14,9 +14,7 @@ namespace Service::HID { -NpadAbstractNfcHandler::NpadAbstractNfcHandler(Kernel::KernelCore& kernel_) - : kernel{kernel_} -{} +NpadAbstractNfcHandler::NpadAbstractNfcHandler() {} NpadAbstractNfcHandler::~NpadAbstractNfcHandler() = default; @@ -50,13 +48,13 @@ void NpadAbstractNfcHandler::UpdateNfcState() { if (count == 0) { if (sensor_state == NpadNfcState::Active) { - nfc_activate_event->Signal(kernel); + nfc_activate_event->Signal(); } if (sensor_state == NpadNfcState::Unavailable) { return; } sensor_state = NpadNfcState::Unavailable; - input_event->Signal(kernel); + input_event->Signal(); return; } @@ -81,18 +79,19 @@ void NpadAbstractNfcHandler::UpdateNfcState() { return; } sensor_state = NpadNfcState::Available; - input_event->Signal(kernel); + input_event->Signal(); return; } if (sensor_state == NpadNfcState::Active) { - nfc_activate_event->Signal(kernel); + nfc_activate_event->Signal(); } if (sensor_state == NpadNfcState::Unavailable) { return; } sensor_state = NpadNfcState::Unavailable; - input_event->Signal(kernel); + input_event->Signal(); + return; } bool NpadAbstractNfcHandler::HasNfcSensor() { @@ -124,7 +123,7 @@ Result NpadAbstractNfcHandler::ActivateNfc(bool is_enabled) { } if (sensor_state != new_state) { sensor_state = new_state; - nfc_activate_event->Signal(kernel); + nfc_activate_event->Signal(); } return ResultSuccess; } diff --git a/src/hid_core/resources/abstracted_pad/abstract_nfc_handler.h b/src/hid_core/resources/abstracted_pad/abstract_nfc_handler.h index 223a0afd4e..0702722a6b 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_nfc_handler.h +++ b/src/hid_core/resources/abstracted_pad/abstract_nfc_handler.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -11,9 +8,7 @@ #include "hid_core/hid_types.h" namespace Kernel { -class KernelCore; class KReadableEvent; -class KEvent; } enum class NpadNfcState : u32 { @@ -29,7 +24,7 @@ class NpadAbstractPropertiesHandler; /// Handles Npad request from HID interfaces class NpadAbstractNfcHandler final { public: - explicit NpadAbstractNfcHandler(Kernel::KernelCore& kernel_); + explicit NpadAbstractNfcHandler(); ~NpadAbstractNfcHandler(); void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); @@ -58,6 +53,5 @@ private: Kernel::KEvent* input_event{nullptr}; u64 xcd_handle{}; NpadNfcState sensor_state{NpadNfcState::Unavailable}; - Kernel::KernelCore& kernel; }; } // namespace Service::HID diff --git a/src/hid_core/resources/abstracted_pad/abstract_pad.cpp b/src/hid_core/resources/abstracted_pad/abstract_pad.cpp index b828c9b11e..d7cf2bba9b 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_pad.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_pad.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -12,20 +12,7 @@ namespace Service::HID { -AbstractPad::AbstractPad(Kernel::KernelCore& kernel_) - //: abstract_pad_holder{kernel_} - : properties_handler{kernel_} - , led_handler{kernel_} - , ir_sensor_handler{kernel_} - , nfc_handler{kernel_} - , mcu_handler{kernel_} - , vibration_handler{kernel_} - , sixaxis_handler{kernel_} - , button_handler{kernel_} - , battery_handler{kernel_} - , palma_handler{kernel_} - , kernel{kernel_} -{} +AbstractPad::AbstractPad() {} AbstractPad::~AbstractPad() = default; diff --git a/src/hid_core/resources/abstracted_pad/abstract_pad.h b/src/hid_core/resources/abstracted_pad/abstract_pad.h index 99d886d40c..3297924574 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_pad.h +++ b/src/hid_core/resources/abstracted_pad/abstract_pad.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -30,10 +27,6 @@ #include "hid_core/resources/vibration/n64_vibration_device.h" #include "hid_core/resources/vibration/vibration_device.h" -namespace Kernel { -class KernelCore; -} - namespace Service::HID { class AppletResource; class SixAxisResource; @@ -56,7 +49,7 @@ struct HandheldConfig; /// Handles Npad request from HID interfaces class AbstractPad final { public: - explicit AbstractPad(Kernel::KernelCore& kernel_); + explicit AbstractPad(); ~AbstractPad(); void SetExternals(AppletResourceHolder* applet_resource, @@ -95,19 +88,17 @@ public: private: AppletResourceHolder* applet_resource_holder{nullptr}; - - // TODO: fix NpadAbstractedPadHolder abstract_pad_holder{}; - NpadAbstractPropertiesHandler properties_handler; - NpadAbstractLedHandler led_handler; - NpadAbstractIrSensorHandler ir_sensor_handler; - NpadAbstractNfcHandler nfc_handler; - NpadAbstractMcuHandler mcu_handler; - NpadAbstractVibrationHandler vibration_handler; - NpadAbstractSixAxisHandler sixaxis_handler; - NpadAbstractButtonHandler button_handler; - NpadAbstractBatteryHandler battery_handler; - NpadAbstractPalmaHandler palma_handler; + NpadAbstractPropertiesHandler properties_handler{}; + NpadAbstractLedHandler led_handler{}; + NpadAbstractIrSensorHandler ir_sensor_handler{}; + NpadAbstractNfcHandler nfc_handler{}; + NpadAbstractMcuHandler mcu_handler{}; + NpadAbstractVibrationHandler vibration_handler{}; + NpadAbstractSixAxisHandler sixaxis_handler{}; + NpadAbstractButtonHandler button_handler{}; + NpadAbstractBatteryHandler battery_handler{}; + NpadAbstractPalmaHandler palma_handler{}; NpadN64VibrationDevice vibration_n64{}; NpadVibrationDevice vibration_left{}; @@ -123,7 +114,6 @@ private: s32 ref_counter{}; Core::HID::NpadInterfaceType interface_type{Core::HID::NpadInterfaceType::None}; - Kernel::KernelCore& kernel; }; using FullAbstractPad = std::array; diff --git a/src/hid_core/resources/abstracted_pad/abstract_palma_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_palma_handler.cpp index 981f92ea00..7766bedfd0 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_palma_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_palma_handler.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -10,9 +10,7 @@ namespace Service::HID { -NpadAbstractPalmaHandler::NpadAbstractPalmaHandler(Kernel::KernelCore& kernel_) - : kernel{kernel_} -{} +NpadAbstractPalmaHandler::NpadAbstractPalmaHandler() {} NpadAbstractPalmaHandler::~NpadAbstractPalmaHandler() = default; diff --git a/src/hid_core/resources/abstracted_pad/abstract_palma_handler.h b/src/hid_core/resources/abstracted_pad/abstract_palma_handler.h index c09572a7b6..fbd2e67e53 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_palma_handler.h +++ b/src/hid_core/resources/abstracted_pad/abstract_palma_handler.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -10,10 +7,6 @@ #include "core/hle/result.h" #include "hid_core/hid_types.h" -namespace Kernel { -class KernelCore; -} - namespace Service::HID { class NpadAbstractedPadHolder; class NpadAbstractPropertiesHandler; @@ -21,7 +14,7 @@ class PalmaResource; class NpadAbstractPalmaHandler final { public: - explicit NpadAbstractPalmaHandler(Kernel::KernelCore& kernel_); + explicit NpadAbstractPalmaHandler(); ~NpadAbstractPalmaHandler(); void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); @@ -39,7 +32,6 @@ private: PalmaResource* palma_resource{nullptr}; s32 ref_counter{}; - Kernel::KernelCore& kernel; }; } // namespace Service::HID diff --git a/src/hid_core/resources/abstracted_pad/abstract_properties_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_properties_handler.cpp index db011bc6dd..c225670043 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_properties_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_properties_handler.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -14,9 +14,7 @@ namespace Service::HID { -NpadAbstractPropertiesHandler::NpadAbstractPropertiesHandler(Kernel::KernelCore& kernel_) - : kernel{kernel_} -{} +NpadAbstractPropertiesHandler::NpadAbstractPropertiesHandler() {} NpadAbstractPropertiesHandler::~NpadAbstractPropertiesHandler() = default; diff --git a/src/hid_core/resources/abstracted_pad/abstract_properties_handler.h b/src/hid_core/resources/abstracted_pad/abstract_properties_handler.h index 1b8cf4be82..fa68278998 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_properties_handler.h +++ b/src/hid_core/resources/abstracted_pad/abstract_properties_handler.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -13,10 +10,6 @@ #include "hid_core/hid_types.h" #include "hid_core/resources/npad/npad_types.h" -namespace Kernel { -class KernelCore; -} - namespace Service::HID { struct NpadSharedMemoryEntry; @@ -32,7 +25,7 @@ struct ColorProperties { /// Handles Npad request from HID interfaces class NpadAbstractPropertiesHandler final { public: - explicit NpadAbstractPropertiesHandler(Kernel::KernelCore& kernel_); + explicit NpadAbstractPropertiesHandler(); ~NpadAbstractPropertiesHandler(); void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); @@ -89,6 +82,5 @@ private: ColorProperties fullkey_color{}; ColorProperties left_color{}; ColorProperties right_color{}; - Kernel::KernelCore& kernel; }; } // namespace Service::HID diff --git a/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.cpp index 54055751a2..a8d2e5b2a0 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -15,9 +15,7 @@ namespace Service::HID { -NpadAbstractSixAxisHandler::NpadAbstractSixAxisHandler(Kernel::KernelCore& kernel_) - : kernel{kernel_} -{} +NpadAbstractSixAxisHandler::NpadAbstractSixAxisHandler() {} NpadAbstractSixAxisHandler::~NpadAbstractSixAxisHandler() = default; diff --git a/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.h b/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.h index c126c25a23..9c20459e91 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.h +++ b/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -9,11 +6,6 @@ #include "common/common_types.h" #include "core/hle/result.h" #include "hid_core/hid_types.h" -#include "hid_core/resources/shared_memory_format.h" - -namespace Kernel { -class KernelCore; -} namespace Service::HID { class SixAxisResource; @@ -25,7 +17,7 @@ struct NpadSixAxisSensorLifo; /// Handles Npad request from HID interfaces class NpadAbstractSixAxisHandler final { public: - explicit NpadAbstractSixAxisHandler(Kernel::KernelCore& kernel_); + explicit NpadAbstractSixAxisHandler(); ~NpadAbstractSixAxisHandler(); void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); @@ -64,7 +56,6 @@ private: SixAxisResource* six_axis_resource{nullptr}; s32 ref_counter{}; - Kernel::KernelCore& kernel; }; } // namespace Service::HID diff --git a/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp index a0a37806fc..3266422133 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -19,9 +19,7 @@ namespace Service::HID { -NpadAbstractVibrationHandler::NpadAbstractVibrationHandler(Kernel::KernelCore& kernel_) - : kernel{kernel_} -{} +NpadAbstractVibrationHandler::NpadAbstractVibrationHandler() {} NpadAbstractVibrationHandler::~NpadAbstractVibrationHandler() = default; diff --git a/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.h b/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.h index d57bf27814..8bc8129c24 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.h +++ b/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -12,10 +9,6 @@ #include "core/hle/result.h" #include "hid_core/hid_types.h" -namespace Kernel { -class KernelCore; -} - namespace Core::HID { class HIDCore; } @@ -32,7 +25,7 @@ class NpadVibration; /// Keeps track of battery levels and updates npad battery shared memory values class NpadAbstractVibrationHandler final { public: - explicit NpadAbstractVibrationHandler(Kernel::KernelCore& kernel_); + explicit NpadAbstractVibrationHandler(); ~NpadAbstractVibrationHandler(); void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); @@ -62,6 +55,5 @@ private: NpadGcVibrationDevice* gc_vibration_device{nullptr}; NpadVibration* vibration_handler{nullptr}; s32 ref_counter{}; - Kernel::KernelCore& kernel; }; } // namespace Service::HID diff --git a/src/hid_core/resources/applet_resource.cpp b/src/hid_core/resources/applet_resource.cpp index a7b9658cac..31480a0e90 100644 --- a/src/hid_core/resources/applet_resource.cpp +++ b/src/hid_core/resources/applet_resource.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -14,10 +14,7 @@ namespace Service::HID { AppletResource::AppletResource(Core::System& system_) : system{system_} {} -AppletResource::~AppletResource() { - for (size_t i = 0; i < shared_memory_holder.size(); ++i) - shared_memory_holder[i].Finalize(system); -} +AppletResource::~AppletResource() = default; Result AppletResource::CreateAppletResource(u64 aruid) { const u64 index = GetIndexFromAruid(aruid); @@ -37,7 +34,7 @@ Result AppletResource::CreateAppletResource(u64 aruid) { return result; } if (shared_memory.GetAddress() == nullptr) { - shared_memory.Finalize(system); + shared_memory.Finalize(); return ResultSharedMemoryNotInitialized; } } @@ -142,7 +139,7 @@ void AppletResource::FreeAppletResourceId(u64 aruid) { if (aruid_data.flag.is_assigned) { aruid_data.shared_memory_format = nullptr; aruid_data.flag.is_assigned.Assign(false); - shared_memory_holder[index].Finalize(system); + shared_memory_holder[index].Finalize(); } } diff --git a/src/hid_core/resources/npad/npad.cpp b/src/hid_core/resources/npad/npad.cpp index 8e309238d2..04d8a85301 100644 --- a/src/hid_core/resources/npad/npad.cpp +++ b/src/hid_core/resources/npad/npad.cpp @@ -29,36 +29,21 @@ namespace Service::HID { NPad::NPad(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service_context_) - : hid_core{hid_core_} - , service_context{service_context_} - , npad_resource{hid_core_.kernel, service_context} - , abstracted_pads{{ - AbstractPad{hid_core_.kernel}, - AbstractPad{hid_core_.kernel}, - AbstractPad{hid_core_.kernel}, - AbstractPad{hid_core_.kernel}, - AbstractPad{hid_core_.kernel}, - AbstractPad{hid_core_.kernel}, - AbstractPad{hid_core_.kernel}, - AbstractPad{hid_core_.kernel}, - AbstractPad{hid_core_.kernel}, - AbstractPad{hid_core_.kernel}, - }} -{ + : hid_core{hid_core_}, service_context{service_context_}, npad_resource{service_context} { for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; ++aruid_index) { for (std::size_t i = 0; i < controller_data[aruid_index].size(); ++i) { auto& controller = controller_data[aruid_index][i]; controller.device = hid_core.GetEmulatedControllerByIndex(i); Core::HID::ControllerUpdateCallback engine_callback{ - .on_change = [this, i](Core::HID::ControllerTriggerType type) { - ControllerUpdate(hid_core.kernel, type, i); - }, + .on_change = + [this, i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); }, .is_npad_service = true, }; controller.callback_key = controller.device->SetCallback(engine_callback); } } for (std::size_t i = 0; i < abstracted_pads.size(); ++i) { + abstracted_pads[i] = AbstractPad{}; abstracted_pads[i].SetNpadId(IndexToNpadIdType(i)); } } @@ -138,10 +123,10 @@ void NPad::FreeAppletResourceId(u64 aruid) { return npad_resource.FreeAppletResourceId(aruid); } -void NPad::ControllerUpdate(Kernel::KernelCore& kernel, Core::HID::ControllerTriggerType type, std::size_t controller_idx) { +void NPad::ControllerUpdate(Core::HID::ControllerTriggerType type, std::size_t controller_idx) { if (type == Core::HID::ControllerTriggerType::All) { - ControllerUpdate(kernel, Core::HID::ControllerTriggerType::Connected, controller_idx); - ControllerUpdate(kernel, Core::HID::ControllerTriggerType::Battery, controller_idx); + ControllerUpdate(Core::HID::ControllerTriggerType::Connected, controller_idx); + ControllerUpdate(Core::HID::ControllerTriggerType::Battery, controller_idx); return; } @@ -166,7 +151,7 @@ void NPad::ControllerUpdate(Kernel::KernelCore& kernel, Core::HID::ControllerTri if (is_connected == controller.is_connected) { return; } - UpdateControllerAt(kernel, data->aruid, npad_type, npad_id, is_connected); + UpdateControllerAt(data->aruid, npad_type, npad_id, is_connected); break; case Core::HID::ControllerTriggerType::Battery: { if (!controller.device->IsConnected()) { @@ -188,7 +173,7 @@ void NPad::ControllerUpdate(Kernel::KernelCore& kernel, Core::HID::ControllerTri } } -void NPad::InitNewlyAddedController(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadIdType npad_id) { +void NPad::InitNewlyAddedController(u64 aruid, Core::HID::NpadIdType npad_id) { auto& controller = GetControllerFromNpadIdType(aruid, npad_id); if (!npad_resource.IsControllerSupported(aruid, controller.device->GetNpadStyleIndex())) { return; @@ -203,7 +188,7 @@ void NPad::InitNewlyAddedController(Kernel::KernelCore& kernel, u64 aruid, Core: return; } if (controller_type == Core::HID::NpadStyleIndex::None) { - npad_resource.SignalStyleSetUpdateEvent(kernel, aruid, npad_id); + npad_resource.SignalStyleSetUpdateEvent(aruid, npad_id); return; } @@ -387,7 +372,7 @@ void NPad::InitNewlyAddedController(Kernel::KernelCore& kernel, u64 aruid, Core: Common::Input::PollingMode::Active); } - npad_resource.SignalStyleSetUpdateEvent(kernel, aruid, npad_id); + npad_resource.SignalStyleSetUpdateEvent(aruid, npad_id); WriteEmptyEntry(controller.shared_memory); hid_core.SetLastActiveController(npad_id); abstracted_pads[NpadIdTypeToIndex(npad_id)].Update(); @@ -414,20 +399,20 @@ void NPad::WriteEmptyEntry(NpadInternalState* npad) { npad->gc_trigger_lifo.WriteNextEntry(dummy_gc_state); } -void NPad::RequestPadStateUpdate(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadIdType npad_id) { +void NPad::RequestPadStateUpdate(u64 aruid, Core::HID::NpadIdType npad_id) { std::scoped_lock lock{*applet_resource_holder.shared_mutex}; auto& controller = GetControllerFromNpadIdType(aruid, npad_id); const auto controller_type = controller.device->GetNpadStyleIndex(); if (!controller.device->IsConnected() && controller.is_connected) { - DisconnectNpad(kernel, aruid, npad_id); + DisconnectNpad(aruid, npad_id); return; } if (!controller.device->IsConnected()) { return; } if (controller.device->IsConnected() && !controller.is_connected) { - InitNewlyAddedController(kernel, aruid, npad_id); + InitNewlyAddedController(aruid, npad_id); } // This function is unique to yuzu for the turbo buttons and motion to work properly @@ -483,7 +468,7 @@ void NPad::RequestPadStateUpdate(Kernel::KernelCore& kernel, u64 aruid, Core::HI } } -void NPad::OnUpdate(Kernel::KernelCore& kernel, const Core::Timing::CoreTiming& core_timing) { +void NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) { if (ref_counter == 0) { return; } @@ -525,7 +510,7 @@ void NPad::OnUpdate(Kernel::KernelCore& kernel, const Core::Timing::CoreTiming& continue; } - RequestPadStateUpdate(kernel, aruid, controller.device->GetNpadIdType()); + RequestPadStateUpdate(aruid, controller.device->GetNpadIdType()); auto& pad_state = controller.npad_pad_state; auto& libnx_state = controller.npad_libnx_state; auto& trigger_state = controller.npad_trigger_state; @@ -642,17 +627,17 @@ void NPad::OnUpdate(Kernel::KernelCore& kernel, const Core::Timing::CoreTiming& } } -Result NPad::SetSupportedNpadStyleSet(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadStyleSet supported_style_set) { +Result NPad::SetSupportedNpadStyleSet(u64 aruid, Core::HID::NpadStyleSet supported_style_set) { std::scoped_lock lock{mutex}; hid_core.SetSupportedStyleTag({supported_style_set}); const Result result = npad_resource.SetSupportedNpadStyleSet(aruid, supported_style_set); if (result.IsSuccess()) { - OnUpdate(kernel, {}); + OnUpdate({}); } return result; } -Result NPad::GetSupportedNpadStyleSet(Kernel::KernelCore& kernel, u64 aruid, +Result NPad::GetSupportedNpadStyleSet(u64 aruid, Core::HID::NpadStyleSet& out_supported_style_set) const { std::scoped_lock lock{mutex}; const Result result = npad_resource.GetSupportedNpadStyleSet(out_supported_style_set, aruid); @@ -665,7 +650,8 @@ Result NPad::GetSupportedNpadStyleSet(Kernel::KernelCore& kernel, u64 aruid, return result; } -Result NPad::GetMaskedSupportedNpadStyleSet(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadStyleSet& out_supported_style_set) const { +Result NPad::GetMaskedSupportedNpadStyleSet( + u64 aruid, Core::HID::NpadStyleSet& out_supported_style_set) const { std::scoped_lock lock{mutex}; const Result result = npad_resource.GetMaskedSupportedNpadStyleSet(out_supported_style_set, aruid); @@ -678,7 +664,8 @@ Result NPad::GetMaskedSupportedNpadStyleSet(Kernel::KernelCore& kernel, u64 arui return result; } -Result NPad::SetSupportedNpadIdType(Kernel::KernelCore& kernel, u64 aruid, std::span supported_npad_list) { +Result NPad::SetSupportedNpadIdType(u64 aruid, + std::span supported_npad_list) { std::scoped_lock lock{mutex}; if (supported_npad_list.size() > MaxSupportedNpadIdTypes) { return ResultInvalidArraySize; @@ -687,7 +674,7 @@ Result NPad::SetSupportedNpadIdType(Kernel::KernelCore& kernel, u64 aruid, std:: Result result = npad_resource.SetSupportedNpadIdType(aruid, supported_npad_list); if (result.IsSuccess()) { - OnUpdate(kernel, {}); + OnUpdate({}); } return result; @@ -703,21 +690,22 @@ Result NPad::GetNpadJoyHoldType(u64 aruid, NpadJoyHoldType& out_hold_type) const return npad_resource.GetNpadJoyHoldType(out_hold_type, aruid); } -Result NPad::SetNpadHandheldActivationMode(Kernel::KernelCore& kernel, u64 aruid, NpadHandheldActivationMode mode) { +Result NPad::SetNpadHandheldActivationMode(u64 aruid, NpadHandheldActivationMode mode) { std::scoped_lock lock{mutex}; Result result = npad_resource.SetNpadHandheldActivationMode(aruid, mode); if (result.IsSuccess()) { - OnUpdate(kernel, {}); + OnUpdate({}); } return result; } -Result NPad::GetNpadHandheldActivationMode(Kernel::KernelCore& kernel, u64 aruid, NpadHandheldActivationMode& out_mode) const { +Result NPad::GetNpadHandheldActivationMode(u64 aruid, NpadHandheldActivationMode& out_mode) const { std::scoped_lock lock{mutex}; return npad_resource.GetNpadHandheldActivationMode(out_mode, aruid); } -bool NPad::SetNpadMode(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id, NpadJoyDeviceType npad_device_type, NpadJoyAssignmentMode assignment_mode) { +bool NPad::SetNpadMode(u64 aruid, Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id, + NpadJoyDeviceType npad_device_type, NpadJoyAssignmentMode assignment_mode) { if (!IsNpadIdValid(npad_id)) { LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); return false; @@ -739,17 +727,17 @@ bool NPad::SetNpadMode(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadIdT if (assignment_mode == NpadJoyAssignmentMode::Dual) { if (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft) { - DisconnectNpad(kernel, aruid, npad_id); + DisconnectNpad(aruid, npad_id); controller.is_dual_left_connected = true; controller.is_dual_right_connected = false; - UpdateControllerAt(kernel, aruid, Core::HID::NpadStyleIndex::JoyconDual, npad_id, true); + UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconDual, npad_id, true); return false; } if (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight) { - DisconnectNpad(kernel, aruid, npad_id); + DisconnectNpad(aruid, npad_id); controller.is_dual_left_connected = false; controller.is_dual_right_connected = true; - UpdateControllerAt(kernel, aruid, Core::HID::NpadStyleIndex::JoyconDual, npad_id, true); + UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconDual, npad_id, true); return false; } return false; @@ -763,55 +751,58 @@ bool NPad::SetNpadMode(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadIdT } if (controller.is_dual_left_connected && !controller.is_dual_right_connected) { - DisconnectNpad(kernel, aruid, npad_id); - UpdateControllerAt(kernel, aruid, Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true); + DisconnectNpad(aruid, npad_id); + UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true); return false; } if (!controller.is_dual_left_connected && controller.is_dual_right_connected) { - DisconnectNpad(kernel, aruid, npad_id); - UpdateControllerAt(kernel, aruid, Core::HID::NpadStyleIndex::JoyconRight, npad_id, true); + DisconnectNpad(aruid, npad_id); + UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconRight, npad_id, true); return false; } // We have two controllers connected to the same npad_id we need to split them new_npad_id = hid_core.GetFirstDisconnectedNpadId(); auto& controller_2 = GetControllerFromNpadIdType(aruid, new_npad_id); - DisconnectNpad(kernel, aruid, npad_id); + DisconnectNpad(aruid, npad_id); if (npad_device_type == NpadJoyDeviceType::Left) { - UpdateControllerAt(kernel, aruid, Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true); + UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true); controller_2.is_dual_left_connected = false; controller_2.is_dual_right_connected = true; - UpdateControllerAt(kernel, aruid, Core::HID::NpadStyleIndex::JoyconDual, new_npad_id, true); + UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconDual, new_npad_id, true); } else { - UpdateControllerAt(kernel, aruid, Core::HID::NpadStyleIndex::JoyconRight, npad_id, true); + UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconRight, npad_id, true); controller_2.is_dual_left_connected = true; controller_2.is_dual_right_connected = false; - UpdateControllerAt(kernel, aruid, Core::HID::NpadStyleIndex::JoyconDual, new_npad_id, true); + UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconDual, new_npad_id, true); } return true; } -Result NPad::AcquireNpadStyleSetUpdateEventHandle(Kernel::KernelCore& kernel, u64 aruid, Kernel::KReadableEvent** out_event, Core::HID::NpadIdType npad_id) { +Result NPad::AcquireNpadStyleSetUpdateEventHandle(u64 aruid, Kernel::KReadableEvent** out_event, + Core::HID::NpadIdType npad_id) { std::scoped_lock lock{mutex}; - return npad_resource.AcquireNpadStyleSetUpdateEventHandle(kernel, aruid, out_event, npad_id); + return npad_resource.AcquireNpadStyleSetUpdateEventHandle(aruid, out_event, npad_id); } -void NPad::AddNewControllerAt(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadStyleIndex controller, Core::HID::NpadIdType npad_id) { - UpdateControllerAt(kernel, aruid, controller, npad_id, true); +void NPad::AddNewControllerAt(u64 aruid, Core::HID::NpadStyleIndex controller, + Core::HID::NpadIdType npad_id) { + UpdateControllerAt(aruid, controller, npad_id, true); } -void NPad::UpdateControllerAt(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadStyleIndex type, Core::HID::NpadIdType npad_id, bool connected) { +void NPad::UpdateControllerAt(u64 aruid, Core::HID::NpadStyleIndex type, + Core::HID::NpadIdType npad_id, bool connected) { auto& controller = GetControllerFromNpadIdType(aruid, npad_id); if (!connected) { - DisconnectNpad(kernel, aruid, npad_id); + DisconnectNpad(aruid, npad_id); return; } controller.device->SetNpadStyleIndex(type); - InitNewlyAddedController(kernel, aruid, npad_id); + InitNewlyAddedController(aruid, npad_id); } -Result NPad::DisconnectNpad(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadIdType npad_id) { +Result NPad::DisconnectNpad(u64 aruid, Core::HID::NpadIdType npad_id) { if (!IsNpadIdValid(npad_id)) { LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); return ResultInvalidNpadId; @@ -854,7 +845,7 @@ Result NPad::DisconnectNpad(Kernel::KernelCore& kernel, u64 aruid, Core::HID::Np controller.is_dual_right_connected = true; controller.is_connected = false; controller.device->Disconnect(); - npad_resource.SignalStyleSetUpdateEvent(kernel, aruid, npad_id); + npad_resource.SignalStyleSetUpdateEvent(aruid, npad_id); WriteEmptyEntry(shared_memory); return ResultSuccess; } @@ -887,7 +878,8 @@ Result NPad::ResetIsSixAxisSensorDeviceNewlyAssigned( return ResultSuccess; } -Result NPad::MergeSingleJoyAsDualJoy(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2) { +Result NPad::MergeSingleJoyAsDualJoy(u64 aruid, Core::HID::NpadIdType npad_id_1, + Core::HID::NpadIdType npad_id_2) { if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) { LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1, npad_id_2); @@ -941,11 +933,11 @@ Result NPad::MergeSingleJoyAsDualJoy(Kernel::KernelCore& kernel, u64 aruid, Core } // Disconnect the joycons and connect them as dual joycon at the first index. - DisconnectNpad(kernel, aruid, npad_id_1); - DisconnectNpad(kernel, aruid, npad_id_2); + DisconnectNpad(aruid, npad_id_1); + DisconnectNpad(aruid, npad_id_2); controller_1.is_dual_left_connected = true; controller_1.is_dual_right_connected = true; - AddNewControllerAt(kernel, aruid, Core::HID::NpadStyleIndex::JoyconDual, npad_id_1); + AddNewControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconDual, npad_id_1); return ResultSuccess; } @@ -969,9 +961,11 @@ Result NPad::StopLrAssignmentMode(u64 aruid) { return result; } -Result NPad::SwapNpadAssignment(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2) { +Result NPad::SwapNpadAssignment(u64 aruid, Core::HID::NpadIdType npad_id_1, + Core::HID::NpadIdType npad_id_2) { if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) { - LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1, npad_id_2); + LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1, + npad_id_2); return ResultInvalidNpadId; } if (npad_id_1 == Core::HID::NpadIdType::Handheld || @@ -993,17 +987,20 @@ Result NPad::SwapNpadAssignment(Kernel::KernelCore& kernel, u64 aruid, Core::HID return ResultNpadNotConnected; } - UpdateControllerAt(kernel, aruid, type_index_2, npad_id_1, is_connected_2); - UpdateControllerAt(kernel, aruid, type_index_1, npad_id_2, is_connected_1); + UpdateControllerAt(aruid, type_index_2, npad_id_1, is_connected_2); + UpdateControllerAt(aruid, type_index_1, npad_id_2, is_connected_1); + return ResultSuccess; } -Result NPad::IsUnintendedHomeButtonInputProtectionEnabled(bool& out_is_enabled, u64 aruid, Core::HID::NpadIdType npad_id) const { +Result NPad::IsUnintendedHomeButtonInputProtectionEnabled(bool& out_is_enabled, u64 aruid, + Core::HID::NpadIdType npad_id) const { std::scoped_lock lock{mutex}; return npad_resource.GetHomeProtectionEnabled(out_is_enabled, aruid, npad_id); } -Result NPad::EnableUnintendedHomeButtonInputProtection(u64 aruid, Core::HID::NpadIdType npad_id, bool is_enabled) { +Result NPad::EnableUnintendedHomeButtonInputProtection(u64 aruid, Core::HID::NpadIdType npad_id, + bool is_enabled) { std::scoped_lock lock{mutex}; return npad_resource.SetHomeProtectionEnabled(aruid, npad_id, is_enabled); } @@ -1057,29 +1054,29 @@ Core::HID::NpadButton NPad::GetAndResetPressState() { return static_cast(press_state.exchange(0)); } -Result NPad::ApplyNpadSystemCommonPolicy(Kernel::KernelCore& kernel, u64 aruid) { +Result NPad::ApplyNpadSystemCommonPolicy(u64 aruid) { std::scoped_lock lock{mutex}; const Result result = npad_resource.ApplyNpadSystemCommonPolicy(aruid, false); if (result.IsSuccess()) { - OnUpdate(kernel, {}); + OnUpdate({}); } return result; } -Result NPad::ApplyNpadSystemCommonPolicyFull(Kernel::KernelCore& kernel, u64 aruid) { +Result NPad::ApplyNpadSystemCommonPolicyFull(u64 aruid) { std::scoped_lock lock{mutex}; const Result result = npad_resource.ApplyNpadSystemCommonPolicy(aruid, true); if (result.IsSuccess()) { - OnUpdate(kernel, {}); + OnUpdate({}); } return result; } -Result NPad::ClearNpadSystemCommonPolicy(Kernel::KernelCore& kernel, u64 aruid) { +Result NPad::ClearNpadSystemCommonPolicy(u64 aruid) { std::scoped_lock lock{mutex}; const Result result = npad_resource.ClearNpadSystemCommonPolicy(aruid); if (result.IsSuccess()) { - OnUpdate(kernel, {}); + OnUpdate({}); } return result; } diff --git a/src/hid_core/resources/npad/npad.h b/src/hid_core/resources/npad/npad.h index 3e10f02a7c..99e761127d 100644 --- a/src/hid_core/resources/npad/npad.h +++ b/src/hid_core/resources/npad/npad.h @@ -1,6 +1,3 @@ -// 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 @@ -64,31 +61,37 @@ public: void FreeAppletResourceId(u64 aruid); // When the controller is requesting an update for the shared memory - void OnUpdate(Kernel::KernelCore& kernel, const Core::Timing::CoreTiming& core_timing); + void OnUpdate(const Core::Timing::CoreTiming& core_timing); - Result SetSupportedNpadStyleSet(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadStyleSet supported_style_set); - Result GetSupportedNpadStyleSet(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadStyleSet& out_supported_style_set) const; - Result GetMaskedSupportedNpadStyleSet(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadStyleSet& out_supported_style_set) const; - Result SetSupportedNpadIdType(Kernel::KernelCore& kernel, u64 aruid, std::span supported_npad_list); + Result SetSupportedNpadStyleSet(u64 aruid, Core::HID::NpadStyleSet supported_style_set); + Result GetSupportedNpadStyleSet(u64 aruid, + Core::HID::NpadStyleSet& out_supported_style_set) const; + Result GetMaskedSupportedNpadStyleSet(u64 aruid, + Core::HID::NpadStyleSet& out_supported_style_set) const; + + Result SetSupportedNpadIdType(u64 aruid, + std::span supported_npad_list); Result SetNpadJoyHoldType(u64 aruid, NpadJoyHoldType hold_type); Result GetNpadJoyHoldType(u64 aruid, NpadJoyHoldType& out_hold_type) const; - Result SetNpadHandheldActivationMode(Kernel::KernelCore& kernel, u64 aruid, NpadHandheldActivationMode mode); - Result GetNpadHandheldActivationMode(Kernel::KernelCore& kernel, u64 aruid, NpadHandheldActivationMode& out_mode) const; + Result SetNpadHandheldActivationMode(u64 aruid, NpadHandheldActivationMode mode); + Result GetNpadHandheldActivationMode(u64 aruid, NpadHandheldActivationMode& out_mode) const; - bool SetNpadMode(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id, + bool SetNpadMode(u64 aruid, Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id, NpadJoyDeviceType npad_device_type, NpadJoyAssignmentMode assignment_mode); - Result AcquireNpadStyleSetUpdateEventHandle(Kernel::KernelCore& kernel, u64 aruid, Kernel::KReadableEvent** out_event, + Result AcquireNpadStyleSetUpdateEventHandle(u64 aruid, Kernel::KReadableEvent** out_event, Core::HID::NpadIdType npad_id); // Adds a new controller at an index. - void AddNewControllerAt(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadStyleIndex controller, Core::HID::NpadIdType npad_id); + void AddNewControllerAt(u64 aruid, Core::HID::NpadStyleIndex controller, + Core::HID::NpadIdType npad_id); // Adds a new controller at an index with connection status. - void UpdateControllerAt(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadStyleIndex controller, Core::HID::NpadIdType npad_id, bool connected); + void UpdateControllerAt(u64 aruid, Core::HID::NpadStyleIndex controller, + Core::HID::NpadIdType npad_id, bool connected); - Result DisconnectNpad(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadIdType npad_id); + Result DisconnectNpad(u64 aruid, Core::HID::NpadIdType npad_id); Result IsFirmwareUpdateAvailableForSixAxisSensor( u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle, @@ -107,18 +110,20 @@ public: void ConnectAllDisconnectedControllers(); void ClearAllControllers(); - Result MergeSingleJoyAsDualJoy(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2); + Result MergeSingleJoyAsDualJoy(u64 aruid, Core::HID::NpadIdType npad_id_1, + Core::HID::NpadIdType npad_id_2); Result StartLrAssignmentMode(u64 aruid); Result StopLrAssignmentMode(u64 aruid); - Result SwapNpadAssignment(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2); + Result SwapNpadAssignment(u64 aruid, Core::HID::NpadIdType npad_id_1, + Core::HID::NpadIdType npad_id_2); // Logical OR for all buttons presses on all controllers // Specifically for cheat engine and other features. Core::HID::NpadButton GetAndResetPressState(); - Result ApplyNpadSystemCommonPolicy(Kernel::KernelCore& kernel, u64 aruid); - Result ApplyNpadSystemCommonPolicyFull(Kernel::KernelCore& kernel, u64 aruid); - Result ClearNpadSystemCommonPolicy(Kernel::KernelCore& kernel, u64 aruid); + Result ApplyNpadSystemCommonPolicy(u64 aruid); + Result ApplyNpadSystemCommonPolicyFull(u64 aruid); + Result ClearNpadSystemCommonPolicy(u64 aruid); void SetRevision(u64 aruid, NpadRevision revision); NpadRevision GetRevision(u64 aruid); @@ -175,9 +180,9 @@ private: int callback_key{}; }; - void ControllerUpdate(Kernel::KernelCore& kernel, Core::HID::ControllerTriggerType type, std::size_t controller_idx); - void InitNewlyAddedController(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadIdType npad_id); - void RequestPadStateUpdate(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadIdType npad_id); + void ControllerUpdate(Core::HID::ControllerTriggerType type, std::size_t controller_idx); + void InitNewlyAddedController(u64 aruid, Core::HID::NpadIdType npad_id); + void RequestPadStateUpdate(u64 aruid, Core::HID::NpadIdType npad_id); void WriteEmptyEntry(NpadInternalState* npad); NpadControllerData& GetControllerFromHandle( @@ -204,6 +209,7 @@ private: NpadVibration vibration_handler{}; std::atomic press_state{}; - std::array, AruidIndexMax> controller_data{}; + std::array, AruidIndexMax> + controller_data{}; }; } // namespace Service::HID diff --git a/src/hid_core/resources/npad/npad_resource.cpp b/src/hid_core/resources/npad/npad_resource.cpp index 54f7acab12..08546f8dc4 100644 --- a/src/hid_core/resources/npad/npad_resource.cpp +++ b/src/hid_core/resources/npad/npad_resource.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -13,9 +13,7 @@ namespace Service::HID { -NPadResource::NPadResource(Kernel::KernelCore& kernel_, KernelHelpers::ServiceContext& context) - : service_context{context} -{} +NPadResource::NPadResource(KernelHelpers::ServiceContext& context) : service_context{context} {} NPadResource::~NPadResource() = default; @@ -507,7 +505,9 @@ Result NPadResource::IsAssigningSingleOnSlSrPressEnabled(bool& is_enabled, u64 a return ResultSuccess; } -Result NPadResource::AcquireNpadStyleSetUpdateEventHandle(Kernel::KernelCore& kernel, u64 aruid, Kernel::KReadableEvent** out_event, Core::HID::NpadIdType npad_id) { +Result NPadResource::AcquireNpadStyleSetUpdateEventHandle(u64 aruid, + Kernel::KReadableEvent** out_event, + Core::HID::NpadIdType npad_id) { const u64 aruid_index = GetIndexFromAruid(aruid); if (aruid_index >= AruidIndexMax) { return ResultNpadNotConnected; @@ -526,25 +526,26 @@ Result NPadResource::AcquireNpadStyleSetUpdateEventHandle(Kernel::KernelCore& ke *out_event = &controller_state.style_set_update_event->GetReadableEvent(); if (controller_state.is_styleset_update_event_initialized) { - controller_state.style_set_update_event->Signal(kernel); + controller_state.style_set_update_event->Signal(); } return ResultSuccess; } -Result NPadResource::SignalStyleSetUpdateEvent(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadIdType npad_id) { +Result NPadResource::SignalStyleSetUpdateEvent(u64 aruid, Core::HID::NpadIdType npad_id) { const u64 aruid_index = GetIndexFromAruid(aruid); if (aruid_index >= AruidIndexMax) { return ResultNpadNotConnected; } - auto& controller_state = state[aruid_index].controller_state[NpadIdTypeToIndex(npad_id)]; - if (controller_state.is_styleset_update_event_initialized) { - controller_state.style_set_update_event->Signal(kernel); + auto controller = state[aruid_index].controller_state[NpadIdTypeToIndex(npad_id)]; + if (controller.is_styleset_update_event_initialized) { + controller.style_set_update_event->Signal(); } return ResultSuccess; } -Result NPadResource::GetHomeProtectionEnabled(bool& is_enabled, u64 aruid, Core::HID::NpadIdType npad_id) const { +Result NPadResource::GetHomeProtectionEnabled(bool& is_enabled, u64 aruid, + Core::HID::NpadIdType npad_id) const { const u64 aruid_index = GetIndexFromAruid(aruid); if (aruid_index >= AruidIndexMax) { return ResultNpadNotConnected; @@ -554,7 +555,8 @@ Result NPadResource::GetHomeProtectionEnabled(bool& is_enabled, u64 aruid, Core: return ResultSuccess; } -Result NPadResource::SetHomeProtectionEnabled(u64 aruid, Core::HID::NpadIdType npad_id, bool is_enabled) { +Result NPadResource::SetHomeProtectionEnabled(u64 aruid, Core::HID::NpadIdType npad_id, + bool is_enabled) { const u64 aruid_index = GetIndexFromAruid(aruid); if (aruid_index >= AruidIndexMax) { return ResultNpadNotConnected; diff --git a/src/hid_core/resources/npad/npad_resource.h b/src/hid_core/resources/npad/npad_resource.h index 2d381c4642..8ee5702fd4 100644 --- a/src/hid_core/resources/npad/npad_resource.h +++ b/src/hid_core/resources/npad/npad_resource.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -23,7 +20,6 @@ class System; } namespace Kernel { -class KernelCore; class KReadableEvent; } @@ -41,7 +37,8 @@ struct NpadState { DataStatusFlag flag{}; u64 aruid{}; NPadData data{}; - std::array, MaxSupportedNpadIdTypes> button_config; + std::array, MaxSupportedNpadIdTypes> + button_config; std::array controller_state; NpadRevision npad_revision; }; @@ -49,7 +46,7 @@ struct NpadState { /// Handles Npad request from HID interfaces class NPadResource final { public: - explicit NPadResource(Kernel::KernelCore& kernel, KernelHelpers::ServiceContext& context); + explicit NPadResource(KernelHelpers::ServiceContext& context); ~NPadResource(); NPadData* GetActiveData(); @@ -84,9 +81,11 @@ public: Result GetNpadJoyHoldType(NpadJoyHoldType& hold_type, u64 aruid) const; Result SetNpadHandheldActivationMode(u64 aruid, NpadHandheldActivationMode activation_mode); - Result GetNpadHandheldActivationMode(NpadHandheldActivationMode& activation_mode, u64 aruid) const; + Result GetNpadHandheldActivationMode(NpadHandheldActivationMode& activation_mode, + u64 aruid) const; - Result SetSupportedNpadIdType(u64 aruid, std::span supported_npad_list); + Result SetSupportedNpadIdType(u64 aruid, + std::span supported_npad_list); bool IsControllerSupported(u64 aruid, Core::HID::NpadStyleIndex style_index) const; Result SetLrAssignmentMode(u64 aruid, bool is_enabled); @@ -95,20 +94,28 @@ public: Result SetAssigningSingleOnSlSrPress(u64 aruid, bool is_enabled); Result IsAssigningSingleOnSlSrPressEnabled(bool& is_enabled, u64 aruid) const; - Result AcquireNpadStyleSetUpdateEventHandle(Kernel::KernelCore& kernel, u64 aruid, Kernel::KReadableEvent** out_event, Core::HID::NpadIdType npad_id); - Result SignalStyleSetUpdateEvent(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadIdType npad_id); - Result GetHomeProtectionEnabled(bool& is_enabled, u64 aruid, Core::HID::NpadIdType npad_id) const; + Result AcquireNpadStyleSetUpdateEventHandle(u64 aruid, Kernel::KReadableEvent** out_event, + Core::HID::NpadIdType npad_id); + Result SignalStyleSetUpdateEvent(u64 aruid, Core::HID::NpadIdType npad_id); + + Result GetHomeProtectionEnabled(bool& is_enabled, u64 aruid, + Core::HID::NpadIdType npad_id) const; Result SetHomeProtectionEnabled(u64 aruid, Core::HID::NpadIdType npad_id, bool is_enabled); Result SetNpadAnalogStickUseCenterClamp(u64 aruid, bool is_enabled); - Result SetButtonConfig(u64 aruid, Core::HID::NpadIdType npad_id, std::size_t index, Core::HID::NpadButton button_config); - Core::HID::NpadButton GetButtonConfig(u64 aruid, Core::HID::NpadIdType npad_id, std::size_t index, Core::HID::NpadButton mask, bool is_enabled); + Result SetButtonConfig(u64 aruid, Core::HID::NpadIdType npad_id, std::size_t index, + Core::HID::NpadButton button_config); + Core::HID::NpadButton GetButtonConfig(u64 aruid, Core::HID::NpadIdType npad_id, + std::size_t index, Core::HID::NpadButton mask, + bool is_enabled); void ResetButtonConfig(); - Result SetNpadCaptureButtonAssignment(u64 aruid, Core::HID::NpadStyleSet npad_style_set, Core::HID::NpadButton button_assignment); + Result SetNpadCaptureButtonAssignment(u64 aruid, Core::HID::NpadStyleSet npad_style_set, + Core::HID::NpadButton button_assignment); Result ClearNpadCaptureButtonAssignment(u64 aruid); - std::size_t GetNpadCaptureButtonAssignment(std::span out_list, u64 aruid) const; + std::size_t GetNpadCaptureButtonAssignment(std::span out_list, + u64 aruid) const; Result SetNpadSystemExtStateEnabled(u64 aruid, bool is_enabled); @@ -117,8 +124,9 @@ private: AruidRegisterList registration_list{}; std::array state{}; u64 active_data_aruid{}; - KernelHelpers::ServiceContext& service_context; NpadJoyHoldType default_hold_type{}; s32 ref_counter{}; + + KernelHelpers::ServiceContext& service_context; }; } // namespace Service::HID diff --git a/src/hid_core/resources/palma/palma.cpp b/src/hid_core/resources/palma/palma.cpp index 1a1a3aae18..0652455f5f 100644 --- a/src/hid_core/resources/palma/palma.cpp +++ b/src/hid_core/resources/palma/palma.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project @@ -77,7 +77,7 @@ Result Palma::PlayPalmaActivity(const PalmaConnectionHandle& handle, u64 palma_a operation.operation = PackedPalmaOperationType::PlayActivity; operation.result = PalmaResultSuccess; operation.data = {}; - operation_complete_event->Signal(hid_core.kernel); + operation_complete_event->Signal(); return ResultSuccess; } @@ -96,7 +96,7 @@ Result Palma::ReadPalmaStep(const PalmaConnectionHandle& handle) { operation.operation = PackedPalmaOperationType::ReadStep; operation.result = PalmaResultSuccess; operation.data = {}; - operation_complete_event->Signal(hid_core.kernel); + operation_complete_event->Signal(); return ResultSuccess; } @@ -125,7 +125,7 @@ Result Palma::ReadPalmaUniqueCode(const PalmaConnectionHandle& handle) { operation.operation = PackedPalmaOperationType::ReadUniqueCode; operation.result = PalmaResultSuccess; operation.data = {}; - operation_complete_event->Signal(hid_core.kernel); + operation_complete_event->Signal(); return ResultSuccess; } @@ -136,7 +136,7 @@ Result Palma::SetPalmaUniqueCodeInvalid(const PalmaConnectionHandle& handle) { operation.operation = PackedPalmaOperationType::SetUniqueCodeInvalid; operation.result = PalmaResultSuccess; operation.data = {}; - operation_complete_event->Signal(hid_core.kernel); + operation_complete_event->Signal(); return ResultSuccess; } @@ -149,7 +149,7 @@ Result Palma::WritePalmaRgbLedPatternEntry(const PalmaConnectionHandle& handle, operation.operation = PackedPalmaOperationType::WriteRgbLedPatternEntry; operation.result = PalmaResultSuccess; operation.data = {}; - operation_complete_event->Signal(hid_core.kernel); + operation_complete_event->Signal(); return ResultSuccess; } @@ -161,7 +161,7 @@ Result Palma::WritePalmaWaveEntry(const PalmaConnectionHandle& handle, PalmaWave operation.operation = PackedPalmaOperationType::WriteWaveEntry; operation.result = PalmaResultSuccess; operation.data = {}; - operation_complete_event->Signal(hid_core.kernel); + operation_complete_event->Signal(); return ResultSuccess; } @@ -174,7 +174,7 @@ Result Palma::SetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& operation.operation = PackedPalmaOperationType::ReadDataBaseIdentificationVersion; operation.result = PalmaResultSuccess; operation.data[0] = {}; - operation_complete_event->Signal(hid_core.kernel); + operation_complete_event->Signal(); return ResultSuccess; } @@ -186,7 +186,7 @@ Result Palma::GetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& operation.result = PalmaResultSuccess; operation.data = {}; operation.data[0] = static_cast(database_id_version); - operation_complete_event->Signal(hid_core.kernel); + operation_complete_event->Signal(); return ResultSuccess; } diff --git a/src/hid_core/resources/shared_memory_holder.cpp b/src/hid_core/resources/shared_memory_holder.cpp index c94829821a..ada593d8ba 100644 --- a/src/hid_core/resources/shared_memory_holder.cpp +++ b/src/hid_core/resources/shared_memory_holder.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -12,10 +9,17 @@ #include "hid_core/resources/shared_memory_holder.h" namespace Service::HID { +SharedMemoryHolder::SharedMemoryHolder() {} + +SharedMemoryHolder::~SharedMemoryHolder() { + Finalize(); +} Result SharedMemoryHolder::Initialize(Core::System& system) { shared_memory = Kernel::KSharedMemory::Create(system.Kernel()); - const Result result = shared_memory->Initialize(system.Kernel(), system.DeviceMemory(), nullptr, Kernel::Svc::MemoryPermission::None, Kernel::Svc::MemoryPermission::Read, sizeof(SharedMemoryFormat)); + const Result result = shared_memory->Initialize( + system.DeviceMemory(), nullptr, Kernel::Svc::MemoryPermission::None, + Kernel::Svc::MemoryPermission::Read, sizeof(SharedMemoryFormat)); if (result.IsError()) { return result; } @@ -27,9 +31,9 @@ Result SharedMemoryHolder::Initialize(Core::System& system) { return ResultSuccess; } -void SharedMemoryHolder::Finalize(Core::System& system) { +void SharedMemoryHolder::Finalize() { if (address != nullptr) { - shared_memory->Close(system.Kernel()); + shared_memory->Close(); } is_created = false; is_mapped = false; diff --git a/src/hid_core/resources/shared_memory_holder.h b/src/hid_core/resources/shared_memory_holder.h index 5fcaddecc0..943407c00a 100644 --- a/src/hid_core/resources/shared_memory_holder.h +++ b/src/hid_core/resources/shared_memory_holder.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -22,13 +19,17 @@ struct SharedMemoryFormat; // This is nn::hid::detail::SharedMemoryHolder class SharedMemoryHolder { public: + SharedMemoryHolder(); + ~SharedMemoryHolder(); + Result Initialize(Core::System& system); - void Finalize(Core::System& system); + void Finalize(); bool IsMapped(); SharedMemoryFormat* GetAddress(); Kernel::KSharedMemory* GetHandle(); +private: bool is_owner{}; bool is_created{}; bool is_mapped{}; diff --git a/src/hid_core/resources/touch_screen/touch_screen_resource.cpp b/src/hid_core/resources/touch_screen/touch_screen_resource.cpp index d340f186b3..018a43b6c0 100644 --- a/src/hid_core/resources/touch_screen/touch_screen_resource.cpp +++ b/src/hid_core/resources/touch_screen/touch_screen_resource.cpp @@ -494,7 +494,7 @@ void TouchResource::ReadTouchInput() { has_moved |= (delta_x > 1 || delta_y > 1); } if (has_moved) { - input_event->Signal(system.Kernel()); + input_event->Signal(); } } } diff --git a/src/input_common/drivers/udp_client.cpp b/src/input_common/drivers/udp_client.cpp index 620e0cf630..7566e6040c 100644 --- a/src/input_common/drivers/udp_client.cpp +++ b/src/input_common/drivers/udp_client.cpp @@ -13,7 +13,6 @@ #include "common/param_package.h" #include "common/random.h" #include "common/settings.h" -#include "common/thread.h" #include "input_common/drivers/udp_client.h" #include "input_common/helpers/udp_protocol.h" @@ -134,7 +133,6 @@ private: }; static void SocketLoop(Socket* socket) { - Common::SetCurrentThreadName("cemuhookWorker"); socket->StartReceive(); socket->StartSend(Socket::clock::now()); socket->Loop(); @@ -330,11 +328,9 @@ void UDPClient::OnPadData(Response::PadData data, std::size_t client) { } void UDPClient::StartCommunication(std::size_t client, const std::string& host, u16 port) { - SocketCallback callback{ - [this](Response::Version version) { OnVersion(version); }, - [this](Response::PortInfo info) { OnPortInfo(info); }, - [this, client](Response::PadData data) { OnPadData(data, client); } - }; + SocketCallback callback{[this](Response::Version version) { OnVersion(version); }, + [this](Response::PortInfo info) { OnPortInfo(info); }, + [this, client](Response::PadData data) { OnPadData(data, client); }}; LOG_INFO(Input, "Starting communication with UDP input server on {}:{}", host, port); clients[client].uuid = GetHostUUID(host); clients[client].host = host; @@ -577,7 +573,9 @@ bool UDPClient::IsStickInverted(const Common::ParamPackage& params) { return true; } -void TestCommunication(const std::string& host, u16 port, const std::function& success_callback, const std::function& failure_callback) { +void TestCommunication(const std::string& host, u16 port, + const std::function& success_callback, + const std::function& failure_callback) { std::thread([=] { Common::Event success_event; SocketCallback callback{ @@ -610,38 +608,40 @@ CalibrationConfigurationJob::CalibrationConfigurationJob( u16 max_y{}; Status current_status{Status::Initialized}; - SocketCallback callback{[](Response::Version) {}, [](Response::PortInfo) {}, [&](Response::PadData data) { - constexpr u16 CALIBRATION_THRESHOLD = 100; + SocketCallback callback{[](Response::Version) {}, [](Response::PortInfo) {}, + [&](Response::PadData data) { + constexpr u16 CALIBRATION_THRESHOLD = 100; - if (current_status == Status::Initialized) { - // Receiving data means the communication is ready now - current_status = Status::Ready; - status_callback(current_status); - } - if (data.touch[0].is_active == 0) { - return; - } - LOG_DEBUG(Input, "Current touch: {} {}", data.touch[0].x, data.touch[0].y); - min_x = (std::min)(min_x, u16(data.touch[0].x)); - min_y = (std::min)(min_y, u16(data.touch[0].y)); - if (current_status == Status::Ready) { - // First touch - min data (min_x/min_y) - current_status = Status::Stage1Completed; - status_callback(current_status); - } - if (data.touch[0].x - min_x > CALIBRATION_THRESHOLD && - data.touch[0].y - min_y > CALIBRATION_THRESHOLD) { - // Set the current position as max value and finishes - // configuration - max_x = data.touch[0].x; - max_y = data.touch[0].y; - current_status = Status::Completed; - data_callback(min_x, min_y, max_x, max_y); - status_callback(current_status); + if (current_status == Status::Initialized) { + // Receiving data means the communication is ready now + current_status = Status::Ready; + status_callback(current_status); + } + if (data.touch[0].is_active == 0) { + return; + } + LOG_DEBUG(Input, "Current touch: {} {}", data.touch[0].x, + data.touch[0].y); + min_x = (std::min)(min_x, static_cast(data.touch[0].x)); + min_y = (std::min)(min_y, static_cast(data.touch[0].y)); + if (current_status == Status::Ready) { + // First touch - min data (min_x/min_y) + current_status = Status::Stage1Completed; + status_callback(current_status); + } + if (data.touch[0].x - min_x > CALIBRATION_THRESHOLD && + data.touch[0].y - min_y > CALIBRATION_THRESHOLD) { + // Set the current position as max value and finishes + // configuration + max_x = data.touch[0].x; + max_y = data.touch[0].y; + current_status = Status::Completed; + data_callback(min_x, min_y, max_x, max_y); + status_callback(current_status); - complete_event.Set(); - } - }}; + complete_event.Set(); + } + }}; Socket socket{host, port, std::move(callback)}; std::thread worker_thread{SocketLoop, &socket}; complete_event.Wait(); diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 5c02b5ed90..53b0d1638b 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -334,7 +334,7 @@ if (YUZU_USE_EXTERNAL_FFMPEG) add_dependencies(video_core ffmpeg-build) endif() -target_include_directories(video_core PUBLIC ${FFmpeg_INCLUDE_DIR}) +target_include_directories(video_core PRIVATE ${FFmpeg_INCLUDE_DIR}) target_link_libraries(video_core PRIVATE ${FFmpeg_LIBRARIES}) target_link_options(video_core PRIVATE ${FFmpeg_LDFLAGS}) diff --git a/src/video_core/cdma_pusher.cpp b/src/video_core/cdma_pusher.cpp index 635ca769d8..1f0f8b5a38 100644 --- a/src/video_core/cdma_pusher.cpp +++ b/src/video_core/cdma_pusher.cpp @@ -20,7 +20,8 @@ namespace Tegra { CDmaPusher::CDmaPusher(Host1x::Host1x& host1x_, s32 id) - : host1x{host1x_} + : host_processor(host1x_) + , host1x{host1x_} , current_class{ChClassId(id)} { thread = std::jthread([this](std::stop_token stop_token) { @@ -98,7 +99,7 @@ void CDmaPusher::ExecuteCommand(u32 method, u32 arg) { switch (current_class) { case ChClassId::Control: LOG_TRACE(Service_NVDRV, "Class {} method {:#X} arg 0x{:X}", u32(current_class), method, arg); - host_processor.ProcessMethod(host1x, Host1x::Control::Method(method), arg); + host_processor.ProcessMethod(Host1x::Control::Method(method), arg); break; default: thi_regs.reg_array[method] = arg; diff --git a/src/video_core/control/channel_state.cpp b/src/video_core/control/channel_state.cpp index c6f2c3c2ca..d07c7e2a83 100644 --- a/src/video_core/control/channel_state.cpp +++ b/src/video_core/control/channel_state.cpp @@ -17,36 +17,28 @@ namespace Tegra::Control { -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_}, initialized{} {} -ChannelState::ChannelState(s32 bind_id_) - : bind_id{bind_id_} -{} - -void ChannelState::Init(Core::System& system, u64 program_id_) { +void ChannelState::Init(Core::System& system, GPU& gpu, u64 program_id_) { ASSERT(memory_manager); program_id = program_id_; - payload.emplace(system, *memory_manager, *this); + 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; } void ChannelState::BindRasterizer(VideoCore::RasterizerInterface* rasterizer) { - payload->dma_pusher.BindRasterizer(rasterizer); + 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); + maxwell_3d->BindRasterizer(rasterizer); + fermi_2d->BindRasterizer(rasterizer); + kepler_memory->BindRasterizer(rasterizer); + kepler_compute->BindRasterizer(rasterizer); + maxwell_dma->BindRasterizer(rasterizer); } } // namespace Tegra::Control diff --git a/src/video_core/control/channel_state.h b/src/video_core/control/channel_state.h index 80811c1458..2984d2e09e 100644 --- a/src/video_core/control/channel_state.h +++ b/src/video_core/control/channel_state.h @@ -14,7 +14,6 @@ #include "video_core/engines/kepler_compute.h" #include "video_core/engines/maxwell_3d.h" #include "video_core/engines/maxwell_dma.h" -#include "video_core/engines/nv01_timer.h" #include "video_core/dma_pusher.h" namespace Core { @@ -35,33 +34,28 @@ namespace Control { struct ChannelState { explicit ChannelState(s32 bind_id); - void Init(Core::System& system, u64 program_id); + void Init(Core::System& system, GPU& gpu, u64 program_id); void BindRasterizer(VideoCore::RasterizerInterface* rasterizer); - struct Payload { - explicit Payload(Core::System& system, MemoryManager& memory_manager, ChannelState& channel_state); - - /// 3D engine - Engines::Maxwell3D maxwell_3d; - /// 2D engine - Engines::Fermi2D fermi_2d; - /// Compute engine - Engines::KeplerCompute kepler_compute; - /// DMA engine - Engines::MaxwellDMA maxwell_dma; - /// Inline memory engine - Engines::KeplerMemory kepler_memory; - /// NV01 Timer - Engines::Nv01Timer nv01_timer; - DmaPusher dma_pusher; - }; - std::optional payload; - MemoryManager* memory_manager = nullptr; + /// 3D engine + std::optional maxwell_3d; + /// 2D engine + std::optional fermi_2d; + /// Compute engine + std::optional kepler_compute; + /// DMA engine + std::optional maxwell_dma; + /// Inline memory engine + std::optional kepler_memory; + /// NV01 Timer + std::optional nv01_timer; + std::optional dma_pusher; + std::shared_ptr memory_manager; s32 bind_id = -1; u64 program_id = 0; - bool initialized = false; + bool initialized{}; }; } // namespace Control diff --git a/src/video_core/control/channel_state_cache.cpp b/src/video_core/control/channel_state_cache.cpp index bd794d939a..f8c6a762d2 100644 --- a/src/video_core/control/channel_state_cache.cpp +++ b/src/video_core/control/channel_state_cache.cpp @@ -1,6 +1,3 @@ -// 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 @@ -9,11 +6,8 @@ namespace VideoCommon { ChannelInfo::ChannelInfo(Tegra::Control::ChannelState& channel_state) - : maxwell3d{channel_state.payload->maxwell_3d} - , kepler_compute{channel_state.payload->kepler_compute} - , gpu_memory{*channel_state.memory_manager} - , program_id{channel_state.program_id} - {} + : maxwell3d{*channel_state.maxwell_3d}, kepler_compute{*channel_state.kepler_compute}, + gpu_memory{*channel_state.memory_manager}, program_id{channel_state.program_id} {} template class VideoCommon::ChannelSetupCaches; diff --git a/src/video_core/control/channel_state_cache.inc b/src/video_core/control/channel_state_cache.inc index 5bb15f8907..d882d8222f 100644 --- a/src/video_core/control/channel_state_cache.inc +++ b/src/video_core/control/channel_state_cache.inc @@ -1,6 +1,3 @@ -// 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 @@ -44,7 +41,7 @@ void ChannelSetupCaches

::CreateChannel(struct Tegra::Control::ChannelState& c AddressSpaceRef new_gpu_mem_ref{ .ref_count = 1, .storage_id = address_spaces.size(), - .gpu_memory = channel.memory_manager, + .gpu_memory = channel.memory_manager.get(), }; address_spaces.emplace(channel.memory_manager->GetID(), new_gpu_mem_ref); OnGPUASRegister(channel.memory_manager->GetID()); diff --git a/src/video_core/control/scheduler.cpp b/src/video_core/control/scheduler.cpp index 8af13e415c..bd3b8b860e 100644 --- a/src/video_core/control/scheduler.cpp +++ b/src/video_core/control/scheduler.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: 2021 yuzu Emulator Project @@ -12,8 +12,11 @@ #include "video_core/gpu.h" namespace Tegra::Control { +Scheduler::Scheduler(GPU& gpu_) : gpu{gpu_} {} -void Scheduler::Push(GPU& gpu, s32 channel, CommandList&& entries) { +Scheduler::~Scheduler() = default; + +void Scheduler::Push(s32 channel, CommandList&& entries) { std::shared_ptr channel_state; { std::unique_lock lk(scheduling_guard); @@ -24,8 +27,8 @@ void Scheduler::Push(GPU& gpu, s32 channel, CommandList&& entries) { } // Process commands outside the lock to reduce contention. // Multiple channels can prepare their commands in parallel. - channel_state->payload->dma_pusher.Push(std::move(entries)); - channel_state->payload->dma_pusher.DispatchCalls(); + channel_state->dma_pusher->Push(std::move(entries)); + channel_state->dma_pusher->DispatchCalls(); } void Scheduler::DeclareChannel(std::shared_ptr new_channel) { diff --git a/src/video_core/control/scheduler.h b/src/video_core/control/scheduler.h index fb9c583386..9c2b9de32b 100644 --- a/src/video_core/control/scheduler.h +++ b/src/video_core/control/scheduler.h @@ -22,13 +22,17 @@ struct ChannelState; class Scheduler { public: - void Push(GPU& gpu, s32 channel, CommandList&& entries); + explicit Scheduler(GPU& gpu_); + ~Scheduler(); + + void Push(s32 channel, CommandList&& entries); void DeclareChannel(std::shared_ptr new_channel); private: ankerl::unordered_dense::map> channels; std::mutex scheduling_guard; + GPU& gpu; }; } // namespace Control diff --git a/src/video_core/dma_pusher.cpp b/src/video_core/dma_pusher.cpp index 41bb43f0c1..8a7798e035 100644 --- a/src/video_core/dma_pusher.cpp +++ b/src/video_core/dma_pusher.cpp @@ -12,32 +12,37 @@ #include "video_core/guest_memory.h" #include "video_core/memory_manager.h" #include "video_core/rasterizer_interface.h" +#include "video_core/texture_cache/util.h" + +#ifdef _MSC_VER +#include +#endif namespace Tegra { constexpr u32 MacroRegistersStart = 0xE00; [[maybe_unused]] constexpr u32 ComputeInline = 0x6D; -DmaPusher::DmaPusher(Core::System& system_, MemoryManager& memory_manager_, Control::ChannelState& channel_state_) - : system{system_} - , memory_manager{memory_manager_} - , channel_state{channel_state_} - , signal_sync{false} - , synced{false} -{} +DmaPusher::DmaPusher(Core::System& system_, GPU& gpu_, MemoryManager& memory_manager_, + Control::ChannelState& channel_state_) + : gpu{gpu_}, system{system_}, memory_manager{memory_manager_}, puller{gpu_, memory_manager_, + *this, channel_state_}, signal_sync{false}, synced{true} {} DmaPusher::~DmaPusher() = default; void DmaPusher::DispatchCalls() { + dma_pushbuffer_subindex = 0; + dma_state.is_last_call = true; + while (system.IsPoweredOn()) { if (!Step()) { break; } } - system.GPU().FlushCommands(); - system.GPU().OnCommandListEnd(); + gpu.FlushCommands(); + gpu.OnCommandListEnd(); } bool DmaPusher::Step() { @@ -166,9 +171,9 @@ void DmaPusher::SetState(const CommandHeader& command_header) { dma_state.method_count = command_header.method_count; } -void DmaPusher::CallMethod(u32 argument) { +void DmaPusher::CallMethod(u32 argument) const { if (dma_state.method < non_puller_methods) { - puller.CallPullerMethod(*this, Engines::Puller::MethodCall{ + puller.CallPullerMethod(Engines::Puller::MethodCall{ dma_state.method, argument, dma_state.subchannel, @@ -176,29 +181,30 @@ void DmaPusher::CallMethod(u32 argument) { }); } else { auto subchannel = subchannels[dma_state.subchannel]; - if (!subchannel->execution_mask[dma_state.method]) { - subchannel->method_sink.emplace_back(dma_state.method, argument); - } else { - subchannel->ConsumeSink(system); + if (subchannel->execution_mask[dma_state.method]) { + subchannel->ConsumeSink(); subchannel->current_dma_segment = dma_state.dma_get + dma_state.dma_word_offset; - subchannel->CallMethod(system, dma_state.method, argument, dma_state.is_last_call); + subchannel->CallMethod(dma_state.method, argument, dma_state.is_last_call); + } else { + subchannel->method_sink.emplace_back(dma_state.method, argument); } } } -void DmaPusher::CallMultiMethod(const u32* base_start, u32 num_methods) { +void DmaPusher::CallMultiMethod(const u32* base_start, u32 num_methods) const { if (dma_state.method < non_puller_methods) { - puller.CallMultiMethod(*this, dma_state.method, dma_state.subchannel, base_start, num_methods, dma_state.method_count); + puller.CallMultiMethod(dma_state.method, dma_state.subchannel, base_start, num_methods, dma_state.method_count); } else { auto subchannel = subchannels[dma_state.subchannel]; - subchannel->ConsumeSink(system); + subchannel->ConsumeSink(); subchannel->current_dma_segment = dma_state.dma_get + dma_state.dma_word_offset; - subchannel->CallMultiMethod(system, dma_state.method, base_start, num_methods, dma_state.method_count); + subchannel->CallMultiMethod(dma_state.method, base_start, num_methods, dma_state.method_count); } } void DmaPusher::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) { rasterizer = rasterizer_; + puller.BindRasterizer(rasterizer); } } // namespace Tegra diff --git a/src/video_core/dma_pusher.h b/src/video_core/dma_pusher.h index 62af628511..f850513603 100644 --- a/src/video_core/dma_pusher.h +++ b/src/video_core/dma_pusher.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project @@ -109,21 +109,25 @@ inline CommandHeader BuildCommandHeader(BufferMethods method, u32 arg_count, Sub struct CommandList final { CommandList() = default; explicit CommandList(std::size_t size) : command_lists(size) {} - explicit CommandList(boost::container::small_vector&& prefetch_command_list_) + explicit CommandList( + boost::container::small_vector&& prefetch_command_list_) : prefetch_command_list{std::move(prefetch_command_list_)} {} boost::container::small_vector command_lists; boost::container::small_vector prefetch_command_list; }; -/// @brief The DmaPusher class implements DMA submission to FIFOs, providing an area of memory that the -/// emulated app fills with commands and tells PFIFO to process. The pushbuffers are then assembled -/// into a "command stream" consisting of 32-bit words that make up "commands". -/// See https://envytools.readthedocs.io/en/latest/hw/fifo/dma-pusher.html#fifo-dma-pusher for -/// details on this implementation. +/** + * The DmaPusher class implements DMA submission to FIFOs, providing an area of memory that the + * emulated app fills with commands and tells PFIFO to process. The pushbuffers are then assembled + * into a "command stream" consisting of 32-bit words that make up "commands". + * See https://envytools.readthedocs.io/en/latest/hw/fifo/dma-pusher.html#fifo-dma-pusher for + * details on this implementation. + */ class DmaPusher final { public: - explicit DmaPusher(Core::System& system_, MemoryManager& memory_manager_, Control::ChannelState& channel_state_); + explicit DmaPusher(Core::System& system_, GPU& gpu_, MemoryManager& memory_manager_, + Control::ChannelState& channel_state_); ~DmaPusher(); void Push(CommandList&& entries) { @@ -132,7 +136,8 @@ public: void DispatchCalls(); - void BindSubchannel(Engines::EngineInterface* engine, u32 subchannel_id, Engines::EngineTypes engine_type) { + void BindSubchannel(Engines::EngineInterface* engine, u32 subchannel_id, + Engines::EngineTypes engine_type) { subchannels[subchannel_id] = engine; subchannel_type[subchannel_id] = engine_type; } @@ -147,11 +152,11 @@ private: void SetState(const CommandHeader& command_header); - void CallMethod(u32 argument); - void CallMultiMethod(const u32* base_start, u32 num_methods); + void CallMethod(u32 argument) const; + void CallMultiMethod(const u32* base_start, u32 num_methods) const; -public: - Common::ScratchBuffer command_headers; ///< Buffer for list of commands fetched at once + Common::ScratchBuffer + command_headers; ///< Buffer for list of commands fetched at once std::queue dma_pushbuffer; ///< Queue of command lists to be processed std::size_t dma_pushbuffer_subindex{}; ///< Index within a command list within the pushbuffer @@ -167,24 +172,24 @@ public: bool is_last_call; }; - Core::System& system; - MemoryManager& memory_manager; - Control::ChannelState& channel_state; - DmaState dma_state{}; + bool dma_increment_once{}; + + const bool ib_enable{true}; ///< IB mode enabled + std::array subchannels{}; std::array subchannel_type; - Engines::Puller puller; + GPU& gpu; + Core::System& system; + MemoryManager& memory_manager; + mutable Engines::Puller puller; + + VideoCore::RasterizerInterface* rasterizer; + bool signal_sync; + bool synced; std::mutex sync_mutex; std::condition_variable sync_cv; - - VideoCore::RasterizerInterface* rasterizer = nullptr; - - const bool ib_enable : 1 = true; ///< IB mode enabled - bool dma_increment_once : 1 = false; - bool signal_sync : 1 = false; - bool synced : 1 = false; }; } // namespace Tegra diff --git a/src/video_core/engines/engine_interface.h b/src/video_core/engines/engine_interface.h index 83dbf13059..bf3bd66aca 100644 --- a/src/video_core/engines/engine_interface.h +++ b/src/video_core/engines/engine_interface.h @@ -12,10 +12,6 @@ #include "common/common_types.h" -namespace Core { -class System; -} - namespace Tegra::Engines { enum class EngineTypes : u32 { @@ -32,25 +28,28 @@ public: virtual ~EngineInterface() = default; /// Write the value to the register identified by method. - virtual void CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) = 0; + virtual void CallMethod(u32 method, u32 method_argument, bool is_last_call) = 0; /// Write multiple values to the register identified by method. - virtual void CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) = 0; + virtual void CallMultiMethod(u32 method, const u32* base_start, u32 amount, + u32 methods_pending) = 0; - void ConsumeSink(Core::System& system) { - if (!method_sink.empty()) { - ConsumeSinkImpl(system); + void ConsumeSink() { + if (method_sink.empty()) { + return; } + ConsumeSinkImpl(); } std::bitset<(std::numeric_limits::max)()> execution_mask{}; std::vector> method_sink{}; - GPUVAddr current_dma_segment; bool current_dirty{}; + GPUVAddr current_dma_segment; + protected: - virtual void ConsumeSinkImpl(Core::System& system) { + virtual void ConsumeSinkImpl() { for (auto [method, value] : method_sink) { - CallMethod(system, method, value, true); + CallMethod(method, value, true); } method_sink.clear(); } diff --git a/src/video_core/engines/fermi_2d.cpp b/src/video_core/engines/fermi_2d.cpp index 8b02c91e03..b442c5cc76 100644 --- a/src/video_core/engines/fermi_2d.cpp +++ b/src/video_core/engines/fermi_2d.cpp @@ -36,8 +36,9 @@ void Fermi2D::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) { rasterizer = rasterizer_; } -void Fermi2D::CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) { - ASSERT_MSG(method < Regs::NUM_REGS, "Invalid Fermi2D register, increase the size of the Regs structure"); +void Fermi2D::CallMethod(u32 method, u32 method_argument, bool is_last_call) { + ASSERT_MSG(method < Regs::NUM_REGS, + "Invalid Fermi2D register, increase the size of the Regs structure"); regs.reg_array[method] = method_argument; if (method == FERMI2D_REG_INDEX(pixels_from_memory.src_y0) + 1) { @@ -45,13 +46,13 @@ void Fermi2D::CallMethod(Core::System& system, u32 method, u32 method_argument, } } -void Fermi2D::CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) { +void Fermi2D::CallMultiMethod(u32 method, const u32* base_start, u32 amount, u32 methods_pending) { for (u32 i = 0; i < amount; ++i) { - CallMethod(system, method, base_start[i], methods_pending - i <= 1); + CallMethod(method, base_start[i], methods_pending - i <= 1); } } -void Fermi2D::ConsumeSinkImpl(Core::System& system) { +void Fermi2D::ConsumeSinkImpl() { for (auto [method, value] : method_sink) { regs.reg_array[method] = value; } @@ -59,7 +60,8 @@ void Fermi2D::ConsumeSinkImpl(Core::System& system) { } void Fermi2D::Blit() { - LOG_DEBUG(HW_GPU, "called. source address=0x{:x}, destination address=0x{:x}", regs.src.Address(), regs.dst.Address()); + LOG_DEBUG(HW_GPU, "called. source address=0x{:x}, destination address=0x{:x}", + regs.src.Address(), regs.dst.Address()); UNIMPLEMENTED_IF_MSG(regs.operation != Operation::SrcCopy, "Operation is not copy"); UNIMPLEMENTED_IF_MSG(regs.src.layer != 0, "Source layer is not zero"); diff --git a/src/video_core/engines/fermi_2d.h b/src/video_core/engines/fermi_2d.h index 7fddf9fdc1..705b323e15 100644 --- a/src/video_core/engines/fermi_2d.h +++ b/src/video_core/engines/fermi_2d.h @@ -1,6 +1,3 @@ -// 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 @@ -47,10 +44,11 @@ public: void BindRasterizer(VideoCore::RasterizerInterface* rasterizer); /// Write the value to the register identified by method. - void CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) override; + void CallMethod(u32 method, u32 method_argument, bool is_last_call) override; /// Write multiple values to the register identified by method. - void CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) override; + void CallMultiMethod(u32 method, const u32* base_start, u32 amount, + u32 methods_pending) override; enum class Origin : u32 { Center = 0, @@ -313,7 +311,7 @@ private: /// registers. void Blit(); - void ConsumeSinkImpl(Core::System& system) override; + void ConsumeSinkImpl() override; }; #define ASSERT_REG_POSITION(field_name, position) \ diff --git a/src/video_core/engines/kepler_compute.cpp b/src/video_core/engines/kepler_compute.cpp index 1ef6e0fc0d..7b4efeb1e0 100644 --- a/src/video_core/engines/kepler_compute.cpp +++ b/src/video_core/engines/kepler_compute.cpp @@ -16,10 +16,8 @@ namespace Tegra::Engines { -KeplerCompute::KeplerCompute(MemoryManager& memory_manager_) - : memory_manager{memory_manager_} - , upload_state{memory_manager, regs.upload} -{ +KeplerCompute::KeplerCompute(Core::System& system_, MemoryManager& memory_manager_) + : system{system_}, memory_manager{memory_manager_}, upload_state{memory_manager, regs.upload} { execution_mask.reset(); execution_mask[KEPLER_COMPUTE_REG_INDEX(exec_upload)] = true; execution_mask[KEPLER_COMPUTE_REG_INDEX(data_upload)] = true; @@ -33,15 +31,16 @@ void KeplerCompute::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) upload_state.BindRasterizer(rasterizer); } -void KeplerCompute::ConsumeSinkImpl(Core::System& system) { +void KeplerCompute::ConsumeSinkImpl() { for (auto [method, value] : method_sink) { regs.reg_array[method] = value; } method_sink.clear(); } -void KeplerCompute::CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) { - ASSERT_MSG(method < Regs::NUM_REGS, "Invalid KeplerCompute register, increase the size of the Regs structure"); +void KeplerCompute::CallMethod(u32 method, u32 method_argument, bool is_last_call) { + ASSERT_MSG(method < Regs::NUM_REGS, + "Invalid KeplerCompute register, increase the size of the Regs structure"); regs.reg_array[method] = method_argument; @@ -79,7 +78,8 @@ void KeplerCompute::CallMethod(Core::System& system, u32 method, u32 method_argu } } -void KeplerCompute::CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) { +void KeplerCompute::CallMultiMethod(u32 method, const u32* base_start, u32 amount, + u32 methods_pending) { switch (method) { case KEPLER_COMPUTE_REG_INDEX(data_upload): upload_address = current_dma_segment; @@ -87,7 +87,7 @@ void KeplerCompute::CallMultiMethod(Core::System& system, u32 method, const u32* return; default: for (u32 i = 0; i < amount; i++) { - CallMethod(system, method, base_start[i], methods_pending - i <= 1); + CallMethod(method, base_start[i], methods_pending - i <= 1); } break; } diff --git a/src/video_core/engines/kepler_compute.h b/src/video_core/engines/kepler_compute.h index 4f7242f804..735e05fb43 100644 --- a/src/video_core/engines/kepler_compute.h +++ b/src/video_core/engines/kepler_compute.h @@ -1,6 +1,3 @@ -// 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 @@ -45,7 +42,7 @@ namespace Tegra::Engines { class KeplerCompute final : public EngineInterface { public: - explicit KeplerCompute(MemoryManager& memory_manager); + explicit KeplerCompute(Core::System& system, MemoryManager& memory_manager); ~KeplerCompute(); /// Binds a rasterizer to this engine. @@ -202,10 +199,11 @@ public: "KeplerCompute LaunchParams has wrong size"); /// Write the value to the register identified by method. - void CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) override; + void CallMethod(u32 method, u32 method_argument, bool is_last_call) override; /// Write multiple values to the register identified by method. - void CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) override; + void CallMultiMethod(u32 method, const u32* base_start, u32 amount, + u32 methods_pending) override; std::optional GetIndirectComputeAddress() const { return indirect_compute; @@ -214,7 +212,7 @@ public: private: void ProcessLaunch(); - void ConsumeSinkImpl(Core::System& system) override; + void ConsumeSinkImpl() override; /// Retrieves information about a specific TIC entry from the TIC buffer. Texture::TICEntry GetTICEntry(u32 tic_index) const; @@ -222,6 +220,7 @@ private: /// Retrieves information about a specific TSC entry from the TSC buffer. Texture::TSCEntry GetTSCEntry(u32 tsc_index) const; + Core::System& system; MemoryManager& memory_manager; VideoCore::RasterizerInterface* rasterizer = nullptr; Upload::State upload_state; diff --git a/src/video_core/engines/kepler_memory.cpp b/src/video_core/engines/kepler_memory.cpp index 3af5f91271..5d4c4720d3 100644 --- a/src/video_core/engines/kepler_memory.cpp +++ b/src/video_core/engines/kepler_memory.cpp @@ -14,9 +14,8 @@ namespace Tegra::Engines { -KeplerMemory::KeplerMemory(MemoryManager& memory_manager) - : upload_state{memory_manager, regs.upload} -{} +KeplerMemory::KeplerMemory(Core::System& system_, MemoryManager& memory_manager) + : system{system_}, upload_state{memory_manager, regs.upload} {} KeplerMemory::~KeplerMemory() = default; @@ -28,15 +27,16 @@ void KeplerMemory::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) { execution_mask[KEPLERMEMORY_REG_INDEX(data)] = true; } -void KeplerMemory::ConsumeSinkImpl(Core::System& system) { +void KeplerMemory::ConsumeSinkImpl() { for (auto [method, value] : method_sink) { regs.reg_array[method] = value; } method_sink.clear(); } -void KeplerMemory::CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) { - ASSERT_MSG(method < Regs::NUM_REGS, "Invalid KeplerMemory register, increase the size of the Regs structure"); +void KeplerMemory::CallMethod(u32 method, u32 method_argument, bool is_last_call) { + ASSERT_MSG(method < Regs::NUM_REGS, + "Invalid KeplerMemory register, increase the size of the Regs structure"); regs.reg_array[method] = method_argument; @@ -52,14 +52,15 @@ void KeplerMemory::CallMethod(Core::System& system, u32 method, u32 method_argum } } -void KeplerMemory::CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) { +void KeplerMemory::CallMultiMethod(u32 method, const u32* base_start, u32 amount, + u32 methods_pending) { switch (method) { case KEPLERMEMORY_REG_INDEX(data): upload_state.ProcessData(base_start, amount); return; default: for (u32 i = 0; i < amount; i++) { - CallMethod(system, method, base_start[i], methods_pending - i <= 1); + CallMethod(method, base_start[i], methods_pending - i <= 1); } break; } diff --git a/src/video_core/engines/kepler_memory.h b/src/video_core/engines/kepler_memory.h index aa0952d17a..fb1eecbba9 100644 --- a/src/video_core/engines/kepler_memory.h +++ b/src/video_core/engines/kepler_memory.h @@ -1,6 +1,3 @@ -// 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 @@ -39,17 +36,18 @@ namespace Tegra::Engines { class KeplerMemory final : public EngineInterface { public: - explicit KeplerMemory(MemoryManager& memory_manager); + explicit KeplerMemory(Core::System& system_, MemoryManager& memory_manager); ~KeplerMemory() override; /// Binds a rasterizer to this engine. void BindRasterizer(VideoCore::RasterizerInterface* rasterizer); /// Write the value to the register identified by method. - void CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) override; + void CallMethod(u32 method, u32 method_argument, bool is_last_call) override; /// Write multiple values to the register identified by method. - void CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) override; + void CallMultiMethod(u32 method, const u32* base_start, u32 amount, + u32 methods_pending) override; struct Regs { static constexpr size_t NUM_REGS = 0x7F; @@ -75,7 +73,9 @@ public: } regs{}; private: - void ConsumeSinkImpl(Core::System& system) override; + void ConsumeSinkImpl() override; + + Core::System& system; Upload::State upload_state; }; diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 3474ad6d63..7cf351e458 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -25,8 +25,9 @@ namespace Tegra::Engines { /// First register id that is actually a Macro call. constexpr u32 MacroRegistersStart = 0xE00; -Maxwell3D::Maxwell3D(MemoryManager& memory_manager_) +Maxwell3D::Maxwell3D(Core::System& system_, MemoryManager& memory_manager_) : draw_manager() + , system{system_} , memory_manager{memory_manager_} #ifdef ARCHITECTURE_x86_64 , macro_engine(bool(Settings::values.disable_macro_jit)) @@ -200,10 +201,11 @@ bool Maxwell3D::IsMethodExecutable(u32 method) { } } -void Maxwell3D::ProcessMacro(Core::System& system, u32 method, const u32* base_start, u32 amount, bool is_last_call) { +void Maxwell3D::ProcessMacro(u32 method, const u32* base_start, u32 amount, bool is_last_call) { if (executing_macro == 0) { // A macro call must begin by writing the macro method's register, not its argument. - ASSERT((method % 2) == 0 && "Can't start macro execution by writing to the ARGS register"); + ASSERT_MSG((method % 2) == 0, + "Can't start macro execution by writing to the ARGS register"); executing_macro = method; } @@ -217,8 +219,8 @@ void Maxwell3D::ProcessMacro(Core::System& system, u32 method, const u32* base_s // Call the macro when there are no more parameters in the command buffer if (is_last_call) { - ConsumeSink(system); - CallMacroMethod(system, executing_macro, macro_params); + ConsumeSink(); + CallMacroMethod(executing_macro, macro_params); macro_params.clear(); macro_addresses.clear(); macro_segments.clear(); @@ -285,7 +287,7 @@ u32 Maxwell3D::ProcessShadowRam(u32 method, u32 argument) { return argument; } -void Maxwell3D::ConsumeSinkImpl(Core::System& system) { +void Maxwell3D::ConsumeSinkImpl() { const auto control = shadow_state.shadow_ram_control; if (control == Regs::ShadowRamControl::Track || control == Regs::ShadowRamControl::TrackWithFilter) { for (auto [method, value] : method_sink) { @@ -376,7 +378,7 @@ void Maxwell3D::ProcessMethodCall(u32 method, u32 argument, u32 nonshadow_argume } } -void Maxwell3D::CallMacroMethod(Core::System& system, u32 method, const std::vector& parameters) { +void Maxwell3D::CallMacroMethod(u32 method, const std::vector& parameters) { // Reset the current macro. executing_macro = 0; @@ -385,11 +387,11 @@ void Maxwell3D::CallMacroMethod(Core::System& system, u32 method, const std::vec ((method - MacroRegistersStart) >> 1) % static_cast(macro_positions.size()); // Execute the current macro. - macro_engine.Execute(system, *this, macro_positions[entry], parameters); + macro_engine.Execute(*this, macro_positions[entry], parameters); draw_manager.DrawDeferred(*this); } -void Maxwell3D::CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) { +void Maxwell3D::CallMethod(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 has finished execution. if (executing_macro != 0) { @@ -399,7 +401,7 @@ void Maxwell3D::CallMethod(Core::System& system, u32 method, u32 method_argument // Methods after 0xE00 are special, they're actually triggers for some microcode that was // uploaded to the GPU during initialization. if (method >= MacroRegistersStart) { - ProcessMacro(system, method, &method_argument, 1, is_last_call); + ProcessMacro(method, &method_argument, 1, is_last_call); return; } @@ -409,11 +411,12 @@ void Maxwell3D::CallMethod(Core::System& system, u32 method, u32 method_argument ProcessMethodCall(method, argument, method_argument, is_last_call); } -void Maxwell3D::CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) { +void Maxwell3D::CallMultiMethod(u32 method, const u32* base_start, u32 amount, + u32 methods_pending) { // Methods after 0xE00 are special, they're actually triggers for some microcode that was // uploaded to the GPU during initialization. if (method >= MacroRegistersStart) { - ProcessMacro(system, method, base_start, amount, amount == methods_pending); + ProcessMacro(method, base_start, amount, amount == methods_pending); return; } switch (method) { @@ -442,7 +445,7 @@ void Maxwell3D::CallMultiMethod(Core::System& system, u32 method, const u32* bas } default: for (u32 i = 0; i < amount; i++) { - CallMethod(system, method, base_start[i], methods_pending - i <= 1); + CallMethod(method, base_start[i], methods_pending - i <= 1); } break; } @@ -464,7 +467,7 @@ void Maxwell3D::ProcessFirmwareCall4() { regs.shadow_scratch[0] = 1; } -void Maxwell3D::StampQueryResult(Core::System& system, u64 payload, bool long_query) { +void Maxwell3D::StampQueryResult(u64 payload, bool long_query) { const GPUVAddr sequence_address{regs.report_semaphore.Address()}; if (long_query) { memory_manager.Write(sequence_address + sizeof(u64), system.GPU().GetTicks()); diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 823be0f63e..864ee27fb6 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h @@ -55,7 +55,7 @@ namespace Tegra::Engines { class Maxwell3D final : public EngineInterface { public: - explicit Maxwell3D(MemoryManager& memory_manager); + explicit Maxwell3D(Core::System& system, MemoryManager& memory_manager); ~Maxwell3D(); /// Binds a rasterizer to this engine. @@ -3129,10 +3129,11 @@ public: u32 GetRegisterValue(u32 method) const; /// Write the value to the register identified by method. - void CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) override; + void CallMethod(u32 method, u32 method_argument, bool is_last_call) override; /// Write multiple values to the register identified by method. - void CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) override; + void CallMultiMethod(u32 method, const u32* base_start, u32 amount, + u32 methods_pending) override; bool ShouldExecute() const { return execute_on; @@ -3189,13 +3190,13 @@ public: private: void InitializeRegisterDefaults(); - void ProcessMacro(Core::System& system, u32 method, const u32* base_start, u32 amount, bool is_last_call); + void ProcessMacro(u32 method, const u32* base_start, u32 amount, bool is_last_call); u32 ProcessShadowRam(u32 method, u32 argument); void ProcessDirtyRegisters(u32 method, u32 argument); - void ConsumeSinkImpl(Core::System& system) override; + void ConsumeSinkImpl() override; void ProcessMethodCall(u32 method, u32 argument, u32 nonshadow_argument, bool is_last_call); @@ -3211,7 +3212,7 @@ private: * @param method Method to call * @param parameters Arguments to the method call */ - void CallMacroMethod(Core::System& system, u32 method, const std::vector& parameters); + void CallMacroMethod(u32 method, const std::vector& parameters); /// Handles writes to the macro uploading register. void ProcessMacroUpload(u32 data); @@ -3226,7 +3227,7 @@ private: void ProcessQueryGet(); /// Writes the query result accordingly. - void StampQueryResult(Core::System& system, u64 payload, bool long_query); + void StampQueryResult(u64 payload, bool long_query); /// Handles conditional rendering. void ProcessQueryCondition(); @@ -3241,6 +3242,7 @@ private: bool IsMethodExecutable(u32 method); + Core::System& system; MemoryManager& memory_manager; VideoCore::RasterizerInterface* rasterizer = nullptr; diff --git a/src/video_core/engines/maxwell_dma.cpp b/src/video_core/engines/maxwell_dma.cpp index a4090bc2ce..089d118a09 100644 --- a/src/video_core/engines/maxwell_dma.cpp +++ b/src/video_core/engines/maxwell_dma.cpp @@ -21,9 +21,8 @@ namespace Tegra::Engines { using namespace Texture; -MaxwellDMA::MaxwellDMA(MemoryManager& memory_manager_) - : memory_manager{memory_manager_} -{ +MaxwellDMA::MaxwellDMA(Core::System& system_, MemoryManager& memory_manager_) + : system{system_}, memory_manager{memory_manager_} { execution_mask.reset(); execution_mask[offsetof(Regs, launch_dma) / sizeof(u32)] = true; } @@ -34,14 +33,14 @@ void MaxwellDMA::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) { rasterizer = rasterizer_; } -void MaxwellDMA::ConsumeSinkImpl(Core::System& system) { +void MaxwellDMA::ConsumeSinkImpl() { for (auto [method, value] : method_sink) { regs.reg_array[method] = value; } method_sink.clear(); } -void MaxwellDMA::CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) { +void MaxwellDMA::CallMethod(u32 method, u32 method_argument, bool is_last_call) { ASSERT_MSG(method < NUM_REGS, "Invalid MaxwellDMA register"); regs.reg_array[method] = method_argument; @@ -51,14 +50,16 @@ void MaxwellDMA::CallMethod(Core::System& system, u32 method, u32 method_argumen } } -void MaxwellDMA::CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) { +void MaxwellDMA::CallMultiMethod(u32 method, const u32* base_start, u32 amount, + u32 methods_pending) { for (u32 i = 0; i < amount; ++i) { - CallMethod(system, method, base_start[i], methods_pending - i <= 1); + CallMethod(method, base_start[i], methods_pending - i <= 1); } } void MaxwellDMA::Launch() { - LOG_TRACE(Render_OpenGL, "DMA copy 0x{:x} -> 0x{:x}", static_cast(regs.offset_in), GPUVAddr(regs.offset_out)); + LOG_TRACE(Render_OpenGL, "DMA copy 0x{:x} -> 0x{:x}", static_cast(regs.offset_in), + static_cast(regs.offset_out)); // TODO(Subv): Perform more research and implement all features of this engine. const LaunchDMA& launch = regs.launch_dma; diff --git a/src/video_core/engines/maxwell_dma.h b/src/video_core/engines/maxwell_dma.h index 9cf2813d31..99341e431c 100644 --- a/src/video_core/engines/maxwell_dma.h +++ b/src/video_core/engines/maxwell_dma.h @@ -1,6 +1,3 @@ -// 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 @@ -241,14 +238,15 @@ public: void BindRasterizer(VideoCore::RasterizerInterface* rasterizer); - explicit MaxwellDMA(MemoryManager& memory_manager_); + explicit MaxwellDMA(Core::System& system_, MemoryManager& memory_manager_); ~MaxwellDMA() override; /// Write the value to the register identified by method. - void CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) override; + void CallMethod(u32 method, u32 method_argument, bool is_last_call) override; /// Write multiple values to the register identified by method. - void CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) override; + void CallMultiMethod(u32 method, const u32* base_start, u32 amount, + u32 methods_pending) override; private: /// Performs the copy from the source buffer to the destination buffer as configured in the @@ -263,7 +261,9 @@ private: void ReleaseSemaphore(); - void ConsumeSinkImpl(Core::System& system) override; + void ConsumeSinkImpl() override; + + Core::System& system; MemoryManager& memory_manager; VideoCore::RasterizerInterface* rasterizer = nullptr; diff --git a/src/video_core/engines/nv01_timer.h b/src/video_core/engines/nv01_timer.h index 37c6668144..add9886f41 100644 --- a/src/video_core/engines/nv01_timer.h +++ b/src/video_core/engines/nv01_timer.h @@ -26,16 +26,18 @@ class MemoryManager; namespace Tegra::Engines { class Nv01Timer final : public EngineInterface { public: - explicit Nv01Timer(MemoryManager& memory_manager) noexcept {} - ~Nv01Timer() noexcept override {} + explicit Nv01Timer(Core::System& system_, MemoryManager& memory_manager) + : system{system_} + {} + ~Nv01Timer() override; /// Write the value to the register identified by method. - void CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) override { + 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(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) override { + 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); } @@ -44,6 +46,7 @@ public: INSERT_PADDING_BYTES_NOINIT(0x48); } regs{}; private: - void ConsumeSinkImpl(Core::System& system) override {} + void ConsumeSinkImpl() override {} + Core::System& system; }; } diff --git a/src/video_core/engines/puller.cpp b/src/video_core/engines/puller.cpp index 5816b5901a..4030f93d49 100644 --- a/src/video_core/engines/puller.cpp +++ b/src/video_core/engines/puller.cpp @@ -22,29 +22,37 @@ namespace Tegra::Engines { -void Puller::ProcessBindMethod(DmaPusher& dma_pusher, const MethodCall& method_call) { +Puller::Puller(GPU& gpu_, MemoryManager& memory_manager_, DmaPusher& dma_pusher_, + Control::ChannelState& channel_state_) + : gpu{gpu_}, memory_manager{memory_manager_}, dma_pusher{dma_pusher_}, channel_state{ + channel_state_} {} + +Puller::~Puller() = default; + +void Puller::ProcessBindMethod(const MethodCall& method_call) { // Bind the current subchannel to the desired engine id. - LOG_DEBUG(HW_GPU, "Binding subchannel {} to engine {}", method_call.subchannel, method_call.argument); + LOG_DEBUG(HW_GPU, "Binding subchannel {} to engine {}", method_call.subchannel, + method_call.argument); const auto engine_id = static_cast(method_call.argument); bound_engines[method_call.subchannel] = engine_id; switch (engine_id) { case EngineID::FERMI_TWOD_A: - dma_pusher.BindSubchannel(&dma_pusher.channel_state.payload->fermi_2d, 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(&dma_pusher.channel_state.payload->maxwell_3d, 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(&dma_pusher.channel_state.payload->kepler_compute, 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(&dma_pusher.channel_state.payload->maxwell_dma, 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(&dma_pusher.channel_state.payload->kepler_memory, 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(&dma_pusher.channel_state.payload->nv01_timer, method_call.subchannel, EngineTypes::Nv01Timer); + dma_pusher.BindSubchannel(&*channel_state.nv01_timer, method_call.subchannel, EngineTypes::Nv01Timer); break; default: UNIMPLEMENTED_MSG("Unimplemented engine {:04X}", engine_id); @@ -52,15 +60,15 @@ void Puller::ProcessBindMethod(DmaPusher& dma_pusher, const MethodCall& method_c } } -void Puller::ProcessFenceActionMethod(DmaPusher& dma_pusher) { +void Puller::ProcessFenceActionMethod() { switch (regs.fence_action.op) { case Puller::FenceOperation::Acquire: // UNIMPLEMENTED_MSG("Channel Scheduling pending."); // WaitFence(regs.fence_action.syncpoint_id, regs.fence_value); - dma_pusher.rasterizer->ReleaseFences(); + rasterizer->ReleaseFences(); break; case Puller::FenceOperation::Increment: - dma_pusher.rasterizer->SignalSyncPoint(regs.fence_action.syncpoint_id); + rasterizer->SignalSyncPoint(regs.fence_action.syncpoint_id); break; default: UNIMPLEMENTED_MSG("Unimplemented operation {}", regs.fence_action.op.Value()); @@ -68,35 +76,37 @@ void Puller::ProcessFenceActionMethod(DmaPusher& dma_pusher) { } } -void Puller::ProcessSemaphoreTriggerMethod(DmaPusher& dma_pusher) { +void Puller::ProcessSemaphoreTriggerMethod() { const auto semaphoreOperationMask = 0xF; - const auto op = GpuSemaphoreOperation(regs.semaphore_trigger & semaphoreOperationMask); + const auto op = + static_cast(regs.semaphore_trigger & semaphoreOperationMask); if (op == GpuSemaphoreOperation::WriteLong) { const GPUVAddr sequence_address{regs.semaphore_address.SemaphoreAddress()}; const u32 payload = regs.semaphore_sequence; - dma_pusher.rasterizer->Query(sequence_address, VideoCommon::QueryType::Payload, VideoCommon::QueryPropertiesFlags::HasTimeout, payload, 0); + rasterizer->Query(sequence_address, VideoCommon::QueryType::Payload, + VideoCommon::QueryPropertiesFlags::HasTimeout, payload, 0); } else { do { - const u32 word = dma_pusher.memory_manager.Read(regs.semaphore_address.SemaphoreAddress()); + const u32 word{memory_manager.Read(regs.semaphore_address.SemaphoreAddress())}; regs.acquire_source = true; regs.acquire_value = regs.semaphore_sequence; if (op == GpuSemaphoreOperation::AcquireEqual) { regs.acquire_active = true; regs.acquire_mode = false; if (word != regs.acquire_value) { - dma_pusher.rasterizer->ReleaseFences(); + rasterizer->ReleaseFences(); continue; } } else if (op == GpuSemaphoreOperation::AcquireGequal) { regs.acquire_active = true; regs.acquire_mode = true; if (word < regs.acquire_value) { - dma_pusher.rasterizer->ReleaseFences(); + rasterizer->ReleaseFences(); continue; } } else if (op == GpuSemaphoreOperation::AcquireMask) { if (word && regs.semaphore_sequence == 0) { - dma_pusher.rasterizer->ReleaseFences(); + rasterizer->ReleaseFences(); continue; } } else { @@ -106,20 +116,21 @@ void Puller::ProcessSemaphoreTriggerMethod(DmaPusher& dma_pusher) { } } -void Puller::ProcessSemaphoreRelease(DmaPusher& dma_pusher) { +void Puller::ProcessSemaphoreRelease() { const GPUVAddr sequence_address{regs.semaphore_address.SemaphoreAddress()}; const u32 payload = regs.semaphore_release; - dma_pusher.rasterizer->Query(sequence_address, VideoCommon::QueryType::Payload, VideoCommon::QueryPropertiesFlags::IsAFence, payload, 0); + rasterizer->Query(sequence_address, VideoCommon::QueryType::Payload, + VideoCommon::QueryPropertiesFlags::IsAFence, payload, 0); } -void Puller::ProcessSemaphoreAcquire(DmaPusher& dma_pusher) { - u32 word = dma_pusher.memory_manager.Read(regs.semaphore_address.SemaphoreAddress()); +void Puller::ProcessSemaphoreAcquire() { + u32 word = memory_manager.Read(regs.semaphore_address.SemaphoreAddress()); const auto value = regs.semaphore_acquire; while (word != value) { regs.acquire_active = true; regs.acquire_value = value; - dma_pusher.rasterizer->ReleaseFences(); - word = dma_pusher.memory_manager.Read(regs.semaphore_address.SemaphoreAddress()); + rasterizer->ReleaseFences(); + word = memory_manager.Read(regs.semaphore_address.SemaphoreAddress()); // TODO(kemathe73) figure out how to do the acquire_timeout regs.acquire_mode = false; regs.acquire_source = false; @@ -127,13 +138,13 @@ void Puller::ProcessSemaphoreAcquire(DmaPusher& dma_pusher) { } /// Calls a GPU puller method. -void Puller::CallPullerMethod(DmaPusher& dma_pusher, const MethodCall& method_call) { +void Puller::CallPullerMethod(const MethodCall& method_call) { regs.reg_array[method_call.method] = method_call.argument; const auto method = static_cast(method_call.method); switch (method) { case BufferMethods::BindObject: { - ProcessBindMethod(dma_pusher, method_call); + ProcessBindMethod(method_call); break; } case BufferMethods::Nop: @@ -144,16 +155,16 @@ void Puller::CallPullerMethod(DmaPusher& dma_pusher, const MethodCall& method_ca case BufferMethods::WrcacheFlush: break; case BufferMethods::RefCnt: - dma_pusher.rasterizer->SignalReference(); + rasterizer->SignalReference(); break; case BufferMethods::SyncpointOperation: - ProcessFenceActionMethod(dma_pusher); + ProcessFenceActionMethod(); break; case BufferMethods::WaitForIdle: - dma_pusher.rasterizer->WaitForIdle(); + rasterizer->WaitForIdle(); break; case BufferMethods::SemaphoreOperation: { - ProcessSemaphoreTriggerMethod(dma_pusher); + ProcessSemaphoreTriggerMethod(); break; } case BufferMethods::NonStallInterrupt: { @@ -166,7 +177,7 @@ void Puller::CallPullerMethod(DmaPusher& dma_pusher, const MethodCall& method_ca } case BufferMethods::MemOpB: { // Implement this better. - dma_pusher.rasterizer->InvalidateGPUCache(); + rasterizer->InvalidateGPUCache(); break; } case BufferMethods::MemOpC: @@ -175,11 +186,11 @@ void Puller::CallPullerMethod(DmaPusher& dma_pusher, const MethodCall& method_ca break; } case BufferMethods::SemaphoreAcquire: { - ProcessSemaphoreAcquire(dma_pusher); + ProcessSemaphoreAcquire(); break; } case BufferMethods::SemaphoreRelease: { - ProcessSemaphoreRelease(dma_pusher); + ProcessSemaphoreRelease(); break; } case BufferMethods::Yield: { @@ -194,26 +205,27 @@ void Puller::CallPullerMethod(DmaPusher& dma_pusher, const MethodCall& method_ca } /// Calls a GPU engine method. -void Puller::CallEngineMethod(DmaPusher& dma_pusher, const MethodCall& method_call) { +void Puller::CallEngineMethod(const MethodCall& method_call) { const EngineID engine = bound_engines[method_call.subchannel]; + switch (engine) { case EngineID::FERMI_TWOD_A: - dma_pusher.channel_state.payload->fermi_2d.CallMethod(dma_pusher.system, 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: - dma_pusher.channel_state.payload->maxwell_3d.CallMethod(dma_pusher.system, 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: - dma_pusher.channel_state.payload->kepler_compute.CallMethod(dma_pusher.system, 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: - dma_pusher.channel_state.payload->maxwell_dma.CallMethod(dma_pusher.system, 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: - dma_pusher.channel_state.payload->kepler_memory.CallMethod(dma_pusher.system, 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: - dma_pusher.channel_state.payload->nv01_timer.CallMethod(dma_pusher.system, method_call.method, method_call.argument, method_call.IsLastCall()); + channel_state.nv01_timer->CallMethod(method_call.method, method_call.argument, method_call.IsLastCall()); break; default: UNIMPLEMENTED_MSG("Unimplemented engine"); @@ -222,26 +234,28 @@ void Puller::CallEngineMethod(DmaPusher& dma_pusher, const MethodCall& method_ca } /// Calls a GPU engine multivalue method. -void Puller::CallEngineMultiMethod(DmaPusher& dma_pusher, u32 method, u32 subchannel, const u32* base_start, u32 amount, u32 methods_pending) { +void Puller::CallEngineMultiMethod(u32 method, u32 subchannel, const u32* base_start, u32 amount, + u32 methods_pending) { const EngineID engine = bound_engines[subchannel]; + switch (engine) { case EngineID::FERMI_TWOD_A: - dma_pusher.channel_state.payload->fermi_2d.CallMultiMethod(dma_pusher.system, method, base_start, amount, methods_pending); + channel_state.fermi_2d->CallMultiMethod(method, base_start, amount, methods_pending); break; case EngineID::MAXWELL_B: - dma_pusher.channel_state.payload->maxwell_3d.CallMultiMethod(dma_pusher.system, method, base_start, amount, methods_pending); + channel_state.maxwell_3d->CallMultiMethod(method, base_start, amount, methods_pending); break; case EngineID::KEPLER_COMPUTE_B: - dma_pusher.channel_state.payload->kepler_compute.CallMultiMethod(dma_pusher.system, method, base_start, amount, methods_pending); + channel_state.kepler_compute->CallMultiMethod(method, base_start, amount, methods_pending); break; case EngineID::MAXWELL_DMA_COPY_A: - dma_pusher.channel_state.payload->maxwell_dma.CallMultiMethod(dma_pusher.system, method, base_start, amount, methods_pending); + channel_state.maxwell_dma->CallMultiMethod(method, base_start, amount, methods_pending); break; case EngineID::KEPLER_INLINE_TO_MEMORY_B: - dma_pusher.channel_state.payload->kepler_memory.CallMultiMethod(dma_pusher.system, method, base_start, amount, methods_pending); + channel_state.kepler_memory->CallMultiMethod(method, base_start, amount, methods_pending); break; case EngineID::NV01_TIMER: - dma_pusher.channel_state.payload->nv01_timer.CallMultiMethod(dma_pusher.system, method, base_start, amount, methods_pending); + channel_state.nv01_timer->CallMultiMethod(method, base_start, amount, methods_pending); break; default: UNIMPLEMENTED_MSG("Unimplemented engine"); @@ -250,26 +264,31 @@ void Puller::CallEngineMultiMethod(DmaPusher& dma_pusher, u32 method, u32 subcha } /// Calls a GPU method. -void Puller::CallMethod(DmaPusher& dma_pusher, const MethodCall& method_call) { - LOG_TRACE(HW_GPU, "Processing method {:08X} on subchannel {}", method_call.method, method_call.subchannel); +void Puller::CallMethod(const MethodCall& method_call) { + LOG_TRACE(HW_GPU, "Processing method {:08X} on subchannel {}", method_call.method, + method_call.subchannel); + ASSERT(method_call.subchannel < bound_engines.size()); - if (ExecuteMethodOnEngine(dma_pusher, method_call.method)) { - CallEngineMethod(dma_pusher, method_call); + if (ExecuteMethodOnEngine(method_call.method)) { + CallEngineMethod(method_call); } else { - CallPullerMethod(dma_pusher, method_call); + CallPullerMethod(method_call); } } /// Calls a GPU multivalue method. -void Puller::CallMultiMethod(DmaPusher& dma_pusher, u32 method, u32 subchannel, const u32* base_start, u32 amount, u32 methods_pending) { +void Puller::CallMultiMethod(u32 method, u32 subchannel, const u32* base_start, u32 amount, + u32 methods_pending) { LOG_TRACE(HW_GPU, "Processing method {:08X} on subchannel {}", method, subchannel); + ASSERT(subchannel < bound_engines.size()); - if (ExecuteMethodOnEngine(dma_pusher, method)) { - CallEngineMultiMethod(dma_pusher, method, subchannel, base_start, amount, methods_pending); + + if (ExecuteMethodOnEngine(method)) { + CallEngineMultiMethod(method, subchannel, base_start, amount, methods_pending); } else { for (u32 i = 0; i < amount; i++) { - CallPullerMethod(dma_pusher, MethodCall{ + CallPullerMethod(MethodCall{ method, base_start[i], subchannel, @@ -279,9 +298,13 @@ void Puller::CallMultiMethod(DmaPusher& dma_pusher, u32 method, u32 subchannel, } } +void Puller::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) { + rasterizer = rasterizer_; +} + /// Determines where the method should be executed. -[[nodiscard]] bool Puller::ExecuteMethodOnEngine(DmaPusher& dma_pusher, u32 method) { - const auto buffer_method = BufferMethods(method); +[[nodiscard]] bool Puller::ExecuteMethodOnEngine(u32 method) { + const auto buffer_method = static_cast(method); return buffer_method >= BufferMethods::NonPullerMethods; } diff --git a/src/video_core/engines/puller.h b/src/video_core/engines/puller.h index e8994f5640..fe5102e3ed 100644 --- a/src/video_core/engines/puller.h +++ b/src/video_core/engines/puller.h @@ -70,13 +70,32 @@ public: BitField<8, 24, u32> syncpoint_id; }; - void CallMethod(DmaPusher& dma_pusher, const MethodCall& method_call); - void CallMultiMethod(DmaPusher& dma_pusher, u32 method, u32 subchannel, const u32* base_start, u32 amount, u32 methods_pending); - void BindRasterizer(DmaPusher& dma_pusher, VideoCore::RasterizerInterface* rasterizer); - void CallPullerMethod(DmaPusher& dma_pusher, const MethodCall& method_call); - void CallEngineMethod(DmaPusher& dma_pusher, const MethodCall& method_call); - void CallEngineMultiMethod(DmaPusher& dma_pusher, u32 method, u32 subchannel, const u32* base_start, u32 amount, u32 methods_pending); + explicit Puller(GPU& gpu_, MemoryManager& memory_manager_, DmaPusher& dma_pusher, + Control::ChannelState& channel_state); + ~Puller(); + + void CallMethod(const MethodCall& method_call); + + void CallMultiMethod(u32 method, u32 subchannel, const u32* base_start, u32 amount, + u32 methods_pending); + + void BindRasterizer(VideoCore::RasterizerInterface* rasterizer); + + void CallPullerMethod(const MethodCall& method_call); + + void CallEngineMethod(const MethodCall& method_call); + + void CallEngineMultiMethod(u32 method, u32 subchannel, const u32* base_start, u32 amount, + u32 methods_pending); + private: + Tegra::GPU& gpu; + + MemoryManager& memory_manager; + DmaPusher& dma_pusher; + Control::ChannelState& channel_state; + VideoCore::RasterizerInterface* rasterizer = nullptr; + static constexpr std::size_t NUM_REGS = 0x800; struct Regs { static constexpr size_t NUM_REGS = 0x40; @@ -120,12 +139,12 @@ private: }; } regs{}; - void ProcessBindMethod(DmaPusher& dma_pusher, const MethodCall& method_call); - void ProcessFenceActionMethod(DmaPusher& dma_pusher); - void ProcessSemaphoreAcquire(DmaPusher& dma_pusher); - void ProcessSemaphoreRelease(DmaPusher& dma_pusher); - void ProcessSemaphoreTriggerMethod(DmaPusher& dma_pusher); - [[nodiscard]] bool ExecuteMethodOnEngine(DmaPusher& dma_pusher, u32 method); + void ProcessBindMethod(const MethodCall& method_call); + void ProcessFenceActionMethod(); + void ProcessSemaphoreAcquire(); + void ProcessSemaphoreRelease(); + void ProcessSemaphoreTriggerMethod(); + [[nodiscard]] bool ExecuteMethodOnEngine(u32 method); /// Mapping of command subchannels to their bound engine ids std::array bound_engines{}; @@ -138,7 +157,8 @@ private: }; #define ASSERT_REG_POSITION(field_name, position) \ - static_assert(offsetof(Regs, field_name) == position * 4, "Field " #field_name " has invalid position") + static_assert(offsetof(Regs, field_name) == position * 4, \ + "Field " #field_name " has invalid position") ASSERT_REG_POSITION(semaphore_address, 0x4); ASSERT_REG_POSITION(semaphore_sequence, 0x6); diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 548a8bf809..391ca4ef5f 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -40,31 +40,30 @@ namespace Tegra { struct GPU::Impl { - explicit Impl(Core::System& system_, bool is_async_, bool use_nvdec_) - : system{system_} - , use_nvdec{use_nvdec_} - , shader_notify() - , is_async{is_async_} - , gpu_thread{system_} - {} + explicit Impl(GPU& gpu_, Core::System& system_, bool is_async_, bool use_nvdec_) + : gpu{gpu_}, system{system_}, host1x{system.Host1x()}, use_nvdec{use_nvdec_}, + shader_notify{std::make_unique()}, is_async{is_async_}, + gpu_thread{system_, is_async_}, scheduler{std::make_unique(gpu)} {} ~Impl() = default; std::shared_ptr CreateChannel(s32 channel_id) { auto channel_state = std::make_shared(channel_id); channels.emplace(channel_id, channel_state); - scheduler.DeclareChannel(channel_state); + scheduler->DeclareChannel(channel_state); return channel_state; } void BindChannel(s32 channel_id) { - if (bound_channel != channel_id) { - auto it = channels.find(channel_id); - ASSERT(it != channels.end()); - bound_channel = channel_id; - current_channel = it->second.get(); - renderer->ReadRasterizer()->BindChannel(*current_channel); + if (bound_channel == channel_id) { + return; } + auto it = channels.find(channel_id); + ASSERT(it != channels.end()); + bound_channel = channel_id; + current_channel = it->second.get(); + + rasterizer->BindChannel(*current_channel); } std::shared_ptr AllocateChannel() { @@ -72,13 +71,13 @@ struct GPU::Impl { } void InitChannel(Control::ChannelState& to_init, u64 program_id) { - to_init.Init(system, program_id); - to_init.BindRasterizer(renderer->ReadRasterizer()); - renderer->ReadRasterizer()->InitializeChannel(to_init); + to_init.Init(system, gpu, program_id); + to_init.BindRasterizer(rasterizer); + rasterizer->InitializeChannel(to_init); } void InitAddressSpace(Tegra::MemoryManager& memory_manager) { - memory_manager.BindRasterizer(renderer->ReadRasterizer()); + memory_manager.BindRasterizer(rasterizer); } void ReleaseChannel(Control::ChannelState& to_release) { @@ -88,26 +87,26 @@ struct GPU::Impl { /// Binds a renderer to the GPU. void BindRenderer(std::unique_ptr renderer_) { renderer = std::move(renderer_); - system.Host1x().memory_manager.BindInterface(renderer->ReadRasterizer()); - system.Host1x().gmmu_manager.BindRasterizer(renderer->ReadRasterizer()); + rasterizer = renderer->ReadRasterizer(); + host1x.MemoryManager().BindInterface(rasterizer); + host1x.gmmu_manager.BindRasterizer(rasterizer); } /// Flush all current written commands into the host GPU for execution. void FlushCommands() { - renderer->ReadRasterizer()->FlushCommands(); + rasterizer->FlushCommands(); } /// Synchronizes CPU writes with Host GPU memory. void InvalidateGPUCache() { - std::function callback_writes([this](PAddr address, size_t size) { - renderer->ReadRasterizer()->OnCacheInvalidation(address, size); - }); + std::function callback_writes( + [this](PAddr address, size_t size) { rasterizer->OnCacheInvalidation(address, size); }); system.GatherGPUDirtyMemory(callback_writes); } /// Signal the ending of command list. void OnCommandListEnd() { - renderer->ReadRasterizer()->ReleaseFences(false); + rasterizer->ReleaseFences(false); Settings::UpdateGPUAccuracy(); } @@ -144,6 +143,62 @@ struct GPU::Impl { } } + /// Returns a reference to the Maxwell3D GPU engine. + [[nodiscard]] Engines::Maxwell3D& Maxwell3D() { + ASSERT(current_channel); + return *current_channel->maxwell_3d; + } + + /// Returns a const reference to the Maxwell3D GPU engine. + [[nodiscard]] const Engines::Maxwell3D& Maxwell3D() const { + ASSERT(current_channel); + return *current_channel->maxwell_3d; + } + + /// Returns a reference to the KeplerCompute GPU engine. + [[nodiscard]] Engines::KeplerCompute& KeplerCompute() { + ASSERT(current_channel); + return *current_channel->kepler_compute; + } + + /// Returns a reference to the KeplerCompute GPU engine. + [[nodiscard]] const Engines::KeplerCompute& KeplerCompute() const { + ASSERT(current_channel); + return *current_channel->kepler_compute; + } + + /// Returns a reference to the GPU DMA pusher. + [[nodiscard]] Tegra::DmaPusher& DmaPusher() { + ASSERT(current_channel); + return *current_channel->dma_pusher; + } + + /// Returns a const reference to the GPU DMA pusher. + [[nodiscard]] const Tegra::DmaPusher& DmaPusher() const { + ASSERT(current_channel); + return *current_channel->dma_pusher; + } + + /// Returns a reference to the underlying renderer. + [[nodiscard]] VideoCore::RendererBase& Renderer() { + return *renderer; + } + + /// Returns a const reference to the underlying renderer. + [[nodiscard]] const VideoCore::RendererBase& Renderer() const { + return *renderer; + } + + /// Returns a reference to the shader notifier. + [[nodiscard]] VideoCore::ShaderNotify& ShaderNotify() { + return *shader_notify; + } + + /// Returns a const reference to the shader notifier. + [[nodiscard]] const VideoCore::ShaderNotify& ShaderNotify() const { + return *shader_notify; + } + [[nodiscard]] u64 GetTicks() const { u64 gpu_tick = system.CoreTiming().GetGPUTicks(); Settings::GpuOverclock overclock = Settings::values.fast_gpu_time.GetValue(); @@ -155,6 +210,14 @@ struct GPU::Impl { return gpu_tick; } + [[nodiscard]] bool IsAsync() const { + return is_async; + } + + [[nodiscard]] bool UseNvdec() const { + return use_nvdec; + } + void RendererFrameEndNotify() { system.GetPerfStats().EndGameFrame(); } @@ -164,7 +227,7 @@ struct GPU::Impl { /// core timing events. void Start() { Settings::UpdateGPUAccuracy(); - gpu_thread.StartThread(*renderer, renderer->Context(), scheduler); + gpu_thread.StartThread(*renderer, renderer->Context(), *scheduler); } void NotifyShutdown() { @@ -188,24 +251,25 @@ struct GPU::Impl { /// Push GPU command entries to be processed void PushGPUEntries(s32 channel, Tegra::CommandList&& entries) { - gpu_thread.SubmitList(channel, std::move(entries), is_async); + gpu_thread.SubmitList(channel, std::move(entries)); } /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory void FlushRegion(DAddr addr, u64 size) { - gpu_thread.FlushRegion(addr, size, is_async); + gpu_thread.FlushRegion(addr, size); } VideoCore::RasterizerDownloadArea OnCPURead(DAddr addr, u64 size) { - auto raster_area = renderer->ReadRasterizer()->GetFlushArea(addr, size); + auto raster_area = rasterizer->GetFlushArea(addr, size); if (raster_area.preemtive) { return raster_area; } raster_area.preemtive = true; const u64 fence = RequestSyncOperation([this, &raster_area]() { - renderer->ReadRasterizer()->FlushRegion(raster_area.start_address, raster_area.end_address - raster_area.start_address); + rasterizer->FlushRegion(raster_area.start_address, + raster_area.end_address - raster_area.start_address); }); - gpu_thread.TickGPU(is_async); + gpu_thread.TickGPU(); WaitForSyncOperation(fence); return raster_area; } @@ -216,15 +280,16 @@ struct GPU::Impl { } bool OnCPUWrite(DAddr addr, u64 size) { - return renderer->ReadRasterizer()->OnCPUWrite(addr, size); + return rasterizer->OnCPUWrite(addr, size); } /// Notify rasterizer that any caches of the specified region should be flushed and invalidated void FlushAndInvalidateRegion(DAddr addr, u64 size) { - gpu_thread.FlushAndInvalidateRegion(addr, size, is_async); + gpu_thread.FlushAndInvalidateRegion(addr, size); } - void RequestComposite(std::vector&& layers, std::vector&& fences) { + void RequestComposite(std::vector&& layers, + std::vector&& fences) { size_t num_fences{fences.size()}; size_t current_request_counter{}; { @@ -239,7 +304,7 @@ struct GPU::Impl { } } const auto wait_fence = RequestSyncOperation([this, current_request_counter, &layers, &fences, num_fences] { - auto& syncpoint_manager = system.Host1x().GetSyncpointManager(); + auto& syncpoint_manager = host1x.GetSyncpointManager(); if (num_fences == 0) { renderer->Composite(layers); } @@ -257,7 +322,7 @@ struct GPU::Impl { syncpoint_manager.RegisterGuestAction(fences[i].id, fences[i].value, executer); } }); - gpu_thread.TickGPU(is_async); + gpu_thread.TickGPU(); WaitForSyncOperation(wait_fence); } @@ -266,20 +331,23 @@ struct GPU::Impl { const auto wait_fence = RequestSyncOperation([&] { out = renderer->GetAppletCaptureBuffer(); }); - gpu_thread.TickGPU(is_async); + gpu_thread.TickGPU(); WaitForSyncOperation(wait_fence); return out; } + GPU& gpu; Core::System& system; + Host1x::Host1x& host1x; std::unique_ptr renderer; + VideoCore::RasterizerInterface* rasterizer = nullptr; const bool use_nvdec; s32 new_channel_id{1}; /// Shader build notifier - VideoCore::ShaderNotify shader_notify; + std::unique_ptr shader_notify; /// When true, we are about to shut down emulation session, so terminate outstanding tasks std::atomic_bool shutting_down{}; @@ -303,7 +371,7 @@ struct GPU::Impl { VideoCommon::GPUThread::ThreadManager gpu_thread; std::unique_ptr cpu_context; - Tegra::Control::Scheduler scheduler; + std::unique_ptr scheduler; ankerl::unordered_dense::map> channels; Tegra::Control::ChannelState* current_channel; s32 bound_channel{-1}; @@ -314,8 +382,7 @@ struct GPU::Impl { }; GPU::GPU(Core::System& system, bool is_async, bool use_nvdec) - : impl{std::make_unique(system, is_async, use_nvdec)} -{} + : impl{std::make_unique(*this, system, is_async, use_nvdec)} {} GPU::~GPU() = default; @@ -356,9 +423,8 @@ void GPU::OnCommandListEnd() { } u64 GPU::RequestFlush(DAddr addr, std::size_t size) { - return impl->RequestSyncOperation([this, addr, size]() { - impl->renderer->ReadRasterizer()->FlushRegion(addr, size); - }); + return impl->RequestSyncOperation( + [this, addr, size]() { impl->rasterizer->FlushRegion(addr, size); }); } u64 GPU::CurrentSyncRequestFence() const { @@ -375,52 +441,52 @@ void GPU::TickWork() { /// Gets a mutable reference to the Host1x interface Host1x::Host1x& GPU::Host1x() { - return impl->system.Host1x(); + return impl->host1x; } /// Gets an immutable reference to the Host1x interface. const Host1x::Host1x& GPU::Host1x() const { - return impl->system.Host1x(); + return impl->host1x; } Engines::Maxwell3D& GPU::Maxwell3D() { - return impl->current_channel->payload->maxwell_3d; + return impl->Maxwell3D(); } const Engines::Maxwell3D& GPU::Maxwell3D() const { - return impl->current_channel->payload->maxwell_3d; + return impl->Maxwell3D(); } Engines::KeplerCompute& GPU::KeplerCompute() { - return impl->current_channel->payload->kepler_compute; + return impl->KeplerCompute(); } const Engines::KeplerCompute& GPU::KeplerCompute() const { - return impl->current_channel->payload->kepler_compute; + return impl->KeplerCompute(); } Tegra::DmaPusher& GPU::DmaPusher() { - return impl->current_channel->payload->dma_pusher; + return impl->DmaPusher(); } const Tegra::DmaPusher& GPU::DmaPusher() const { - return impl->current_channel->payload->dma_pusher; + return impl->DmaPusher(); } VideoCore::RendererBase& GPU::Renderer() { - return *impl->renderer; + return impl->Renderer(); } const VideoCore::RendererBase& GPU::Renderer() const { - return *impl->renderer; + return impl->Renderer(); } VideoCore::ShaderNotify& GPU::ShaderNotify() { - return impl->shader_notify; + return impl->ShaderNotify(); } const VideoCore::ShaderNotify& GPU::ShaderNotify() const { - return impl->shader_notify; + return impl->ShaderNotify(); } void GPU::RequestComposite(std::vector&& layers, @@ -437,11 +503,11 @@ u64 GPU::GetTicks() const { } bool GPU::IsAsync() const { - return impl->is_async; + return impl->IsAsync(); } bool GPU::UseNvdec() const { - return impl->use_nvdec; + return impl->UseNvdec(); } void GPU::RendererFrameEndNotify() { diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp index 50570b596d..d7c8ac391c 100644 --- a/src/video_core/gpu_thread.cpp +++ b/src/video_core/gpu_thread.cpp @@ -19,9 +19,8 @@ namespace VideoCommon::GPUThread { -ThreadManager::ThreadManager(Core::System& system_) - : system{system_} -{} +ThreadManager::ThreadManager(Core::System& system_, bool is_async_) + : system{system_}, is_async{is_async_} {} ThreadManager::~ThreadManager() = default; @@ -40,7 +39,7 @@ void ThreadManager::StartThread(VideoCore::RendererBase& renderer, Core::Fronten break; } if (auto* submit_list = std::get_if(&next.data)) { - scheduler.Push(system.GPU(), submit_list->channel, std::move(submit_list->entries)); + scheduler.Push(submit_list->channel, std::move(submit_list->entries)); } else if (std::holds_alternative(next.data)) { system.GPU().TickWork(); } else if (const auto* flush = std::get_if(&next.data)) { @@ -61,40 +60,41 @@ void ThreadManager::StartThread(VideoCore::RendererBase& renderer, Core::Fronten }); } -void ThreadManager::SubmitList(s32 channel, Tegra::CommandList&& entries, bool is_async) { - PushCommand(SubmitListCommand(channel, std::move(entries)), false, is_async); +void ThreadManager::SubmitList(s32 channel, Tegra::CommandList&& entries) { + PushCommand(SubmitListCommand(channel, std::move(entries))); } -void ThreadManager::FlushRegion(DAddr addr, u64 size, bool is_async) { +void ThreadManager::FlushRegion(DAddr addr, u64 size) { if (!is_async) { // Always flush with synchronous GPU mode - PushCommand(FlushRegionCommand(addr, size), false, is_async); + PushCommand(FlushRegionCommand(addr, size)); } + return; } -void ThreadManager::TickGPU(bool is_async) { - PushCommand(GPUTickCommand(), false, is_async); +void ThreadManager::TickGPU() { + PushCommand(GPUTickCommand()); } void ThreadManager::InvalidateRegion(DAddr addr, u64 size) { rasterizer->OnCacheInvalidation(addr, size); } -void ThreadManager::FlushAndInvalidateRegion(DAddr addr, u64 size, bool is_async) { +void ThreadManager::FlushAndInvalidateRegion(DAddr addr, u64 size) { if (Settings::IsGPULevelHigh()) { if (!is_async) { - PushCommand(FlushRegionCommand(addr, size), false, is_async); + PushCommand(FlushRegionCommand(addr, size)); } else { auto& gpu = system.GPU(); const u64 fence = gpu.RequestFlush(addr, size); - TickGPU(is_async); + TickGPU(); gpu.WaitForSyncOperation(fence); } } rasterizer->OnCacheInvalidation(addr, size); } -u64 ThreadManager::PushCommand(CommandData&& command_data, bool block, bool is_async) { +u64 ThreadManager::PushCommand(CommandData&& command_data, bool block) { if (!is_async) { // In synchronous GPU mode, block the caller until the command has executed block = true; diff --git a/src/video_core/gpu_thread.h b/src/video_core/gpu_thread.h index 4c3fadce15..ac1283a338 100644 --- a/src/video_core/gpu_thread.h +++ b/src/video_core/gpu_thread.h @@ -15,7 +15,6 @@ #include "common/bounded_threadsafe_queue.h" #include "common/polyfill_thread.h" -#include "video_core/dma_pusher.h" #include "video_core/framebuffer_config.h" namespace Tegra { @@ -104,7 +103,7 @@ struct SynchState final { /// Class used to manage the GPU thread class ThreadManager final { public: - explicit ThreadManager(Core::System& system_); + explicit ThreadManager(Core::System& system_, bool is_async_); ~ThreadManager(); /// Creates and starts the GPU thread. @@ -112,25 +111,27 @@ public: Tegra::Control::Scheduler& scheduler); /// Push GPU command entries to be processed - void SubmitList(s32 channel, Tegra::CommandList&& entries, bool is_async); + void SubmitList(s32 channel, Tegra::CommandList&& entries); /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory - void FlushRegion(DAddr addr, u64 size, bool is_async); + void FlushRegion(DAddr addr, u64 size); /// Notify rasterizer that any caches of the specified region should be invalidated void InvalidateRegion(DAddr addr, u64 size); /// Notify rasterizer that any caches of the specified region should be flushed and invalidated - void FlushAndInvalidateRegion(DAddr addr, u64 size, bool is_async); + void FlushAndInvalidateRegion(DAddr addr, u64 size); - void TickGPU(bool is_async); + void TickGPU(); private: /// Pushes a command to be executed by the GPU thread - u64 PushCommand(CommandData&& command_data, bool block, bool is_async); + u64 PushCommand(CommandData&& command_data, bool block = false); Core::System& system; + const bool is_async; VideoCore::RasterizerInterface* rasterizer = nullptr; + SynchState state; std::jthread thread; }; diff --git a/src/video_core/host1x/control.cpp b/src/video_core/host1x/control.cpp index 93ee57456b..53b3063557 100644 --- a/src/video_core/host1x/control.cpp +++ b/src/video_core/host1x/control.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: 2021 yuzu Emulator Project @@ -10,22 +10,26 @@ namespace Tegra::Host1x { -void Control::ProcessMethod(Host1x& host1x, Method method, u32 argument) { +Control::Control(Host1x& host1x_) : host1x(host1x_) {} + +Control::~Control() = default; + +void Control::ProcessMethod(Method method, u32 argument) { switch (method) { case Method::LoadSyncptPayload32: syncpoint_value = argument; break; case Method::WaitSyncpt: case Method::WaitSyncpt32: - Execute(host1x, argument); + Execute(argument); break; default: - UNIMPLEMENTED_MSG("Control method {:#X}", u32(method)); + UNIMPLEMENTED_MSG("Control method {:#X}", static_cast(method)); break; } } -void Control::Execute(Host1x& host1x, u32 data) { +void Control::Execute(u32 data) { LOG_TRACE(Service_NVDRV, "Control wait syncpt {} value {}", data, syncpoint_value); host1x.GetSyncpointManager().WaitHost(data, syncpoint_value); } diff --git a/src/video_core/host1x/control.h b/src/video_core/host1x/control.h index 4d87e63b32..bd8a2d7ad4 100644 --- a/src/video_core/host1x/control.h +++ b/src/video_core/host1x/control.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: 2021 yuzu Emulator Project // SPDX-FileCopyrightText: 2021 Skyline Team and Contributors // SPDX-License-Identifier: GPL-3.0-or-later @@ -22,11 +19,17 @@ public: WaitSyncpt32 = 0x50, }; - /// Writes the method into the state, Invoke Execute() if encountered - void ProcessMethod(Host1x& host1x, Method method, u32 argument); - /// For Host1x, execute is waiting on a syncpoint previously written into the state - void Execute(Host1x& host1x, u32 data); + explicit Control(Host1x& host1x); + ~Control(); + /// Writes the method into the state, Invoke Execute() if encountered + void ProcessMethod(Method method, u32 argument); + +private: + /// For Host1x, execute is waiting on a syncpoint previously written into the state + void Execute(u32 data); + + Host1x& host1x; u32 syncpoint_value{}; }; diff --git a/src/video_core/host1x/host1x.cpp b/src/video_core/host1x/host1x.cpp index 590b0e0ff2..b4e4a38c80 100644 --- a/src/video_core/host1x/host1x.cpp +++ b/src/video_core/host1x/host1x.cpp @@ -27,22 +27,22 @@ void Host1x::StartDevice(s32 fd, ChannelType type, u32 syncpt) { #ifdef YUZU_LEGACY std::call_once(nvdec_first_init, []() {std::this_thread::sleep_for(std::chrono::milliseconds{500});}); // HACK: For Astroneer #endif - devices[fd].emplace(*this, fd, syncpt); + devices[fd] = std::make_unique(*this, fd, syncpt); break; case ChannelType::VIC: #ifdef YUZU_LEGACY std::call_once(vic_first_init, []() {std::this_thread::sleep_for(std::chrono::milliseconds{500});}); // HACK: For Astroneer #endif - devices[fd].emplace(*this, fd, syncpt); + devices[fd] = std::make_unique(*this, fd, syncpt); break; default: - LOG_ERROR(HW_GPU, "Unimplemented host1x device {}", u32(type)); + LOG_ERROR(HW_GPU, "Unimplemented host1x device {}", static_cast(type)); break; } } void Host1x::StopDevice(s32 fd, ChannelType type) { - devices[fd].emplace(); + devices.erase(fd); } } // namespace Tegra::Host1x diff --git a/src/video_core/host1x/host1x.h b/src/video_core/host1x/host1x.h index 592ec449e8..838e749072 100644 --- a/src/video_core/host1x/host1x.h +++ b/src/video_core/host1x/host1x.h @@ -8,14 +8,10 @@ #include #include -#include +#include #include "common/common_types.h" -// fd types? -#include "video_core/host1x/nvdec.h" -#include "video_core/host1x/vic.h" - #include "common/address_space.h" #include "video_core/cdma_pusher.h" #include "video_core/host1x/gpu_device_memory_manager.h" @@ -35,90 +31,118 @@ class Nvdec; class FrameQueue { public: - struct FrameDevice { - std::deque>> m_presentation_order; - std::unordered_map> m_decode_order; - }; - void Open(s32 fd) { std::scoped_lock l{m_mutex}; - m_frame_devices.insert_or_assign(fd, FrameDevice{}); + m_presentation_order.insert({fd, {}}); + m_decode_order.insert({fd, {}}); } void Close(s32 fd) { std::scoped_lock l{m_mutex}; - m_frame_devices.erase(fd); + m_presentation_order.erase(fd); + m_decode_order.erase(fd); } s32 VicFindNvdecFdFromOffset(u64 search_offset) { std::scoped_lock l{m_mutex}; - for (auto const& [fd, dev] : m_frame_devices) { - for (auto const& [offset, frame] : dev.m_presentation_order) - if (offset == search_offset) - return fd; - for (auto const& [offset, frame] : dev.m_decode_order) - if (offset == search_offset) - return fd; + for (auto& map : m_presentation_order) { + for (auto& [offset, frame] : map.second) { + if (offset == search_offset) { + return map.first; + } + } + } + for (auto& map : m_decode_order) { + for (auto& [offset, frame] : map.second) { + if (offset == search_offset) { + return map.first; + } + } } return -1; } void PushPresentOrder(s32 fd, u64 offset, std::shared_ptr&& frame) { std::scoped_lock l{m_mutex}; - if (auto const it = m_frame_devices.find(fd); it != m_frame_devices.end()) { - if (it->second.m_presentation_order.size() >= MAX_PRESENT_QUEUE) - it->second.m_presentation_order.pop_front(); - it->second.m_presentation_order.emplace_back(offset, std::move(frame)); + auto map = m_presentation_order.find(fd); + if (map == m_presentation_order.end()) { + return; } + + if (map->second.size() >= MAX_PRESENT_QUEUE) { + map->second.pop_front(); + } + + map->second.emplace_back(offset, std::move(frame)); } void PushDecodeOrder(s32 fd, u64 offset, std::shared_ptr&& frame) { std::scoped_lock l{m_mutex}; - if (auto const it = m_frame_devices.find(fd); it != m_frame_devices.end()) { - it->second.m_decode_order.insert_or_assign(offset, std::move(frame)); - if (it->second.m_decode_order.size() > MAX_DECODE_MAP) { - auto it2 = it->second.m_decode_order.begin(); - std::advance(it2, it->second.m_decode_order.size() - MAX_DECODE_MAP); - it->second.m_decode_order.erase(it->second.m_decode_order.begin(), it2); - } + auto map = m_decode_order.find(fd); + if (map == m_decode_order.end()) { + return; + } + + map->second.insert_or_assign(offset, std::move(frame)); + + if (map->second.size() > MAX_DECODE_MAP) { + auto it = map->second.begin(); + std::advance(it, map->second.size() - MAX_DECODE_MAP); + map->second.erase(map->second.begin(), it); } } std::shared_ptr GetFrame(s32 fd, u64 offset) { - if (fd != -1) { - std::scoped_lock l{m_mutex}; - if (auto const it = m_frame_devices.find(fd); it != m_frame_devices.end()) { - if (it->second.m_presentation_order.size() > 0) - return GetPresentOrderLocked(fd); - if (it->second.m_decode_order.size() > 0) - return GetDecodeOrderLocked(fd, offset); - } + if (fd == -1) { + return {}; } + + std::scoped_lock l{m_mutex}; + + auto present_map = m_presentation_order.find(fd); + if (present_map != m_presentation_order.end() && !present_map->second.empty()) { + return GetPresentOrderLocked(fd); + } + + auto decode_map = m_decode_order.find(fd); + if (decode_map != m_decode_order.end() && !decode_map->second.empty()) { + return GetDecodeOrderLocked(fd, offset); + } + return {}; } private: std::shared_ptr GetPresentOrderLocked(s32 fd) { - if (auto const it = m_frame_devices.find(fd); it != m_frame_devices.end()) { - auto frame = std::move(it->second.m_presentation_order.front().second); - it->second.m_presentation_order.pop_front(); - return frame; + auto map = m_presentation_order.find(fd); + if (map == m_presentation_order.end() || map->second.empty()) { + return {}; } - return {}; + + auto frame = std::move(map->second.front().second); + map->second.pop_front(); + return frame; } std::shared_ptr GetDecodeOrderLocked(s32 fd, u64 offset) { - if (auto const it = m_frame_devices.find(fd); it != m_frame_devices.end()) { - if (auto const it2 = it->second.m_decode_order.find(offset); it2 != it->second.m_decode_order.end()) { - // TODO: this "mapped" prevents us from fully embracing ankerl - return std::move(it->second.m_decode_order.extract(it2).mapped()); - } + auto map = m_decode_order.find(fd); + if (map == m_decode_order.end() || map->second.empty()) { + return {}; } - return {}; + + auto it = map->second.find(offset); + if (it == map->second.end()) { + return {}; + } + // TODO: this "mapped" prevents us from fully embracing ankerl + return std::move(map->second.extract(it).mapped()); } + using FramePtr = std::shared_ptr; + std::mutex m_mutex{}; - ankerl::unordered_dense::map m_frame_devices; + ankerl::unordered_dense::map>> m_presentation_order; + ankerl::unordered_dense::map> m_decode_order; static constexpr size_t MAX_PRESENT_QUEUE = 100; static constexpr size_t MAX_DECODE_MAP = 200; @@ -172,11 +196,11 @@ public: void StopDevice(s32 fd, ChannelType type); void PushEntries(s32 fd, ChCommandHeaderList&& entries) { - if (auto const nvdec = std::get_if(&devices[fd])) { - nvdec->PushEntries(std::move(entries)); - } else if (auto const vic = std::get_if(&devices[fd])) { - vic->PushEntries(std::move(entries)); + auto it = devices.find(fd); + if (it == devices.end()) { + return; } + it->second->PushEntries(std::move(entries)); } Core::System& system; @@ -185,11 +209,7 @@ public: Tegra::MemoryManager gmmu_manager; Common::FlatAllocator allocator; FrameQueue frame_queue; - std::array, 1024> devices; + ankerl::unordered_dense::map> devices; #ifdef YUZU_LEGACY std::once_flag nvdec_first_init; std::once_flag vic_first_init; diff --git a/src/video_core/host1x/vic.cpp b/src/video_core/host1x/vic.cpp index f7830a3a45..bafbb0ed25 100644 --- a/src/video_core/host1x/vic.cpp +++ b/src/video_core/host1x/vic.cpp @@ -407,15 +407,15 @@ void Vic::ReadInterlacedY8__V8U8_N420(const SlotStruct& slot, std::span offsets, std::shared_ptr frame, bool planar) noexcept { switch (slot.config.frame_format) { - case DxvhadFrameFormat::Progressive: + case DXVAHD_FRAME_FORMAT::PROGRESSIVE: ReadProgressiveY8__V8U8_N420(slot, offsets, std::move(frame), planar, false); break; - case DxvhadFrameFormat::TopField: + case DXVAHD_FRAME_FORMAT::TOP_FIELD: ReadInterlacedY8__V8U8_N420(slot, offsets, std::move(frame), planar, true); break; - case DxvhadFrameFormat::BottomField: + case DXVAHD_FRAME_FORMAT::BOTTOM_FIELD: ReadInterlacedY8__V8U8_N420(slot, offsets, std::move(frame), planar, false); break; default: @@ -860,7 +860,7 @@ void Vic::WriteY8__V8U8_N420(const OutputSurfaceConfig& output_surface_config) n }; switch (output_surface_config.out_block_kind) { - case BlkKind::Generic_16Bx2: { + case BLK_KIND::GENERIC_16Bx2: { u32 const block_height = u32(output_surface_config.out_block_height); auto const out_luma_swizzle_size = Texture::CalculateSize(true, BytesPerPixel, out_luma_width, out_luma_height, 1, block_height, 0); auto const out_chroma_swizzle_size = Texture::CalculateSize(true, BytesPerPixel * 2, out_chroma_width, out_chroma_height, 1, block_height, 0); @@ -889,7 +889,7 @@ void Vic::WriteY8__V8U8_N420(const OutputSurfaceConfig& output_surface_config) n Texture::SwizzleTexture(out_chroma, chroma_scratch, BytesPerPixel, out_chroma_width, out_chroma_height, 1, block_height, 0, 1); } } break; - case BlkKind::Pitch: { + case BLK_KIND::PITCH: { LOG_TRACE(HW_GPU, "Writing Y8__V8U8_N420 swizzled frame\n" "\tinput surface {}x{} stride {} size {:#X}\n" "\toutput luma {}x{} stride {} size {:#X} block height {} swizzled size 0x{:X}\n", @@ -1032,7 +1032,7 @@ void Vic::WriteABGR(const OutputSurfaceConfig& output_surface_config, VideoPixel }; switch (output_surface_config.out_block_kind) { - case BlkKind::Generic_16Bx2: { + case BLK_KIND::GENERIC_16Bx2: { const u32 block_height = u32(output_surface_config.out_block_height); auto const out_swizzle_size = Texture::CalculateSize(true, BytesPerPixel, out_luma_width, out_luma_height, 1, block_height, 0); LOG_TRACE(HW_GPU, "Writing ABGR swizzled frame\n" @@ -1051,7 +1051,7 @@ void Vic::WriteABGR(const OutputSurfaceConfig& output_surface_config, VideoPixel Texture::SwizzleTexture(out_luma, luma_scratch, BytesPerPixel, out_luma_width, out_luma_height, 1, block_height, 0, 1); } } break; - case BlkKind::Pitch: { + case BLK_KIND::PITCH: { LOG_TRACE(HW_GPU, "Writing ABGR pitch frame\n" "\tinput surface {}x{} stride {} size {:#X}" "\toutput surface {}x{} stride {} size {:#X}", diff --git a/src/video_core/host1x/vic.h b/src/video_core/host1x/vic.h index 23f3f66c18..d728b38f91 100644 --- a/src/video_core/host1x/vic.h +++ b/src/video_core/host1x/vic.h @@ -6,12 +6,16 @@ #pragma once +#include +#include #include +#include +#include #include "common/common_types.h" #include "common/scratch_buffer.h" #include "video_core/cdma_pusher.h" -#include "video_core/host1x/ffmpeg.h" +#include "video_core/host1x/host1x.h" namespace Tegra::Host1x { class Host1x; @@ -134,53 +138,52 @@ enum SurfaceIndex : u32 { CombinedMotion = 7, }; -// Note: these will inevitably collide with Win32 defines if you use their UPPER_SNAKE_CASE naming -enum class DxvhadAlphaFillMode : u32 { - Opaque = 0, - Background = 1, - Destination = 2, - SourceStream = 3, - Composited = 4, - SourceAlpha = 5, +enum class DXVAHD_ALPHA_FILL_MODE : u32 { + OPAQUE = 0, + BACKGROUND = 1, + DESTINATION = 2, + SOURCE_STREAM = 3, + COMPOSITED = 4, + SOURCE_ALPHA = 5, }; -enum class DxvhadFrameFormat : u64 { - Progressive = 0, - InterlacedTopFieldFirst = 1, - InterlacedBottomFieldFirst = 2, - TopField = 3, - BottomField = 4, - SubpicProgressive = 5, - SubpicInterlacedTopFieldFirst = 6, - SubpicInterlacedBottomFieldFirst = 7, - SubpicTopField = 8, - SubpicBottomField = 9, - TopFieldChromaBottom = 10, - BottomFieldChromaTop = 11, - SubpicTopFieldChromaBottom = 12, - SubpicBottomFieldChromaTop = 13, +enum class DXVAHD_FRAME_FORMAT : u64 { + PROGRESSIVE = 0, + INTERLACED_TOP_FIELD_FIRST = 1, + INTERLACED_BOTTOM_FIELD_FIRST = 2, + TOP_FIELD = 3, + BOTTOM_FIELD = 4, + SUBPIC_PROGRESSIVE = 5, + SUBPIC_INTERLACED_TOP_FIELD_FIRST = 6, + SUBPIC_INTERLACED_BOTTOM_FIELD_FIRST = 7, + SUBPIC_TOP_FIELD = 8, + SUBPIC_BOTTOM_FIELD = 9, + TOP_FIELD_CHROMA_BOTTOM = 10, + BOTTOM_FIELD_CHROMA_TOP = 11, + SUBPIC_TOP_FIELD_CHROMA_BOTTOM = 12, + SUBPIC_BOTTOM_FIELD_CHROMA_TOP = 13, }; -enum class DxvhadDeinterlaceModePrivate : u64 { - Weave = 0, - BobField = 1, - Bob = 2, - Newbob = 3, - Disi1 = 4, - WeaveLumaBobFieldChroma = 5, - Max = 0xF, +enum class DXVAHD_DEINTERLACE_MODE_PRIVATE : u64 { + WEAVE = 0, + BOB_FIELD = 1, + BOB = 2, + NEWBOB = 3, + DISI1 = 4, + WEAVE_LUMA_BOB_FIELD_CHROMA = 5, + MAX = 0xF, }; -enum class BlkKind { - Pitch = 0, - Generic_16Bx2 = 1, +enum class BLK_KIND { + PITCH = 0, + GENERIC_16Bx2 = 1, // These are unsupported in the vic - BlNaive = 2, - BlKeplerXbarRaw = 3, - Vp2Tiled = 15, + BL_NAIVE = 2, + BL_KEPLER_XBAR_RAW = 3, + VP2_TILED = 15, }; -enum class BlendSrcFactC : u32 { +enum class BLEND_SRCFACTC : u32 { K1 = 0, K1_TIMES_DST = 1, NEG_K1_TIMES_DST = 2, @@ -188,7 +191,7 @@ enum class BlendSrcFactC : u32 { ZERO = 4, }; -enum class BlendDstFactC : u32 { +enum class BLEND_DSTFACTC : u32 { K1 = 0, K2 = 1, K1_TIMES_DST = 2, @@ -198,7 +201,7 @@ enum class BlendDstFactC : u32 { ONE = 6, }; -enum class BlendSrcFactA : u32 { +enum class BLEND_SRCFACTA : u32 { K1 = 0, K2 = 1, NEG_K1_TIMES_DST = 2, @@ -206,7 +209,7 @@ enum class BlendSrcFactA : u32 { MAX = 7, }; -enum class BlendDstFactA : u32 { +enum class BLEND_DSTFACTA : u32 { K2 = 0, NEG_K1_TIMES_SRC = 1, ZERO = 2, @@ -229,7 +232,7 @@ static_assert(sizeof(PipeConfig) == 0x10, "PipeConfig has the wrong size!"); struct OutputConfig { union { - BitField<0, 3, DxvhadAlphaFillMode> alpha_fill_mode; + BitField<0, 3, DXVAHD_ALPHA_FILL_MODE> alpha_fill_mode; BitField<3, 3, u64> alpha_fill_slot; BitField<6, 10, u64> background_a; BitField<16, 10, u64> background_r; @@ -262,7 +265,7 @@ struct OutputSurfaceConfig { BitField<0, 7, VideoPixelFormat> out_pixel_format; BitField<7, 2, u32> out_chroma_loc_horiz; BitField<9, 2, u32> out_chroma_loc_vert; - BitField<11, 4, BlkKind> out_block_kind; + BitField<11, 4, BLK_KIND> out_block_kind; BitField<15, 4, u32> out_block_height; // in gobs, log2 BitField<19, 3, u32> reserved0; BitField<22, 10, u32> reserved1; @@ -362,7 +365,7 @@ struct SlotConfig { BitField<14, 1, u64> prev_prev_motion_field_enable; BitField<15, 1, u64> combined_motion_field_enable; - BitField<16, 4, DxvhadFrameFormat> frame_format; + BitField<16, 4, DXVAHD_FRAME_FORMAT> frame_format; BitField<20, 2, u64> filter_length_y; // 0: 1-tap, 1: 2-tap, 2: 5-tap, 3: 10-tap BitField<22, 2, u64> filter_length_x; BitField<24, 12, u64> panoramic; @@ -374,7 +377,7 @@ struct SlotConfig { BitField<10, 10, u64> filter_detail; BitField<20, 10, u64> chroma_noise; BitField<30, 10, u64> chroma_detail; - BitField<40, 4, DxvhadDeinterlaceModePrivate> deinterlace_mode; + BitField<40, 4, DXVAHD_DEINTERLACE_MODE_PRIVATE> deinterlace_mode; BitField<44, 3, u64> motion_accumulation_weight; BitField<47, 11, u64> noise_iir; BitField<58, 4, u64> light_level; @@ -481,13 +484,13 @@ struct BlendingSlotStruct { BitField<26, 6, u32> reserved1; }; union { - BitField<0, 3, BlendSrcFactC> src_factor_color_match_select; + BitField<0, 3, BLEND_SRCFACTC> src_factor_color_match_select; BitField<3, 1, u32> reserved2; - BitField<4, 3, BlendDstFactC> dst_factor_color_match_select; + BitField<4, 3, BLEND_DSTFACTC> dst_factor_color_match_select; BitField<7, 1, u32> reserved3; - BitField<8, 3, BlendSrcFactA> src_factor_a_match_select; + BitField<8, 3, BLEND_SRCFACTA> src_factor_a_match_select; BitField<11, 1, u32> reserved4; - BitField<12, 3, BlendDstFactA> dst_factor_a_match_select; + BitField<12, 3, BLEND_DSTFACTA> dst_factor_a_match_select; BitField<15, 1, u32> reserved5; BitField<16, 4, u32> reserved6; BitField<20, 4, u32> reserved7; @@ -621,8 +624,8 @@ private: VicRegisters regs{}; Common::ScratchBuffer swizzle_scratch; - Common::ScratchBuffer output_surface; - Common::ScratchBuffer slot_surface; + Common::ScratchBuffer output_surface; + Common::ScratchBuffer slot_surface; Common::ScratchBuffer luma_scratch; Common::ScratchBuffer chroma_scratch; diff --git a/src/video_core/macro.cpp b/src/video_core/macro.cpp index 2833f95ee9..76a054665c 100644 --- a/src/video_core/macro.cpp +++ b/src/video_core/macro.cpp @@ -64,10 +64,10 @@ bool IsTopologySafe(Maxwell3D::Regs::PrimitiveTopology topology) { } // Anonymous namespace -void HLE_DrawArraysIndirect::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { +void HLE_DrawArraysIndirect::Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { auto topology = static_cast(parameters[0]); if (!maxwell3d.AnyParametersDirty() || !IsTopologySafe(topology)) { - Fallback(system, maxwell3d, parameters); + Fallback(maxwell3d, parameters); return; } @@ -93,7 +93,7 @@ void HLE_DrawArraysIndirect::Execute(Core::System& system, Engines::Maxwell3D& m maxwell3d.replace_table.clear(); } } -void HLE_DrawArraysIndirect::Fallback(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters) { +void HLE_DrawArraysIndirect::Fallback(Engines::Maxwell3D& maxwell3d, std::span parameters) { SCOPE_EXIT { if (extended) { maxwell3d.engine_state = Maxwell3D::EngineHint::None; @@ -123,10 +123,10 @@ void HLE_DrawArraysIndirect::Fallback(Core::System& system, Engines::Maxwell3D& } } -void HLE_DrawIndexedIndirect::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { +void HLE_DrawIndexedIndirect::Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { auto topology = static_cast(parameters[0]); if (!maxwell3d.AnyParametersDirty() || !IsTopologySafe(topology)) { - Fallback(system, maxwell3d, parameters); + Fallback(maxwell3d, parameters); return; } @@ -161,7 +161,7 @@ void HLE_DrawIndexedIndirect::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d.replace_table.clear(); } } -void HLE_DrawIndexedIndirect::Fallback(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters) { +void HLE_DrawIndexedIndirect::Fallback(Engines::Maxwell3D& maxwell3d, std::span parameters) { maxwell3d.RefreshParameters(); const u32 instance_count = (maxwell3d.GetRegisterValue(0xD1B) & parameters[2]); const u32 element_base = parameters[4]; @@ -184,7 +184,7 @@ void HLE_DrawIndexedIndirect::Fallback(Core::System& system, Engines::Maxwell3D& maxwell3d.replace_table.clear(); } } -void HLE_MultiLayerClear::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { +void HLE_MultiLayerClear::Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { maxwell3d.RefreshParameters(); ASSERT(parameters.size() == 1); @@ -196,44 +196,47 @@ void HLE_MultiLayerClear::Execute(Core::System& system, Engines::Maxwell3D& maxw maxwell3d.regs.clear_surface.raw = clear_params.raw; maxwell3d.draw_manager.Clear(maxwell3d, num_layers); } -void HLE_MultiDrawIndexedIndirectCount::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { +void HLE_MultiDrawIndexedIndirectCount::Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { const auto topology = Maxwell3D::Regs::PrimitiveTopology(parameters[2]); - if (IsTopologySafe(topology)) { - const u32 start_indirect = parameters[0]; - const u32 end_indirect = parameters[1]; - if (start_indirect >= end_indirect) { - // Nothing to do. - return; - } - const u32 padding = parameters[3]; // padding is in words - // size of each indirect segment - const u32 indirect_words = 5 + padding; - const u32 stride = indirect_words * sizeof(u32); - const std::size_t draw_count = end_indirect - start_indirect; - const u32 estimate = u32(maxwell3d.EstimateIndexBufferSize()); - maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; - auto& params = maxwell3d.draw_manager.indirect_state; - params.is_byte_count = false; - params.is_indexed = true; - params.include_count = true; - params.count_start_address = maxwell3d.GetMacroAddress(4); - params.indirect_start_address = maxwell3d.GetMacroAddress(5); - params.buffer_size = stride * draw_count; - params.max_draw_counts = draw_count; - params.stride = stride; - maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; - maxwell3d.engine_state = Maxwell3D::EngineHint::OnHLEMacro; - maxwell3d.SetHLEReplacementAttributeType(0, 0x640, Maxwell3D::HLEReplacementAttributeType::BaseVertex); - maxwell3d.SetHLEReplacementAttributeType(0, 0x644, Maxwell3D::HLEReplacementAttributeType::BaseInstance); - maxwell3d.SetHLEReplacementAttributeType(0, 0x648, Maxwell3D::HLEReplacementAttributeType::DrawID); - maxwell3d.draw_manager.DrawIndexedIndirect(maxwell3d, topology, 0, estimate); - maxwell3d.engine_state = Maxwell3D::EngineHint::None; - maxwell3d.replace_table.clear(); - } else { - Fallback(system, maxwell3d, parameters); + if (!IsTopologySafe(topology)) { + Fallback(maxwell3d, parameters); + return; } + + const u32 start_indirect = parameters[0]; + const u32 end_indirect = parameters[1]; + if (start_indirect >= end_indirect) { + // Nothing to do. + return; + } + + const u32 padding = parameters[3]; // padding is in words + + // size of each indirect segment + const u32 indirect_words = 5 + padding; + const u32 stride = indirect_words * sizeof(u32); + const std::size_t draw_count = end_indirect - start_indirect; + const u32 estimate = static_cast(maxwell3d.EstimateIndexBufferSize()); + maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; + auto& params = maxwell3d.draw_manager.indirect_state; + params.is_byte_count = false; + params.is_indexed = true; + params.include_count = true; + params.count_start_address = maxwell3d.GetMacroAddress(4); + params.indirect_start_address = maxwell3d.GetMacroAddress(5); + params.buffer_size = stride * draw_count; + params.max_draw_counts = draw_count; + params.stride = stride; + maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; + maxwell3d.engine_state = Maxwell3D::EngineHint::OnHLEMacro; + maxwell3d.SetHLEReplacementAttributeType(0, 0x640, Maxwell3D::HLEReplacementAttributeType::BaseVertex); + maxwell3d.SetHLEReplacementAttributeType(0, 0x644, Maxwell3D::HLEReplacementAttributeType::BaseInstance); + maxwell3d.SetHLEReplacementAttributeType(0, 0x648, Maxwell3D::HLEReplacementAttributeType::DrawID); + maxwell3d.draw_manager.DrawIndexedIndirect(maxwell3d, topology, 0, estimate); + maxwell3d.engine_state = Maxwell3D::EngineHint::None; + maxwell3d.replace_table.clear(); } -void HLE_MultiDrawIndexedIndirectCount::Fallback(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters) { +void HLE_MultiDrawIndexedIndirectCount::Fallback(Engines::Maxwell3D& maxwell3d, std::span parameters) { SCOPE_EXIT { // Clean everything. maxwell3d.regs.vertex_id_base = 0x0; @@ -247,7 +250,7 @@ void HLE_MultiDrawIndexedIndirectCount::Fallback(Core::System& system, Engines:: // Nothing to do. return; } - const auto topology = Maxwell3D::Regs::PrimitiveTopology(parameters[2]); + const auto topology = static_cast(parameters[2]); const u32 padding = parameters[3]; const std::size_t max_draws = parameters[4]; const u32 indirect_words = 5 + padding; @@ -262,41 +265,41 @@ void HLE_MultiDrawIndexedIndirectCount::Fallback(Core::System& system, Engines:: maxwell3d.engine_state = Maxwell3D::EngineHint::OnHLEMacro; maxwell3d.SetHLEReplacementAttributeType(0, 0x640, Maxwell3D::HLEReplacementAttributeType::BaseVertex); maxwell3d.SetHLEReplacementAttributeType(0, 0x644, Maxwell3D::HLEReplacementAttributeType::BaseInstance); - maxwell3d.CallMethod(system, 0x8e3, 0x648, true); - maxwell3d.CallMethod(system, 0x8e4, u32(index), true); + maxwell3d.CallMethod(0x8e3, 0x648, true); + maxwell3d.CallMethod(0x8e4, static_cast(index), true); maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; maxwell3d.draw_manager.DrawIndex(maxwell3d, topology, parameters[base + 2], parameters[base], base_vertex, base_instance, parameters[base + 1]); } } -void HLE_DrawIndirectByteCount::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { +void HLE_DrawIndirectByteCount::Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { const bool force = maxwell3d.Rasterizer().HasDrawTransformFeedback(); - if (force) { - auto topology = Maxwell3D::Regs::PrimitiveTopology(parameters[0] & 0xFFFFU); - auto& params = maxwell3d.draw_manager.indirect_state; - params.is_byte_count = true; - params.is_indexed = false; - params.include_count = false; - params.count_start_address = 0; - params.indirect_start_address = maxwell3d.GetMacroAddress(2); - params.buffer_size = 4; - params.max_draw_counts = 1; - params.stride = parameters[1]; - maxwell3d.regs.draw.begin = parameters[0]; - maxwell3d.regs.draw_auto_stride = parameters[1]; - maxwell3d.regs.draw_auto_byte_count = parameters[2]; - maxwell3d.draw_manager.DrawArrayIndirect(maxwell3d, topology); - } else { - Fallback(system, maxwell3d, parameters); + if (!force) { + Fallback(maxwell3d, parameters); + return; } + auto topology = Maxwell3D::Regs::PrimitiveTopology(parameters[0] & 0xFFFFU); + auto& params = maxwell3d.draw_manager.indirect_state; + params.is_byte_count = true; + params.is_indexed = false; + params.include_count = false; + params.count_start_address = 0; + params.indirect_start_address = maxwell3d.GetMacroAddress(2); + params.buffer_size = 4; + params.max_draw_counts = 1; + params.stride = parameters[1]; + maxwell3d.regs.draw.begin = parameters[0]; + maxwell3d.regs.draw_auto_stride = parameters[1]; + maxwell3d.regs.draw_auto_byte_count = parameters[2]; + maxwell3d.draw_manager.DrawArrayIndirect(maxwell3d, topology); } -void HLE_DrawIndirectByteCount::Fallback(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters) { +void HLE_DrawIndirectByteCount::Fallback(Engines::Maxwell3D& maxwell3d, std::span parameters) { maxwell3d.RefreshParameters(); maxwell3d.regs.draw.begin = parameters[0]; maxwell3d.regs.draw_auto_stride = parameters[1]; maxwell3d.regs.draw_auto_byte_count = parameters[2]; maxwell3d.draw_manager.DrawArray(maxwell3d, maxwell3d.regs.draw.topology, 0, maxwell3d.regs.draw_auto_byte_count / maxwell3d.regs.draw_auto_stride, 0, 1); } -void HLE_C713C83D8F63CCF3::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { +void HLE_C713C83D8F63CCF3::Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { maxwell3d.RefreshParameters(); const u32 offset = (parameters[0] & 0x3FFFFFFF) << 2; const u32 address = maxwell3d.regs.shadow_scratch[24]; @@ -306,7 +309,7 @@ void HLE_C713C83D8F63CCF3::Execute(Core::System& system, Engines::Maxwell3D& max const_buffer.address_low = address << 8; const_buffer.offset = offset; } -void HLE_D7333D26E0A93EDE::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { +void HLE_D7333D26E0A93EDE::Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { maxwell3d.RefreshParameters(); const size_t index = parameters[0]; const u32 address = maxwell3d.regs.shadow_scratch[42 + index]; @@ -316,7 +319,7 @@ void HLE_D7333D26E0A93EDE::Execute(Core::System& system, Engines::Maxwell3D& max const_buffer.address_high = (address >> 24) & 0xFF; const_buffer.address_low = address << 8; } -void HLE_BindShader::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { +void HLE_BindShader::Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { maxwell3d.RefreshParameters(); auto& regs = maxwell3d.regs; const u32 index = parameters[0]; @@ -340,7 +343,7 @@ void HLE_BindShader::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d bind_group.raw_config = 0x11; maxwell3d.ProcessCBBind(bind_group_id); } -void HLE_SetRasterBoundingBox::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { +void HLE_SetRasterBoundingBox::Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { maxwell3d.RefreshParameters(); const u32 raster_mode = parameters[0]; auto& regs = maxwell3d.regs; @@ -349,7 +352,7 @@ void HLE_SetRasterBoundingBox::Execute(Core::System& system, Engines::Maxwell3D& regs.raster_bounding_box.raw = raster_mode & 0xFFFFF00F; regs.raster_bounding_box.pad.Assign(scratch_data & raster_enabled); } -void HLE_ClearConstBuffer::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { +void HLE_ClearConstBuffer::Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { static constexpr std::array zeroes{}; //must be bigger than either 7000 or 5F00 maxwell3d.RefreshParameters(); auto& regs = maxwell3d.regs; @@ -359,7 +362,7 @@ void HLE_ClearConstBuffer::Execute(Core::System& system, Engines::Maxwell3D& max regs.const_buffer.offset = 0; maxwell3d.ProcessCBMultiData(zeroes.data(), parameters[2] * 4); } -void HLE_ClearMemory::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { +void HLE_ClearMemory::Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { maxwell3d.RefreshParameters(); const u32 needed_memory = parameters[2] / sizeof(u32); if (needed_memory > zero_memory.size()) { @@ -370,10 +373,10 @@ void HLE_ClearMemory::Execute(Core::System& system, Engines::Maxwell3D& maxwell3 regs.upload.line_count = 1; regs.upload.dest.address_high = parameters[0]; regs.upload.dest.address_low = parameters[1]; - maxwell3d.CallMethod(system, size_t(MAXWELL3D_REG_INDEX(launch_dma)), 0x1011, true); - maxwell3d.CallMultiMethod(system, size_t(MAXWELL3D_REG_INDEX(inline_data)), zero_memory.data(), needed_memory, needed_memory); + maxwell3d.CallMethod(size_t(MAXWELL3D_REG_INDEX(launch_dma)), 0x1011, true); + maxwell3d.CallMultiMethod(size_t(MAXWELL3D_REG_INDEX(inline_data)), zero_memory.data(), needed_memory, needed_memory); } -void HLE_TransformFeedbackSetup::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { +void HLE_TransformFeedbackSetup::Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { maxwell3d.RefreshParameters(); auto& regs = maxwell3d.regs; regs.transform_feedback_enabled = 1; @@ -385,8 +388,8 @@ void HLE_TransformFeedbackSetup::Execute(Core::System& system, Engines::Maxwell3 regs.upload.line_count = 1; regs.upload.dest.address_high = parameters[0]; regs.upload.dest.address_low = parameters[1]; - maxwell3d.CallMethod(system, size_t(MAXWELL3D_REG_INDEX(launch_dma)), 0x1011, true); - maxwell3d.CallMethod(system, size_t(MAXWELL3D_REG_INDEX(inline_data)), regs.transform_feedback.controls[0].stride, true); + maxwell3d.CallMethod(size_t(MAXWELL3D_REG_INDEX(launch_dma)), 0x1011, true); + maxwell3d.CallMethod(size_t(MAXWELL3D_REG_INDEX(inline_data)), regs.transform_feedback.controls[0].stride, true); maxwell3d.Rasterizer().RegisterTransformFeedback(regs.upload.dest.Address()); } @@ -426,7 +429,7 @@ void HLE_TransformFeedbackSetup::Execute(Core::System& system, Engines::Maxwell3 } } -void MacroInterpreterImpl::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span params, u32 method) { +void MacroInterpreterImpl::Execute(Engines::Maxwell3D& maxwell3d, std::span params, u32 method) { Reset(); registers[1] = params[0]; @@ -436,7 +439,7 @@ void MacroInterpreterImpl::Execute(Core::System& system, Engines::Maxwell3D& max // Execute the code until we hit an exit condition. bool keep_executing = true; while (keep_executing) { - keep_executing = Step(system, maxwell3d, false); + keep_executing = Step(maxwell3d, false); } // Assert the the macro used all the input parameters @@ -459,7 +462,7 @@ void MacroInterpreterImpl::Reset() { /// @brief Executes a single macro instruction located at the current program counter. Returns whether /// the interpreter should keep running. /// @param is_delay_slot Whether the current step is being executed due to a delay slot in a previous instruction. -bool MacroInterpreterImpl::Step(Core::System& system, Engines::Maxwell3D& maxwell3d, bool is_delay_slot) { +bool MacroInterpreterImpl::Step(Engines::Maxwell3D& maxwell3d, bool is_delay_slot) { u32 base_address = pc; Macro::Opcode opcode = GetOpcode(); @@ -475,11 +478,11 @@ bool MacroInterpreterImpl::Step(Core::System& system, Engines::Maxwell3D& maxwel switch (opcode.operation) { case Macro::Operation::ALU: { u32 result = GetALUResult(opcode.alu_operation, GetRegister(opcode.src_a), GetRegister(opcode.src_b)); - ProcessResult(system, maxwell3d, opcode.result_operation, opcode.dst, result); + ProcessResult(maxwell3d, opcode.result_operation, opcode.dst, result); break; } case Macro::Operation::AddImmediate: { - ProcessResult(system, maxwell3d, opcode.result_operation, opcode.dst, GetRegister(opcode.src_a) + opcode.immediate); + ProcessResult(maxwell3d, opcode.result_operation, opcode.dst, GetRegister(opcode.src_a) + opcode.immediate); break; } case Macro::Operation::ExtractInsert: { @@ -489,7 +492,7 @@ bool MacroInterpreterImpl::Step(Core::System& system, Engines::Maxwell3D& maxwel src = (src >> opcode.bf_src_bit) & opcode.GetBitfieldMask(); dst &= ~(opcode.GetBitfieldMask() << opcode.bf_dst_bit); dst |= src << opcode.bf_dst_bit; - ProcessResult(system, maxwell3d, opcode.result_operation, opcode.dst, dst); + ProcessResult(maxwell3d, opcode.result_operation, opcode.dst, dst); break; } case Macro::Operation::ExtractShiftLeftImmediate: { @@ -498,7 +501,7 @@ bool MacroInterpreterImpl::Step(Core::System& system, Engines::Maxwell3D& maxwel u32 result = ((src >> dst) & opcode.GetBitfieldMask()) << opcode.bf_dst_bit; - ProcessResult(system, maxwell3d, opcode.result_operation, opcode.dst, result); + ProcessResult(maxwell3d, opcode.result_operation, opcode.dst, result); break; } case Macro::Operation::ExtractShiftLeftRegister: { @@ -507,12 +510,12 @@ bool MacroInterpreterImpl::Step(Core::System& system, Engines::Maxwell3D& maxwel u32 result = ((src >> opcode.bf_src_bit) & opcode.GetBitfieldMask()) << dst; - ProcessResult(system, maxwell3d, opcode.result_operation, opcode.dst, result); + ProcessResult(maxwell3d, opcode.result_operation, opcode.dst, result); break; } case Macro::Operation::Read: { u32 result = Read(maxwell3d, GetRegister(opcode.src_a) + opcode.immediate); - ProcessResult(system, maxwell3d, opcode.result_operation, opcode.dst, result); + ProcessResult(maxwell3d, opcode.result_operation, opcode.dst, result); break; } case Macro::Operation::Branch: { @@ -528,7 +531,7 @@ bool MacroInterpreterImpl::Step(Core::System& system, Engines::Maxwell3D& maxwel delayed_pc = base_address + opcode.GetBranchTarget(); // Execute one more instruction due to the delay slot. - return Step(system, maxwell3d, true); + return Step(maxwell3d, true); } break; } @@ -541,7 +544,7 @@ bool MacroInterpreterImpl::Step(Core::System& system, Engines::Maxwell3D& maxwel // cause an exit if it's executed inside a delay slot. if (opcode.is_exit && !is_delay_slot) { // Exit has a delay slot, execute the next instruction - Step(system, maxwell3d, true); + Step(maxwell3d, true); return false; } return true; @@ -588,7 +591,7 @@ u32 MacroInterpreterImpl::GetALUResult(Macro::ALUOperation operation, u32 src_a, } /// Performs the result operation on the input result and stores it in the specified register (if necessary). -void MacroInterpreterImpl::ProcessResult(Core::System& system, Engines::Maxwell3D& maxwell3d, Macro::ResultOperation operation, u32 reg, u32 result) { +void MacroInterpreterImpl::ProcessResult(Engines::Maxwell3D& maxwell3d, Macro::ResultOperation operation, u32 reg, u32 result) { switch (operation) { case Macro::ResultOperation::IgnoreAndFetch: // Fetch parameter and ignore result. @@ -606,12 +609,12 @@ void MacroInterpreterImpl::ProcessResult(Core::System& system, Engines::Maxwell3 case Macro::ResultOperation::FetchAndSend: // Fetch parameter and send result. SetRegister(reg, FetchParameter()); - Send(system, maxwell3d, result); + Send(maxwell3d, result); break; case Macro::ResultOperation::MoveAndSend: // Move and send result. SetRegister(reg, result); - Send(system, maxwell3d, result); + Send(maxwell3d, result); break; case Macro::ResultOperation::FetchAndSetMethod: // Fetch parameter and use result as Method Address. @@ -622,13 +625,13 @@ void MacroInterpreterImpl::ProcessResult(Core::System& system, Engines::Maxwell3 // Move result and use as Method Address, then fetch and send parameter. SetRegister(reg, result); SetMethodAddress(result); - Send(system, maxwell3d, FetchParameter()); + Send(maxwell3d, FetchParameter()); break; case Macro::ResultOperation::MoveAndSetMethodSend: // Move result and use as Method Address, then send bits 12:17 of result. SetRegister(reg, result); SetMethodAddress(result); - Send(system, maxwell3d, (result >> 12) & 0b111111); + Send(maxwell3d, (result >> 12) & 0b111111); break; default: UNIMPLEMENTED_MSG("Unimplemented result operation {}", operation); @@ -669,8 +672,8 @@ void MacroInterpreterImpl::SetRegister(u32 register_id, u32 value) { } /// Calls a GPU Engine method with the input parameter. -void MacroInterpreterImpl::Send(Core::System& system, Engines::Maxwell3D& maxwell3d, u32 value) { - maxwell3d.CallMethod(system, method_address.address, value, true); +void MacroInterpreterImpl::Send(Engines::Maxwell3D& maxwell3d, u32 value) { + maxwell3d.CallMethod(method_address.address, value, true); // Increment the method address by the method increment. method_address.address.Assign(method_address.address.Value() + method_address.increment.Value()); } @@ -721,35 +724,34 @@ static const auto default_cg_mode = nullptr; //Allow RWE #endif struct MacroJITx64Impl final : public Xbyak::CodeGenerator, public DynamicCachedMacro { - explicit MacroJITx64Impl(Core::System& system, std::span code_) + explicit MacroJITx64Impl(std::span code_) : Xbyak::CodeGenerator(MAX_CODE_SIZE, default_cg_mode) , code{code_} { - Compile(system); + Compile(); } - void Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, u32 method) override; + void Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, u32 method) override; - void Compile_ALU(Core::System& system, Macro::Opcode opcode); - void Compile_AddImmediate(Core::System& system, Macro::Opcode opcode); - void Compile_ExtractInsert(Core::System& system, Macro::Opcode opcode); - void Compile_ExtractShiftLeftImmediate(Core::System& system, Macro::Opcode opcode); - void Compile_ExtractShiftLeftRegister(Core::System& system, Macro::Opcode opcode); - void Compile_Read(Core::System& system, Macro::Opcode opcode); + void Compile_ALU(Macro::Opcode opcode); + void Compile_AddImmediate(Macro::Opcode opcode); + void Compile_ExtractInsert(Macro::Opcode opcode); + void Compile_ExtractShiftLeftImmediate(Macro::Opcode opcode); + void Compile_ExtractShiftLeftRegister(Macro::Opcode opcode); + void Compile_Read(Macro::Opcode opcode); void Compile_Branch(Macro::Opcode opcode); void Optimizer_ScanFlags(); - void Compile(Core::System& system); - bool Compile_NextInstruction(Core::System& system); + void Compile(); + bool Compile_NextInstruction(); Xbyak::Reg32 Compile_FetchParameter(); Xbyak::Reg32 Compile_GetRegister(u32 index, Xbyak::Reg32 dst); - void Compile_ProcessResult(Core::System& system, Macro::ResultOperation operation, u32 reg); - void Compile_Send(Core::System& system, Xbyak::Reg32 value); + void Compile_ProcessResult(Macro::ResultOperation operation, u32 reg); + void Compile_Send(Xbyak::Reg32 value); Macro::Opcode GetOpCode() const; struct JITState { - Engines::Maxwell3D* maxwell3d = nullptr; - Core::System* system = nullptr; + Engines::Maxwell3D* maxwell3d{}; std::array registers{}; u32 carry_flag{}; }; @@ -775,16 +777,15 @@ struct MacroJITx64Impl final : public Xbyak::CodeGenerator, public DynamicCached std::span code; }; -void MacroJITx64Impl::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, u32 method) { +void MacroJITx64Impl::Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, u32 method) { ASSERT_OR_EXECUTE(program != nullptr, { return; }); JITState state{}; state.maxwell3d = &maxwell3d; - state.system = &system; state.registers = {}; program(&state, parameters.data(), parameters.data() + parameters.size()); } -void MacroJITx64Impl::Compile_ALU(Core::System& system, Macro::Opcode opcode) { +void MacroJITx64Impl::Compile_ALU(Macro::Opcode opcode) { const bool is_a_zero = opcode.src_a == 0; const bool is_b_zero = opcode.src_b == 0; const bool valid_operation = !is_a_zero && !is_b_zero; @@ -901,10 +902,10 @@ void MacroJITx64Impl::Compile_ALU(Core::System& system, Macro::Opcode opcode) { UNIMPLEMENTED_MSG("Unimplemented ALU operation {}", opcode.alu_operation.Value()); break; } - Compile_ProcessResult(system, opcode.result_operation, opcode.dst); + Compile_ProcessResult(opcode.result_operation, opcode.dst); } -void MacroJITx64Impl::Compile_AddImmediate(Core::System& system, Macro::Opcode opcode) { +void MacroJITx64Impl::Compile_AddImmediate(Macro::Opcode opcode) { if (optimizer.skip_dummy_addimmediate) { // Games tend to use this as an exit instruction placeholder. It's to encode an instruction // without doing anything. In our case we can just not emit anything. @@ -939,10 +940,10 @@ void MacroJITx64Impl::Compile_AddImmediate(Core::System& system, Macro::Opcode o sub(result, opcode.immediate * -1); } } - Compile_ProcessResult(system, opcode.result_operation, opcode.dst); + Compile_ProcessResult(opcode.result_operation, opcode.dst); } -void MacroJITx64Impl::Compile_ExtractInsert(Core::System& system, Macro::Opcode opcode) { +void MacroJITx64Impl::Compile_ExtractInsert(Macro::Opcode opcode) { auto dst = Compile_GetRegister(opcode.src_a, RESULT); auto src = Compile_GetRegister(opcode.src_b, eax); @@ -953,10 +954,10 @@ void MacroJITx64Impl::Compile_ExtractInsert(Core::System& system, Macro::Opcode shl(src, opcode.bf_dst_bit); or_(dst, src); - Compile_ProcessResult(system, opcode.result_operation, opcode.dst); + Compile_ProcessResult(opcode.result_operation, opcode.dst); } -void MacroJITx64Impl::Compile_ExtractShiftLeftImmediate(Core::System& system, Macro::Opcode opcode) { +void MacroJITx64Impl::Compile_ExtractShiftLeftImmediate(Macro::Opcode opcode) { const auto dst = Compile_GetRegister(opcode.src_a, ecx); const auto src = Compile_GetRegister(opcode.src_b, RESULT); @@ -964,10 +965,10 @@ void MacroJITx64Impl::Compile_ExtractShiftLeftImmediate(Core::System& system, Ma and_(src, opcode.GetBitfieldMask()); shl(src, opcode.bf_dst_bit); - Compile_ProcessResult(system, opcode.result_operation, opcode.dst); + Compile_ProcessResult(opcode.result_operation, opcode.dst); } -void MacroJITx64Impl::Compile_ExtractShiftLeftRegister(Core::System& system, Macro::Opcode opcode) { +void MacroJITx64Impl::Compile_ExtractShiftLeftRegister(Macro::Opcode opcode) { const auto dst = Compile_GetRegister(opcode.src_a, ecx); const auto src = Compile_GetRegister(opcode.src_b, RESULT); @@ -975,10 +976,10 @@ void MacroJITx64Impl::Compile_ExtractShiftLeftRegister(Core::System& system, Mac and_(src, opcode.GetBitfieldMask()); shl(src, dst.cvt8()); - Compile_ProcessResult(system, opcode.result_operation, opcode.dst); + Compile_ProcessResult(opcode.result_operation, opcode.dst); } -void MacroJITx64Impl::Compile_Read(Core::System& system, Macro::Opcode opcode) { +void MacroJITx64Impl::Compile_Read(Macro::Opcode opcode) { if (optimizer.zero_reg_skip && opcode.src_a == 0) { if (opcode.immediate == 0) { xor_(RESULT, RESULT); @@ -1004,21 +1005,23 @@ void MacroJITx64Impl::Compile_Read(Core::System& system, Macro::Opcode opcode) { int3(); L(pass_range_check); } - mov(rax, qword[STATE + offsetof(JITState, maxwell3d)]); - mov(RESULT, dword[rax + offsetof(Engines::Maxwell3D, regs) + offsetof(Engines::Maxwell3D::Regs, reg_array) + RESULT.cvt64() * sizeof(u32)]); - Compile_ProcessResult(system, opcode.result_operation, opcode.dst); + mov(rax, qword[STATE]); + mov(RESULT, + dword[rax + offsetof(Engines::Maxwell3D, regs) + + offsetof(Engines::Maxwell3D::Regs, reg_array) + RESULT.cvt64() * sizeof(u32)]); + + Compile_ProcessResult(opcode.result_operation, opcode.dst); } -static void MacroJIT_SendThunk(Core::System* system, Engines::Maxwell3D* maxwell3d, Macro::MethodAddress method_address, u32 value) { - maxwell3d->CallMethod(*system, method_address.address, value, true); +static void MacroJIT_SendThunk(Engines::Maxwell3D* maxwell3d, Macro::MethodAddress method_address, u32 value) { + maxwell3d->CallMethod(method_address.address, value, true); } -void MacroJITx64Impl::Compile_Send(Core::System& system, Xbyak::Reg32 value) { +void MacroJITx64Impl::Compile_Send(Xbyak::Reg32 value) { Common::X64::ABI_PushRegistersAndAdjustStack(*this, PersistentCallerSavedRegs(), 0); - mov(Common::X64::ABI_PARAM1, qword[STATE + offsetof(JITState, system)]); - mov(Common::X64::ABI_PARAM2, qword[STATE + offsetof(JITState, maxwell3d)]); - mov(Common::X64::ABI_PARAM3.cvt32(), METHOD_ADDRESS); - mov(Common::X64::ABI_PARAM4.cvt32(), value); + mov(Common::X64::ABI_PARAM1, qword[STATE]); + mov(Common::X64::ABI_PARAM2.cvt32(), METHOD_ADDRESS); + mov(Common::X64::ABI_PARAM3.cvt32(), value); Common::X64::CallFarFunction(*this, &MacroJIT_SendThunk); Common::X64::ABI_PopRegistersAndAdjustStack(*this, PersistentCallerSavedRegs(), 0); @@ -1042,8 +1045,9 @@ void MacroJITx64Impl::Compile_Send(Core::System& system, Xbyak::Reg32 value) { } void MacroJITx64Impl::Compile_Branch(Macro::Opcode opcode) { - ASSERT(!is_delay_slot && "Executing a branch in a delay slot is not valid"); - const s32 jump_address = s32(pc) + s32(opcode.GetBranchTarget() / sizeof(s32)); + ASSERT_MSG(!is_delay_slot, "Executing a branch in a delay slot is not valid"); + const s32 jump_address = + static_cast(pc) + static_cast(opcode.GetBranchTarget() / sizeof(s32)); Xbyak::Label end; auto value = Compile_GetRegister(opcode.src_a, eax); @@ -1112,7 +1116,7 @@ void MacroJITx64Impl::Optimizer_ScanFlags() { } } -void MacroJITx64Impl::Compile(Core::System& system) { +void MacroJITx64Impl::Compile() { // Matching PROTECT_RE needed for W^X systems setProtectMode(Xbyak::CodeArray::ProtectMode::PROTECT_RW); labels.fill(Xbyak::Label()); @@ -1154,7 +1158,7 @@ void MacroJITx64Impl::Compile(Core::System& system) { next_opcode = {}; } pc = i; - Compile_NextInstruction(system); + Compile_NextInstruction(); } L(end_of_code); @@ -1166,7 +1170,7 @@ void MacroJITx64Impl::Compile(Core::System& system) { program = getCode(); } -bool MacroJITx64Impl::Compile_NextInstruction(Core::System& system) { +bool MacroJITx64Impl::Compile_NextInstruction() { const auto opcode = GetOpCode(); if (labels[pc].getAddress()) { return false; @@ -1176,22 +1180,22 @@ bool MacroJITx64Impl::Compile_NextInstruction(Core::System& system) { switch (opcode.operation) { case Macro::Operation::ALU: - Compile_ALU(system, opcode); + Compile_ALU(opcode); break; case Macro::Operation::AddImmediate: - Compile_AddImmediate(system, opcode); + Compile_AddImmediate(opcode); break; case Macro::Operation::ExtractInsert: - Compile_ExtractInsert(system, opcode); + Compile_ExtractInsert(opcode); break; case Macro::Operation::ExtractShiftLeftImmediate: - Compile_ExtractShiftLeftImmediate(system, opcode); + Compile_ExtractShiftLeftImmediate(opcode); break; case Macro::Operation::ExtractShiftLeftRegister: - Compile_ExtractShiftLeftRegister(system, opcode); + Compile_ExtractShiftLeftRegister(opcode); break; case Macro::Operation::Read: - Compile_Read(system, opcode); + Compile_Read(opcode); break; case Macro::Operation::Branch: Compile_Branch(opcode); @@ -1263,7 +1267,7 @@ Xbyak::Reg32 MacroJITx64Impl::Compile_GetRegister(u32 index, Xbyak::Reg32 dst) { return dst; } -void MacroJITx64Impl::Compile_ProcessResult(Core::System& system, Macro::ResultOperation operation, u32 reg) { +void MacroJITx64Impl::Compile_ProcessResult(Macro::ResultOperation operation, u32 reg) { const auto SetRegister = [this](u32 reg_index, const Xbyak::Reg32& result) { // Register 0 is supposed to always return 0. NOP is implemented as a store to the zero // register. @@ -1288,12 +1292,12 @@ void MacroJITx64Impl::Compile_ProcessResult(Core::System& system, Macro::ResultO case Macro::ResultOperation::FetchAndSend: // Fetch parameter and send result. SetRegister(reg, Compile_FetchParameter()); - Compile_Send(system, RESULT); + Compile_Send(RESULT); break; case Macro::ResultOperation::MoveAndSend: // Move and send result. SetRegister(reg, RESULT); - Compile_Send(system, RESULT); + Compile_Send(RESULT); break; case Macro::ResultOperation::FetchAndSetMethod: // Fetch parameter and use result as Method Address. @@ -1304,7 +1308,7 @@ void MacroJITx64Impl::Compile_ProcessResult(Core::System& system, Macro::ResultO // Move result and use as Method Address, then fetch and send parameter. SetRegister(reg, RESULT); SetMethodAddress(RESULT); - Compile_Send(system, Compile_FetchParameter()); + Compile_Send(Compile_FetchParameter()); break; case Macro::ResultOperation::MoveAndSetMethodSend: // Move result and use as Method Address, then send bits 12:17 of result. @@ -1312,7 +1316,7 @@ void MacroJITx64Impl::Compile_ProcessResult(Core::System& system, Macro::ResultO SetMethodAddress(RESULT); shr(RESULT, 12); and_(RESULT, 0b111111); - Compile_Send(system, RESULT); + Compile_Send(RESULT); break; default: UNIMPLEMENTED_MSG("Unimplemented macro operation {}", operation); @@ -1353,36 +1357,36 @@ static void Dump(u64 hash, std::span code, bool decompiled = false) { macro_file.write(reinterpret_cast(code.data()), code.size_bytes()); } -void MacroEngine::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, u32 method, std::span parameters) { - auto const execute_variant = [&system, &maxwell3d, ¶meters, method](AnyCachedMacro& acm) { +void MacroEngine::Execute(Engines::Maxwell3D& maxwell3d, u32 method, std::span parameters) { + auto const execute_variant = [&maxwell3d, ¶meters, method](AnyCachedMacro& acm) { if (auto a = std::get_if(&acm)) - a->Execute(system, maxwell3d, parameters, method); + a->Execute(maxwell3d, parameters, method); if (auto a = std::get_if(&acm)) - a->Execute(system, maxwell3d, parameters, method); + a->Execute(maxwell3d, parameters, method); if (auto a = std::get_if(&acm)) - a->Execute(system, maxwell3d, parameters, method); + a->Execute(maxwell3d, parameters, method); if (auto a = std::get_if(&acm)) - a->Execute(system, maxwell3d, parameters, method); + a->Execute(maxwell3d, parameters, method); if (auto a = std::get_if(&acm)) - a->Execute(system, maxwell3d, parameters, method); + a->Execute(maxwell3d, parameters, method); if (auto a = std::get_if(&acm)) - a->Execute(system, maxwell3d, parameters, method); + a->Execute(maxwell3d, parameters, method); if (auto a = std::get_if(&acm)) - a->Execute(system, maxwell3d, parameters, method); + a->Execute(maxwell3d, parameters, method); if (auto a = std::get_if(&acm)) - a->Execute(system, maxwell3d, parameters, method); + a->Execute(maxwell3d, parameters, method); if (auto a = std::get_if(&acm)) - a->Execute(system, maxwell3d, parameters, method); + a->Execute(maxwell3d, parameters, method); if (auto a = std::get_if(&acm)) - a->Execute(system, maxwell3d, parameters, method); + a->Execute(maxwell3d, parameters, method); if (auto a = std::get_if(&acm)) - a->Execute(system, maxwell3d, parameters, method); + a->Execute(maxwell3d, parameters, method); if (auto a = std::get_if(&acm)) - a->Execute(system, maxwell3d, parameters, method); + a->Execute(maxwell3d, parameters, method); if (auto a = std::get_if(&acm)) - a->Execute(system, maxwell3d, parameters, method); + a->Execute(maxwell3d, parameters, method); if (auto a = std::get_if>(&acm)) - a->get()->Execute(system, maxwell3d, parameters, method); + a->get()->Execute(maxwell3d, parameters, method); }; if (auto const it = macro_cache.find(method); it != macro_cache.end()) { auto& ci = it->second; @@ -1413,9 +1417,9 @@ void MacroEngine::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, u code.resize(macro_cached.size() - rebased_method); std::memcpy(code.data(), macro_cached.data() + rebased_method, code.size() * sizeof(u32)); ci.hash = Common::HashValue(code); - ci.program = Compile(system, maxwell3d, code); + ci.program = Compile(maxwell3d, code); } else { - ci.program = Compile(system, maxwell3d, macro_code->second); + ci.program = Compile(maxwell3d, macro_code->second); ci.hash = Common::HashValue(macro_code->second); } if (CanBeHLEProgram(ci.hash) && !Settings::values.disable_macro_hle) { @@ -1430,10 +1434,10 @@ void MacroEngine::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, u } } -AnyCachedMacro MacroEngine::Compile(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span code) { +AnyCachedMacro MacroEngine::Compile(Engines::Maxwell3D& maxwell3d, std::span code) { #ifdef ARCHITECTURE_x86_64 if (!is_interpreted) - return std::make_unique(system, code); + return std::make_unique(code); #endif return MacroInterpreterImpl(code); } diff --git a/src/video_core/macro.h b/src/video_core/macro.h index 43b32ed920..a9a8f2de04 100644 --- a/src/video_core/macro.h +++ b/src/video_core/macro.h @@ -14,10 +14,6 @@ #include "common/bit_field.h" #include "common/common_types.h" -namespace Core { -class System; -} - namespace Tegra { namespace Engines { @@ -110,61 +106,61 @@ struct HLEMacro { /// also assigning the base vertex/instance. struct HLE_DrawArraysIndirect final { HLE_DrawArraysIndirect(bool extended_) noexcept : extended{extended_} {} - void Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); - void Fallback(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters); + void Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); + void Fallback(Engines::Maxwell3D& maxwell3d, std::span parameters); bool extended; }; /// @note: these macros have two versions, a normal and extended version, with the extended version /// also assigning the base vertex/instance. struct HLE_DrawIndexedIndirect final { explicit HLE_DrawIndexedIndirect(bool extended_) noexcept : extended{extended_} {} - void Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); - void Fallback(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters); + void Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); + void Fallback(Engines::Maxwell3D& maxwell3d, std::span parameters); bool extended; }; struct HLE_MultiLayerClear final { - void Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); + void Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); }; struct HLE_MultiDrawIndexedIndirectCount final { - void Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); - void Fallback(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters); + void Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); + void Fallback(Engines::Maxwell3D& maxwell3d, std::span parameters); }; struct HLE_DrawIndirectByteCount final { - void Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); - void Fallback(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters); + void Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); + void Fallback(Engines::Maxwell3D& maxwell3d, std::span parameters); }; struct HLE_C713C83D8F63CCF3 final { - void Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); + void Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); }; struct HLE_D7333D26E0A93EDE final { - void Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); + void Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); }; struct HLE_BindShader final { - void Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); + void Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); }; struct HLE_SetRasterBoundingBox final { - void Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); + void Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); }; struct HLE_ClearConstBuffer final { HLE_ClearConstBuffer(size_t base_size_) noexcept : base_size{base_size_} {} - void Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); + void Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); size_t base_size; }; struct HLE_ClearMemory final { - void Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); + void Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); std::vector zero_memory; }; struct HLE_TransformFeedbackSetup final { - void Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); + void Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); }; struct MacroInterpreterImpl final { MacroInterpreterImpl() {} MacroInterpreterImpl(std::span code_) : code{code_} {} - void Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span params, u32 method); + void Execute(Engines::Maxwell3D& maxwell3d, std::span params, u32 method); void Reset(); - bool Step(Core::System& system, Engines::Maxwell3D& maxwell3d, bool is_delay_slot); + bool Step(Engines::Maxwell3D& maxwell3d, bool is_delay_slot); u32 GetALUResult(Macro::ALUOperation operation, u32 src_a, u32 src_b); - void ProcessResult(Core::System& system, Engines::Maxwell3D& maxwell3d, Macro::ResultOperation operation, u32 reg, u32 result); + void ProcessResult(Engines::Maxwell3D& maxwell3d, Macro::ResultOperation operation, u32 reg, u32 result); bool EvaluateBranchCondition(Macro::BranchCondition cond, u32 value) const; Macro::Opcode GetOpcode() const; u32 GetRegister(u32 register_id) const; @@ -173,7 +169,7 @@ struct MacroInterpreterImpl final { [[nodiscard]] inline void SetMethodAddress(u32 address) noexcept { method_address.raw = address; } - void Send(Core::System& system, Engines::Maxwell3D& maxwell3d, u32 value); + void Send(Engines::Maxwell3D& maxwell3d, u32 value); u32 Read(Engines::Maxwell3D& maxwell3d, u32 method) const; u32 FetchParameter(); /// General purpose macro registers. @@ -196,7 +192,7 @@ struct DynamicCachedMacro { /// Executes the macro code with the specified input parameters. /// @param parameters The parameters of the macro /// @param method The method to execute - virtual void Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, u32 method) = 0; + virtual void Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, u32 method) = 0; }; using AnyCachedMacro = std::variant< @@ -231,8 +227,8 @@ struct MacroEngine { uploaded_macro_code.erase(method); } // Compiles the macro if its not in the cache, and executes the compiled macro - void Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, u32 method, std::span parameters); - AnyCachedMacro Compile(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span code); + void Execute(Engines::Maxwell3D& maxwell3d, u32 method, std::span parameters); + AnyCachedMacro Compile(Engines::Maxwell3D& maxwell3d, std::span code); struct CacheInfo { AnyCachedMacro program; u64 hash{}; diff --git a/src/video_core/renderer_opengl/gl_state_tracker.cpp b/src/video_core/renderer_opengl/gl_state_tracker.cpp index dc91723300..d53b422cac 100644 --- a/src/video_core/renderer_opengl/gl_state_tracker.cpp +++ b/src/video_core/renderer_opengl/gl_state_tracker.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -207,7 +204,7 @@ void SetupDirtyMisc(Tables& tables) { } // Anonymous namespace void StateTracker::SetupTables(Tegra::Control::ChannelState& channel_state) { - auto& tables{channel_state.payload->maxwell_3d.dirty.tables}; + auto& tables{channel_state.maxwell_3d->dirty.tables}; SetupDirtyFlags(tables); SetupDirtyColorMasks(tables); SetupDirtyViewports(tables); @@ -234,7 +231,7 @@ void StateTracker::SetupTables(Tegra::Control::ChannelState& channel_state) { } void StateTracker::ChangeChannel(Tegra::Control::ChannelState& channel_state) { - flags = &channel_state.payload->maxwell_3d.dirty.flags; + flags = &channel_state.maxwell_3d->dirty.flags; } void StateTracker::InvalidateState() { diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp index d99e528bc0..2bca1ba28f 100644 --- a/src/video_core/renderer_vulkan/blit_image.cpp +++ b/src/video_core/renderer_vulkan/blit_image.cpp @@ -502,9 +502,9 @@ BlitImageHelper::BlitImageHelper(const Device& device_, Scheduler& scheduler_, two_textures_set_layout(device.GetLogical().CreateDescriptorSetLayout( TWO_TEXTURES_DESCRIPTOR_SET_LAYOUT_CREATE_INFO)), one_texture_descriptor_allocator{ - descriptor_pool.Allocator(device_, scheduler_, *one_texture_set_layout, TEXTURE_DESCRIPTOR_BANK_INFO<1>)}, + descriptor_pool.Allocator(*one_texture_set_layout, TEXTURE_DESCRIPTOR_BANK_INFO<1>)}, two_textures_descriptor_allocator{ - descriptor_pool.Allocator(device_, scheduler_, *two_textures_set_layout, TEXTURE_DESCRIPTOR_BANK_INFO<2>)}, + descriptor_pool.Allocator(*two_textures_set_layout, TEXTURE_DESCRIPTOR_BANK_INFO<2>)}, one_texture_pipeline_layout(device.GetLogical().CreatePipelineLayout(PipelineLayoutCreateInfo( one_texture_set_layout.address(), PUSH_CONSTANT_RANGE))), diff --git a/src/video_core/renderer_vulkan/pipeline_statistics.cpp b/src/video_core/renderer_vulkan/pipeline_statistics.cpp index 04f42c71a6..ad288436a8 100644 --- a/src/video_core/renderer_vulkan/pipeline_statistics.cpp +++ b/src/video_core/renderer_vulkan/pipeline_statistics.cpp @@ -31,13 +31,14 @@ static u64 GetUint64(const VkPipelineExecutableStatisticKHR& statistic) { } } -PipelineStatistics::PipelineStatistics(const Device& device_) {} +PipelineStatistics::PipelineStatistics(const Device& device_) : device{device_} {} -void PipelineStatistics::Collect(const Device& device, VkPipeline pipeline) { - const std::vector properties{device.GetLogical().GetPipelineExecutablePropertiesKHR(pipeline)}; +void PipelineStatistics::Collect(VkPipeline pipeline) { + const auto& dev{device.GetLogical()}; + const std::vector properties{dev.GetPipelineExecutablePropertiesKHR(pipeline)}; const u32 num_executables{static_cast(properties.size())}; for (u32 executable = 0; executable < num_executables; ++executable) { - const auto statistics{device.GetLogical().GetPipelineExecutableStatisticsKHR(pipeline, executable)}; + const auto statistics{dev.GetPipelineExecutableStatisticsKHR(pipeline, executable)}; if (statistics.empty()) { continue; } diff --git a/src/video_core/renderer_vulkan/pipeline_statistics.h b/src/video_core/renderer_vulkan/pipeline_statistics.h index 83e70b704f..197bb09363 100644 --- a/src/video_core/renderer_vulkan/pipeline_statistics.h +++ b/src/video_core/renderer_vulkan/pipeline_statistics.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -19,7 +16,9 @@ class Device; class PipelineStatistics { public: explicit PipelineStatistics(const Device& device_); - void Collect(const Device& device, VkPipeline pipeline); + + void Collect(VkPipeline pipeline); + void Report() const; private: @@ -31,6 +30,8 @@ private: u64 branches_count{}; u64 basic_block_count{}; }; + + const Device& device; mutable std::mutex mutex; std::vector collected_stats; }; diff --git a/src/video_core/renderer_vulkan/present/anti_alias_pass.h b/src/video_core/renderer_vulkan/present/anti_alias_pass.h index 8061d01208..4990e87502 100644 --- a/src/video_core/renderer_vulkan/present/anti_alias_pass.h +++ b/src/video_core/renderer_vulkan/present/anti_alias_pass.h @@ -11,12 +11,12 @@ namespace Vulkan { class Scheduler; -class Device; class AntiAliasPass { public: virtual ~AntiAliasPass() = default; - virtual void Draw(const Device& device, Scheduler& scheduler, size_t image_index, VkImage* inout_image, VkImageView* inout_image_view) = 0; + virtual void Draw(Scheduler& scheduler, size_t image_index, VkImage* inout_image, + VkImageView* inout_image_view) = 0; }; } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/present/fsr.cpp b/src/video_core/renderer_vulkan/present/fsr.cpp index 894fb144f0..ba6252ed95 100644 --- a/src/video_core/renderer_vulkan/present/fsr.cpp +++ b/src/video_core/renderer_vulkan/present/fsr.cpp @@ -25,74 +25,74 @@ using namespace FSR; using PushConstants = std::array; -FSR::FSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count, VkExtent2D extent) - : m_memory_allocator{memory_allocator} - , m_image_count{image_count} - , m_extent{extent} -{ - CreateImages(device); - CreateRenderPasses(device); - CreateSampler(device); - CreateShaders(device); - CreateDescriptorPool(device); - CreateDescriptorSetLayout(device); - CreateDescriptorSets(device); - CreatePipelineLayouts(device); - CreatePipelines(device); +FSR::FSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count, + VkExtent2D extent) + : m_device{device}, m_memory_allocator{memory_allocator}, + m_image_count{image_count}, m_extent{extent} { + + CreateImages(); + CreateRenderPasses(); + CreateSampler(); + CreateShaders(); + CreateDescriptorPool(); + CreateDescriptorSetLayout(); + CreateDescriptorSets(); + CreatePipelineLayouts(); + CreatePipelines(); } -void FSR::CreateImages(const Device& device) { +void FSR::CreateImages() { m_dynamic_images.resize(m_image_count); for (auto& images : m_dynamic_images) { images.images[Easu] = CreateWrappedImage(m_memory_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT); images.images[Rcas] = CreateWrappedImage(m_memory_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT); - images.image_views[Easu] = CreateWrappedImageView(device, images.images[Easu], VK_FORMAT_R16G16B16A16_SFLOAT); - images.image_views[Rcas] = CreateWrappedImageView(device, images.images[Rcas], VK_FORMAT_R16G16B16A16_SFLOAT); + images.image_views[Easu] = CreateWrappedImageView(m_device, images.images[Easu], VK_FORMAT_R16G16B16A16_SFLOAT); + images.image_views[Rcas] = CreateWrappedImageView(m_device, images.images[Rcas], VK_FORMAT_R16G16B16A16_SFLOAT); } } -void FSR::CreateRenderPasses(const Device& device) { - m_renderpass = CreateWrappedRenderPass(device, VK_FORMAT_R16G16B16A16_SFLOAT); +void FSR::CreateRenderPasses() { + m_renderpass = CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16B16A16_SFLOAT); for (auto& images : m_dynamic_images) { - images.framebuffers[Easu] = CreateWrappedFramebuffer(device, m_renderpass, images.image_views[Easu], m_extent); - images.framebuffers[Rcas] = CreateWrappedFramebuffer(device, m_renderpass, images.image_views[Rcas], m_extent); + images.framebuffers[Easu] = CreateWrappedFramebuffer(m_device, m_renderpass, images.image_views[Easu], m_extent); + images.framebuffers[Rcas] = CreateWrappedFramebuffer(m_device, m_renderpass, images.image_views[Rcas], m_extent); } } -void FSR::CreateSampler(const Device& device) { - m_sampler = CreateBilinearSampler(device); +void FSR::CreateSampler() { + m_sampler = CreateBilinearSampler(m_device); } -void FSR::CreateShaders(const Device& device) { - m_vert_shader = BuildShader(device, VULKAN_FIDELITYFX_FSR_VERT_SPV); +void FSR::CreateShaders() { + m_vert_shader = BuildShader(m_device, VULKAN_FIDELITYFX_FSR_VERT_SPV); - if (device.IsFloat16Supported()) { - m_easu_shader = BuildShader(device, VULKAN_FIDELITYFX_FSR_EASU_FP16_FRAG_SPV); - m_rcas_shader = BuildShader(device, VULKAN_FIDELITYFX_FSR_RCAS_FP16_FRAG_SPV); + if (m_device.IsFloat16Supported()) { + m_easu_shader = BuildShader(m_device, VULKAN_FIDELITYFX_FSR_EASU_FP16_FRAG_SPV); + m_rcas_shader = BuildShader(m_device, VULKAN_FIDELITYFX_FSR_RCAS_FP16_FRAG_SPV); } else { - m_easu_shader = BuildShader(device, VULKAN_FIDELITYFX_FSR_EASU_FP32_FRAG_SPV); - m_rcas_shader = BuildShader(device, VULKAN_FIDELITYFX_FSR_RCAS_FP32_FRAG_SPV); + m_easu_shader = BuildShader(m_device, VULKAN_FIDELITYFX_FSR_EASU_FP32_FRAG_SPV); + m_rcas_shader = BuildShader(m_device, VULKAN_FIDELITYFX_FSR_RCAS_FP32_FRAG_SPV); } } -void FSR::CreateDescriptorPool(const Device& device) { +void FSR::CreateDescriptorPool() { // EASU: 1 descriptor // RCAS: 1 descriptor // 2 descriptors, 2 descriptor sets per invocation - m_descriptor_pool = CreateWrappedDescriptorPool(device, 2 * m_image_count, 2 * m_image_count); + m_descriptor_pool = CreateWrappedDescriptorPool(m_device, 2 * m_image_count, 2 * m_image_count); } -void FSR::CreateDescriptorSetLayout(const Device& device) { - m_descriptor_set_layout = CreateWrappedDescriptorSetLayout(device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}); +void FSR::CreateDescriptorSetLayout() { + m_descriptor_set_layout = CreateWrappedDescriptorSetLayout(m_device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}); } -void FSR::CreateDescriptorSets(const Device& device) { +void FSR::CreateDescriptorSets() { std::vector layouts(MaxFsrStage, *m_descriptor_set_layout); for (auto& images : m_dynamic_images) images.descriptor_sets = CreateWrappedDescriptorSets(m_descriptor_pool, layouts); } -void FSR::CreatePipelineLayouts(const Device& device) { +void FSR::CreatePipelineLayouts() { const VkPushConstantRange range{ .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, .offset = 0, @@ -108,17 +108,17 @@ void FSR::CreatePipelineLayouts(const Device& device) { .pPushConstantRanges = &range, }; - m_pipeline_layout = device.GetLogical().CreatePipelineLayout(ci); + m_pipeline_layout = m_device.GetLogical().CreatePipelineLayout(ci); } -void FSR::CreatePipelines(const Device& device) { - m_easu_pipeline = CreateWrappedPipeline(device, m_renderpass, m_pipeline_layout, +void FSR::CreatePipelines() { + m_easu_pipeline = CreateWrappedPipeline(m_device, m_renderpass, m_pipeline_layout, std::tie(m_vert_shader, m_easu_shader)); - m_rcas_pipeline = CreateWrappedPipeline(device, m_renderpass, m_pipeline_layout, + m_rcas_pipeline = CreateWrappedPipeline(m_device, m_renderpass, m_pipeline_layout, std::tie(m_vert_shader, m_rcas_shader)); } -void FSR::UpdateDescriptorSets(const Device& device, VkImageView image_view, size_t image_index) { +void FSR::UpdateDescriptorSets(VkImageView image_view, size_t image_index) { Images& images = m_dynamic_images[image_index]; std::vector image_infos; image_infos.reserve(2); @@ -126,10 +126,10 @@ void FSR::UpdateDescriptorSets(const Device& device, VkImageView image_view, siz CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, images.descriptor_sets[Easu], 0), CreateWriteDescriptorSet(image_infos, *m_sampler, *images.image_views[Easu], images.descriptor_sets[Rcas], 0) }; - device.GetLogical().UpdateDescriptorSets(updates, {}); + m_device.GetLogical().UpdateDescriptorSets(updates, {}); } -void FSR::UploadImages(const Device& device, Scheduler& scheduler) { +void FSR::UploadImages(Scheduler& scheduler) { if (!m_images_ready) { m_images_ready = true; scheduler.Record([&](vk::CommandBuffer cmdbuf) { @@ -142,7 +142,7 @@ void FSR::UploadImages(const Device& device, Scheduler& scheduler) { } } -VkImageView FSR::Draw(const Device& device, Scheduler& scheduler, size_t image_index, VkImage source_image, +VkImageView FSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, VkImageView source_image_view, VkExtent2D input_image_extent, const Common::Rectangle& crop_rect) { Images& images = m_dynamic_images[image_index]; @@ -179,8 +179,8 @@ VkImageView FSR::Draw(const Device& device, Scheduler& scheduler, size_t image_i static_cast(Settings::values.fsr_sharpening_slider.GetValue()) / 100.0f; FsrRcasCon(rcas_con.data(), sharpening); - UploadImages(device, scheduler); - UpdateDescriptorSets(device, source_image_view, image_index); + UploadImages(scheduler); + UpdateDescriptorSets(source_image_view, image_index); scheduler.RequestOutsideRenderPassOperationContext(); scheduler.Record([=](vk::CommandBuffer cmdbuf) { diff --git a/src/video_core/renderer_vulkan/present/fsr.h b/src/video_core/renderer_vulkan/present/fsr.h index 7762480757..8602e81465 100644 --- a/src/video_core/renderer_vulkan/present/fsr.h +++ b/src/video_core/renderer_vulkan/present/fsr.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -17,25 +14,27 @@ class Scheduler; class FSR { public: - explicit FSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count, VkExtent2D extent); - VkImageView Draw(const Device& device, Scheduler& scheduler, size_t image_index, VkImage source_image, + explicit FSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count, + VkExtent2D extent); + VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, VkImageView source_image_view, VkExtent2D input_image_extent, const Common::Rectangle& crop_rect); private: - void CreateImages(const Device& device); - void CreateRenderPasses(const Device& device); - void CreateSampler(const Device& device); - void CreateShaders(const Device& device); - void CreateDescriptorPool(const Device& device); - void CreateDescriptorSetLayout(const Device& device); - void CreateDescriptorSets(const Device& device); - void CreatePipelineLayouts(const Device& device); - void CreatePipelines(const Device& device); + void CreateImages(); + void CreateRenderPasses(); + void CreateSampler(); + void CreateShaders(); + void CreateDescriptorPool(); + void CreateDescriptorSetLayout(); + void CreateDescriptorSets(); + void CreatePipelineLayouts(); + void CreatePipelines(); - void UploadImages(const Device& device, Scheduler& scheduler); - void UpdateDescriptorSets(const Device& device, VkImageView image_view, size_t image_index); + void UploadImages(Scheduler& scheduler); + void UpdateDescriptorSets(VkImageView image_view, size_t image_index); + const Device& m_device; MemoryAllocator& m_memory_allocator; const size_t m_image_count; const VkExtent2D m_extent; diff --git a/src/video_core/renderer_vulkan/present/fxaa.cpp b/src/video_core/renderer_vulkan/present/fxaa.cpp index 62f79d490c..bdafd1f4d0 100644 --- a/src/video_core/renderer_vulkan/present/fxaa.cpp +++ b/src/video_core/renderer_vulkan/present/fxaa.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -17,60 +14,61 @@ namespace Vulkan { FXAA::FXAA(const Device& device, MemoryAllocator& allocator, size_t image_count, VkExtent2D extent) - : m_extent(extent) - , m_image_count(u32(image_count)) -{ - CreateImages(device, allocator); - CreateRenderPasses(device); - CreateSampler(device); - CreateShaders(device); - CreateDescriptorPool(device); - CreateDescriptorSetLayouts(device); - CreateDescriptorSets(device); - CreatePipelineLayouts(device); - CreatePipelines(device); + : m_device(device), m_allocator(allocator), m_extent(extent), + m_image_count(static_cast(image_count)) { + CreateImages(); + CreateRenderPasses(); + CreateSampler(); + CreateShaders(); + CreateDescriptorPool(); + CreateDescriptorSetLayouts(); + CreateDescriptorSets(); + CreatePipelineLayouts(); + CreatePipelines(); } FXAA::~FXAA() = default; -void FXAA::CreateImages(const Device& device, MemoryAllocator& allocator) { +void FXAA::CreateImages() { for (u32 i = 0; i < m_image_count; i++) { Image& image = m_dynamic_images.emplace_back(); - image.image = CreateWrappedImage(allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT); - image.image_view = CreateWrappedImageView(device, image.image, VK_FORMAT_R16G16B16A16_SFLOAT); + + image.image = CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT); + image.image_view = + CreateWrappedImageView(m_device, image.image, VK_FORMAT_R16G16B16A16_SFLOAT); } } -void FXAA::CreateRenderPasses(const Device& device) { - m_renderpass = CreateWrappedRenderPass(device, VK_FORMAT_R16G16B16A16_SFLOAT); +void FXAA::CreateRenderPasses() { + m_renderpass = CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16B16A16_SFLOAT); for (auto& image : m_dynamic_images) { image.framebuffer = - CreateWrappedFramebuffer(device, m_renderpass, image.image_view, m_extent); + CreateWrappedFramebuffer(m_device, m_renderpass, image.image_view, m_extent); } } -void FXAA::CreateSampler(const Device& device) { - m_sampler = CreateWrappedSampler(device); +void FXAA::CreateSampler() { + m_sampler = CreateWrappedSampler(m_device); } -void FXAA::CreateShaders(const Device& device) { - m_vertex_shader = CreateWrappedShaderModule(device, FXAA_VERT_SPV); - m_fragment_shader = CreateWrappedShaderModule(device, FXAA_FRAG_SPV); +void FXAA::CreateShaders() { + m_vertex_shader = CreateWrappedShaderModule(m_device, FXAA_VERT_SPV); + m_fragment_shader = CreateWrappedShaderModule(m_device, FXAA_FRAG_SPV); } -void FXAA::CreateDescriptorPool(const Device& device) { +void FXAA::CreateDescriptorPool() { // 2 descriptors, 1 descriptor set per image - m_descriptor_pool = CreateWrappedDescriptorPool(device, 2 * m_image_count, m_image_count); + m_descriptor_pool = CreateWrappedDescriptorPool(m_device, 2 * m_image_count, m_image_count); } -void FXAA::CreateDescriptorSetLayouts(const Device& device) { +void FXAA::CreateDescriptorSetLayouts() { m_descriptor_set_layout = - CreateWrappedDescriptorSetLayout(device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + CreateWrappedDescriptorSetLayout(m_device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}); } -void FXAA::CreateDescriptorSets(const Device& device) { +void FXAA::CreateDescriptorSets() { VkDescriptorSetLayout layout = *m_descriptor_set_layout; for (auto& images : m_dynamic_images) { @@ -78,28 +76,30 @@ void FXAA::CreateDescriptorSets(const Device& device) { } } -void FXAA::CreatePipelineLayouts(const Device& device) { - m_pipeline_layout = CreateWrappedPipelineLayout(device, m_descriptor_set_layout); +void FXAA::CreatePipelineLayouts() { + m_pipeline_layout = CreateWrappedPipelineLayout(m_device, m_descriptor_set_layout); } -void FXAA::CreatePipelines(const Device& device) { - m_pipeline = CreateWrappedPipeline(device, m_renderpass, m_pipeline_layout, +void FXAA::CreatePipelines() { + m_pipeline = CreateWrappedPipeline(m_device, m_renderpass, m_pipeline_layout, std::tie(m_vertex_shader, m_fragment_shader)); } -void FXAA::UpdateDescriptorSets(const Device& device, VkImageView image_view, size_t image_index) { +void FXAA::UpdateDescriptorSets(VkImageView image_view, size_t image_index) { Image& image = m_dynamic_images[image_index]; std::vector image_infos; std::vector updates; image_infos.reserve(2); - updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, image.descriptor_sets[0], 0)); - updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, image.descriptor_sets[0], 1)); + updates.push_back( + CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, image.descriptor_sets[0], 0)); + updates.push_back( + CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, image.descriptor_sets[0], 1)); - device.GetLogical().UpdateDescriptorSets(updates, {}); + m_device.GetLogical().UpdateDescriptorSets(updates, {}); } -void FXAA::UploadImages(const Device& device, Scheduler& scheduler) { +void FXAA::UploadImages(Scheduler& scheduler) { if (m_images_ready) { return; } @@ -114,7 +114,8 @@ void FXAA::UploadImages(const Device& device, Scheduler& scheduler) { m_images_ready = true; } -void FXAA::Draw(const Device& device, Scheduler& scheduler, size_t image_index, VkImage* inout_image, VkImageView* inout_image_view) { +void FXAA::Draw(Scheduler& scheduler, size_t image_index, VkImage* inout_image, + VkImageView* inout_image_view) { const Image& image{m_dynamic_images[image_index]}; const VkImage input_image{*inout_image}; const VkImage output_image{*image.image}; @@ -125,8 +126,8 @@ void FXAA::Draw(const Device& device, Scheduler& scheduler, size_t image_index, const VkPipelineLayout layout{*m_pipeline_layout}; const VkExtent2D extent{m_extent}; - UploadImages(device, scheduler); - UpdateDescriptorSets(device, *inout_image_view, image_index); + UploadImages(scheduler); + UpdateDescriptorSets(*inout_image_view, image_index); scheduler.RequestOutsideRenderPassOperationContext(); scheduler.Record([=](vk::CommandBuffer cmdbuf) { diff --git a/src/video_core/renderer_vulkan/present/fxaa.h b/src/video_core/renderer_vulkan/present/fxaa.h index 7eaf31f81c..97a2e5c1cb 100644 --- a/src/video_core/renderer_vulkan/present/fxaa.h +++ b/src/video_core/renderer_vulkan/present/fxaa.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -18,23 +15,38 @@ class StagingBufferPool; class FXAA final : public AntiAliasPass { public: - explicit FXAA(const Device& device, MemoryAllocator& allocator, size_t image_count, VkExtent2D extent); + explicit FXAA(const Device& device, MemoryAllocator& allocator, size_t image_count, + VkExtent2D extent); ~FXAA() override; - void Draw(const Device& device, Scheduler& scheduler, size_t image_index, VkImage* inout_image, VkImageView* inout_image_view) override; + void Draw(Scheduler& scheduler, size_t image_index, VkImage* inout_image, + VkImageView* inout_image_view) override; private: - void CreateImages(const Device& device, MemoryAllocator& allocator); - void CreateRenderPasses(const Device& device); - void CreateSampler(const Device& device); - void CreateShaders(const Device& device); - void CreateDescriptorPool(const Device& device); - void CreateDescriptorSetLayouts(const Device& device); - void CreateDescriptorSets(const Device& device); - void CreatePipelineLayouts(const Device& device); - void CreatePipelines(const Device& device); - void UpdateDescriptorSets(const Device& device, VkImageView image_view, size_t image_index); - void UploadImages(const Device& device, Scheduler& scheduler); + void CreateImages(); + void CreateRenderPasses(); + void CreateSampler(); + void CreateShaders(); + void CreateDescriptorPool(); + void CreateDescriptorSetLayouts(); + void CreateDescriptorSets(); + void CreatePipelineLayouts(); + void CreatePipelines(); + void UpdateDescriptorSets(VkImageView image_view, size_t image_index); + void UploadImages(Scheduler& scheduler); + + const Device& m_device; + MemoryAllocator& m_allocator; + const VkExtent2D m_extent; + const u32 m_image_count; + + vk::ShaderModule m_vertex_shader{}; + vk::ShaderModule m_fragment_shader{}; + vk::DescriptorPool m_descriptor_pool{}; + vk::DescriptorSetLayout m_descriptor_set_layout{}; + vk::PipelineLayout m_pipeline_layout{}; + vk::Pipeline m_pipeline{}; + vk::RenderPass m_renderpass{}; struct Image { vk::DescriptorSets descriptor_sets{}; @@ -43,17 +55,9 @@ private: vk::ImageView image_view{}; }; std::vector m_dynamic_images{}; - const VkExtent2D m_extent; - const u32 m_image_count; - vk::ShaderModule m_vertex_shader{}; - vk::ShaderModule m_fragment_shader{}; - vk::DescriptorPool m_descriptor_pool{}; - vk::DescriptorSetLayout m_descriptor_set_layout{}; - vk::PipelineLayout m_pipeline_layout{}; - vk::Pipeline m_pipeline{}; - vk::RenderPass m_renderpass{}; - vk::Sampler m_sampler{}; bool m_images_ready{}; + + vk::Sampler m_sampler{}; }; } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/present/layer.cpp b/src/video_core/renderer_vulkan/present/layer.cpp index 14935f92bb..e20473d2af 100644 --- a/src/video_core/renderer_vulkan/present/layer.cpp +++ b/src/video_core/renderer_vulkan/present/layer.cpp @@ -56,15 +56,13 @@ VkFormat GetFormat(const Tegra::FramebufferConfig& framebuffer) { } // Anonymous namespace -Layer::Layer(const Device& device, MemoryAllocator& memory_allocator_, Scheduler& scheduler_, Tegra::MaxwellDeviceMemoryManager& device_memory_, size_t image_count_, VkExtent2D output_size, VkDescriptorSetLayout layout, const PresentFilters& filters_) - : memory_allocator(memory_allocator_) - , scheduler(scheduler_) - , device_memory(device_memory_) - , filters(filters_) - , image_count(image_count_) -{ - CreateDescriptorPool(device); - CreateDescriptorSets(device, layout); +Layer::Layer(const Device& device_, MemoryAllocator& memory_allocator_, Scheduler& scheduler_, + Tegra::MaxwellDeviceMemoryManager& device_memory_, size_t image_count_, + VkExtent2D output_size, VkDescriptorSetLayout layout, const PresentFilters& filters_) + : device(device_), memory_allocator(memory_allocator_), scheduler(scheduler_), + device_memory(device_memory_), filters(filters_), image_count(image_count_) { + CreateDescriptorPool(); + CreateDescriptorSets(layout); if (filters.get_scaling_filter() == Settings::ScalingFilter::Fsr) { sr_filter.emplace(device, memory_allocator, image_count, output_size); } else if (filters.get_scaling_filter() == Settings::ScalingFilter::Sgsr) { @@ -78,7 +76,7 @@ Layer::~Layer() { ReleaseRawImages(); } -void Layer::ConfigureDraw(const Device& device, PresentPushConstants* out_push_constants, +void Layer::ConfigureDraw(PresentPushConstants* out_push_constants, VkDescriptorSet* out_descriptor_set, RasterizerVulkan& rasterizer, VkSampler sampler, size_t image_index, const Tegra::FramebufferConfig& framebuffer, @@ -91,8 +89,8 @@ void Layer::ConfigureDraw(const Device& device, PresentPushConstants* out_push_c const u32 scaled_height = texture_info ? texture_info->scaled_height : texture_height; const bool use_accelerated = texture_info.has_value(); - RefreshResources(device, framebuffer); - SetAntiAliasPass(device); + RefreshResources(framebuffer); + SetAntiAliasPass(); // Finish any pending renderpass scheduler.RequestOutsideRenderPassOperationContext(); @@ -110,9 +108,9 @@ void Layer::ConfigureDraw(const Device& device, PresentPushConstants* out_push_c texture_info ? texture_info->image_view : *raw_image_views[image_index]; if (auto* fxaa = std::get_if(&anti_alias)) { - fxaa->Draw(device, scheduler, image_index, &source_image, &source_image_view); + fxaa->Draw(scheduler, image_index, &source_image, &source_image_view); } else if (auto* smaa = std::get_if(&anti_alias)) { - smaa->Draw(device, scheduler, image_index, &source_image, &source_image_view); + smaa->Draw(scheduler, image_index, &source_image, &source_image_view); } auto crop_rect = Tegra::NormalizeCrop(framebuffer, texture_width, texture_height); @@ -122,30 +120,30 @@ void Layer::ConfigureDraw(const Device& device, PresentPushConstants* out_push_c }; if (auto* fsr = std::get_if(&sr_filter)) { - source_image_view = fsr->Draw(device, scheduler, image_index, source_image, source_image_view, render_extent, crop_rect); + source_image_view = fsr->Draw(scheduler, image_index, source_image, source_image_view, render_extent, crop_rect); crop_rect = {0, 0, 1, 1}; } else if (auto* sgsr = std::get_if(&sr_filter)) { - source_image_view = sgsr->Draw(device, scheduler, image_index, source_image, source_image_view, render_extent, crop_rect); + source_image_view = sgsr->Draw(scheduler, image_index, source_image, source_image_view, render_extent, crop_rect); crop_rect = {0, 0, 1, 1}; } - SetMatrixData(device, *out_push_constants, layout); - SetVertexData(device, *out_push_constants, layout, crop_rect); + SetMatrixData(*out_push_constants, layout); + SetVertexData(*out_push_constants, layout, crop_rect); - UpdateDescriptorSet(device, source_image_view, sampler, image_index); + UpdateDescriptorSet(source_image_view, sampler, image_index); *out_descriptor_set = descriptor_sets[image_index]; } -void Layer::CreateDescriptorPool(const Device& device) { +void Layer::CreateDescriptorPool() { descriptor_pool = CreateWrappedDescriptorPool(device, image_count, image_count); } -void Layer::CreateDescriptorSets(const Device& device, VkDescriptorSetLayout layout) { +void Layer::CreateDescriptorSets(VkDescriptorSetLayout layout) { const std::vector layouts(image_count, layout); descriptor_sets = CreateWrappedDescriptorSets(descriptor_pool, layouts); } -void Layer::CreateStagingBuffer(const Device& device, const Tegra::FramebufferConfig& framebuffer) { +void Layer::CreateStagingBuffer(const Tegra::FramebufferConfig& framebuffer) { const VkBufferCreateInfo ci{ .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .pNext = nullptr, @@ -161,7 +159,7 @@ void Layer::CreateStagingBuffer(const Device& device, const Tegra::FramebufferCo buffer = memory_allocator.CreateBuffer(ci, MemoryUsage::Upload); } -void Layer::CreateRawImages(const Device& device, const Tegra::FramebufferConfig& framebuffer) { +void Layer::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) { const auto format = GetFormat(framebuffer); resource_ticks.resize(image_count); raw_images.resize(image_count); @@ -174,7 +172,7 @@ void Layer::CreateRawImages(const Device& device, const Tegra::FramebufferConfig } } -void Layer::RefreshResources(const Device& device, const Tegra::FramebufferConfig& framebuffer) { +void Layer::RefreshResources(const Tegra::FramebufferConfig& framebuffer) { if (framebuffer.width == raw_width && framebuffer.height == raw_height && framebuffer.pixel_format == pixel_format && !raw_images.empty()) { return; @@ -186,11 +184,11 @@ void Layer::RefreshResources(const Device& device, const Tegra::FramebufferConfi anti_alias.emplace(); ReleaseRawImages(); - CreateStagingBuffer(device, framebuffer); - CreateRawImages(device, framebuffer); + CreateStagingBuffer(framebuffer); + CreateRawImages(framebuffer); } -void Layer::SetAntiAliasPass(const Device& device) { +void Layer::SetAntiAliasPass() { if (!std::holds_alternative(anti_alias) && anti_alias_setting == filters.get_anti_aliasing()) return; @@ -231,17 +229,20 @@ u64 Layer::GetRawImageOffset(const Tegra::FramebufferConfig& framebuffer, return GetSizeInBytes(framebuffer) * image_index; } -void Layer::SetMatrixData(const Device& device, PresentPushConstants& data, const Layout::FramebufferLayout& layout) const { - data.modelview_matrix = MakeOrthographicMatrix(f32(layout.width), static_cast(layout.height)); +void Layer::SetMatrixData(PresentPushConstants& data, + const Layout::FramebufferLayout& layout) const { + data.modelview_matrix = + MakeOrthographicMatrix(static_cast(layout.width), static_cast(layout.height)); } -void Layer::SetVertexData(const Device& device, PresentPushConstants& data, const Layout::FramebufferLayout& layout, const Common::Rectangle& crop) const { +void Layer::SetVertexData(PresentPushConstants& data, const Layout::FramebufferLayout& layout, + const Common::Rectangle& crop) const { // Map the coordinates to the screen. const auto& screen = layout.screen; - const auto x = f32(screen.left); - const auto y = f32(screen.top); - const auto w = f32(screen.GetWidth()); - const auto h = f32(screen.GetHeight()); + const auto x = static_cast(screen.left); + const auto y = static_cast(screen.top); + const auto w = static_cast(screen.GetWidth()); + const auto h = static_cast(screen.GetHeight()); data.vertices[0] = ScreenRectVertex(x, y, crop.left, crop.top); data.vertices[1] = ScreenRectVertex(x + w, y, crop.right, crop.top); @@ -249,7 +250,7 @@ void Layer::SetVertexData(const Device& device, PresentPushConstants& data, cons data.vertices[3] = ScreenRectVertex(x + w, y + h, crop.right, crop.bottom); } -void Layer::UpdateDescriptorSet(const Device& device, VkImageView image_view, VkSampler sampler, size_t image_index) { +void Layer::UpdateDescriptorSet(VkImageView image_view, VkSampler sampler, size_t image_index) { const VkDescriptorImageInfo image_info{ .sampler = sampler, .imageView = image_view, diff --git a/src/video_core/renderer_vulkan/present/layer.h b/src/video_core/renderer_vulkan/present/layer.h index 4d75e86ba6..47a6a69218 100644 --- a/src/video_core/renderer_vulkan/present/layer.h +++ b/src/video_core/renderer_vulkan/present/layer.h @@ -52,31 +52,33 @@ public: const PresentFilters& filters); ~Layer(); - void ConfigureDraw(const Device& device, PresentPushConstants* out_push_constants, + void ConfigureDraw(PresentPushConstants* out_push_constants, VkDescriptorSet* out_descriptor_set, RasterizerVulkan& rasterizer, VkSampler sampler, size_t image_index, const Tegra::FramebufferConfig& framebuffer, const Layout::FramebufferLayout& layout); private: - void CreateDescriptorPool(const Device& device); - void CreateDescriptorSets(const Device& device, VkDescriptorSetLayout layout); - void CreateStagingBuffer(const Device& device, const Tegra::FramebufferConfig& framebuffer); - void CreateRawImages(const Device& device, const Tegra::FramebufferConfig& framebuffer); + void CreateDescriptorPool(); + void CreateDescriptorSets(VkDescriptorSetLayout layout); + void CreateStagingBuffer(const Tegra::FramebufferConfig& framebuffer); + void CreateRawImages(const Tegra::FramebufferConfig& framebuffer); - void RefreshResources(const Device& device, const Tegra::FramebufferConfig& framebuffer); - void SetAntiAliasPass(const Device& device); + void RefreshResources(const Tegra::FramebufferConfig& framebuffer); + void SetAntiAliasPass(); void ReleaseRawImages(); u64 CalculateBufferSize(const Tegra::FramebufferConfig& framebuffer) const; u64 GetRawImageOffset(const Tegra::FramebufferConfig& framebuffer, size_t image_index) const; - void SetMatrixData(const Device& device, PresentPushConstants& data, const Layout::FramebufferLayout& layout) const; - void SetVertexData(const Device& device, PresentPushConstants& data, const Layout::FramebufferLayout& layout, const Common::Rectangle& crop) const; - void UpdateDescriptorSet(const Device& device, VkImageView image_view, VkSampler sampler, size_t image_index); + void SetMatrixData(PresentPushConstants& data, const Layout::FramebufferLayout& layout) const; + void SetVertexData(PresentPushConstants& data, const Layout::FramebufferLayout& layout, + const Common::Rectangle& crop) const; + void UpdateDescriptorSet(VkImageView image_view, VkSampler sampler, size_t image_index); void UpdateRawImage(const Tegra::FramebufferConfig& framebuffer, size_t image_index); private: + const Device& device; MemoryAllocator& memory_allocator; Scheduler& scheduler; Tegra::MaxwellDeviceMemoryManager& device_memory; diff --git a/src/video_core/renderer_vulkan/present/sgsr.cpp b/src/video_core/renderer_vulkan/present/sgsr.cpp index 5fc746458d..4175190690 100644 --- a/src/video_core/renderer_vulkan/present/sgsr.cpp +++ b/src/video_core/renderer_vulkan/present/sgsr.cpp @@ -20,7 +20,8 @@ namespace Vulkan { using PushConstants = std::array; SGSR::SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count, VkExtent2D extent, bool edge_dir) - : m_memory_allocator{memory_allocator} + : m_device{device} + , m_memory_allocator{memory_allocator} , m_image_count{image_count} , m_extent{extent} , m_edge_dir{edge_dir} @@ -29,21 +30,21 @@ SGSR::SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image m_dynamic_images.resize(m_image_count); for (auto& images : m_dynamic_images) { images.image = CreateWrappedImage(m_memory_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT); - images.image_view = CreateWrappedImageView(device, images.image, VK_FORMAT_R16G16B16A16_SFLOAT); + images.image_view = CreateWrappedImageView(m_device, images.image, VK_FORMAT_R16G16B16A16_SFLOAT); } - m_renderpass = CreateWrappedRenderPass(device, VK_FORMAT_R16G16B16A16_SFLOAT); + m_renderpass = CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16B16A16_SFLOAT); for (auto& images : m_dynamic_images) - images.framebuffer = CreateWrappedFramebuffer(device, m_renderpass, images.image_view, m_extent); + images.framebuffer = CreateWrappedFramebuffer(m_device, m_renderpass, images.image_view, m_extent); - m_sampler = CreateBilinearSampler(device); - m_vert_shader = BuildShader(device, SGSR1_SHADER_VERT_SPV); + m_sampler = CreateBilinearSampler(m_device); + m_vert_shader = BuildShader(m_device, SGSR1_SHADER_VERT_SPV); m_stage_shader = m_edge_dir - ? BuildShader(device, SGSR1_SHADER_MOBILE_EDGE_DIRECTION_FRAG_SPV) - : BuildShader(device, SGSR1_SHADER_MOBILE_FRAG_SPV); + ? BuildShader(m_device, SGSR1_SHADER_MOBILE_EDGE_DIRECTION_FRAG_SPV) + : BuildShader(m_device, SGSR1_SHADER_MOBILE_FRAG_SPV); // 2 descriptors, 2 descriptor sets per invocation - m_descriptor_pool = CreateWrappedDescriptorPool(device, m_image_count, m_image_count); - m_descriptor_set_layout = CreateWrappedDescriptorSetLayout(device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}); + m_descriptor_pool = CreateWrappedDescriptorPool(m_device, m_image_count, m_image_count); + m_descriptor_set_layout = CreateWrappedDescriptorSetLayout(m_device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}); VkDescriptorSetLayout layout = *m_descriptor_set_layout; for (auto& images : m_dynamic_images) @@ -63,20 +64,20 @@ SGSR::SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image .pushConstantRangeCount = 1, .pPushConstantRanges = &range, }; - m_pipeline_layout = device.GetLogical().CreatePipelineLayout(ci); - m_stage_pipeline = CreateWrappedPipeline(device, m_renderpass, m_pipeline_layout, std::tie(m_vert_shader, m_stage_shader)); + m_pipeline_layout = m_device.GetLogical().CreatePipelineLayout(ci); + m_stage_pipeline = CreateWrappedPipeline(m_device, m_renderpass, m_pipeline_layout, std::tie(m_vert_shader, m_stage_shader)); } -void SGSR::UpdateDescriptorSets(const Device& device, VkImageView image_view, size_t image_index) { +void SGSR::UpdateDescriptorSets(VkImageView image_view, size_t image_index) { Images& images = m_dynamic_images[image_index]; std::vector image_infos; std::vector updates; image_infos.reserve(1); updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, images.descriptor_sets[0], 0)); - device.GetLogical().UpdateDescriptorSets(updates, {}); + m_device.GetLogical().UpdateDescriptorSets(updates, {}); } -void SGSR::UploadImages(const Device& device, Scheduler& scheduler) { +void SGSR::UploadImages(Scheduler& scheduler) { if (!m_images_ready) { scheduler.Record([&](vk::CommandBuffer cmdbuf) { for (auto& image : m_dynamic_images) @@ -87,7 +88,7 @@ void SGSR::UploadImages(const Device& device, Scheduler& scheduler) { } } -VkImageView SGSR::Draw(const Device& device, Scheduler& scheduler, size_t image_index, VkImage source_image, VkImageView source_image_view, VkExtent2D input_image_extent, const Common::Rectangle& crop_rect) { +VkImageView SGSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, VkImageView source_image_view, VkExtent2D input_image_extent, const Common::Rectangle& crop_rect) { Images& images = m_dynamic_images[image_index]; auto const output_image = *images.image; auto const descriptor_set = images.descriptor_sets[0]; @@ -121,8 +122,8 @@ VkImageView SGSR::Draw(const Device& device, Scheduler& scheduler, size_t image_ viewport_con[5] = std::bit_cast(viewport_height / input_image_height); viewport_con[6] = std::bit_cast(sharpening); - UploadImages(device, scheduler); - UpdateDescriptorSets(device, source_image_view, image_index); + UploadImages(scheduler); + UpdateDescriptorSets(source_image_view, image_index); scheduler.RequestOutsideRenderPassOperationContext(); scheduler.Record([=](vk::CommandBuffer cmdbuf) { diff --git a/src/video_core/renderer_vulkan/present/sgsr.h b/src/video_core/renderer_vulkan/present/sgsr.h index 42ba00898f..67b25be75d 100644 --- a/src/video_core/renderer_vulkan/present/sgsr.h +++ b/src/video_core/renderer_vulkan/present/sgsr.h @@ -16,12 +16,13 @@ class SGSR { public: static constexpr size_t SGSR_STAGE_COUNT = 1; explicit SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count, VkExtent2D extent, bool edge_dir); - VkImageView Draw(const Device& device, Scheduler& scheduler, size_t image_index, VkImage source_image, VkImageView source_image_view, VkExtent2D input_image_extent, const Common::Rectangle& crop_rect); + VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, VkImageView source_image_view, VkExtent2D input_image_extent, const Common::Rectangle& crop_rect); private: - void Initialize(const Device& device); - void UploadImages(const Device& device, Scheduler& scheduler); - void UpdateDescriptorSets(const Device& device, VkImageView image_view, size_t image_index); + void Initialize(); + void UploadImages(Scheduler& scheduler); + void UpdateDescriptorSets(VkImageView image_view, size_t image_index); + const Device& m_device; MemoryAllocator& m_memory_allocator; const size_t m_image_count; const VkExtent2D m_extent; diff --git a/src/video_core/renderer_vulkan/present/smaa.cpp b/src/video_core/renderer_vulkan/present/smaa.cpp index 28b0427fa0..686112f2f0 100644 --- a/src/video_core/renderer_vulkan/present/smaa.cpp +++ b/src/video_core/renderer_vulkan/present/smaa.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project @@ -27,24 +27,22 @@ namespace Vulkan { SMAA::SMAA(const Device& device, MemoryAllocator& allocator, size_t image_count, VkExtent2D extent) - : m_allocator(allocator) - , m_extent(extent) - , m_image_count(u32(image_count)) -{ - CreateImages(device); - CreateRenderPasses(device); - CreateSampler(device); - CreateShaders(device); - CreateDescriptorPool(device); - CreateDescriptorSetLayouts(device); - CreateDescriptorSets(device); - CreatePipelineLayouts(device); - CreatePipelines(device); + : m_device(device), m_allocator(allocator), m_extent(extent), + m_image_count(static_cast(image_count)) { + CreateImages(); + CreateRenderPasses(); + CreateSampler(); + CreateShaders(); + CreateDescriptorPool(); + CreateDescriptorSetLayouts(); + CreateDescriptorSets(); + CreatePipelineLayouts(); + CreatePipelines(); } SMAA::~SMAA() = default; -void SMAA::CreateImages(const Device& device) { +void SMAA::CreateImages() { static constexpr VkExtent2D area_extent{AREATEX_WIDTH, AREATEX_HEIGHT}; static constexpr VkExtent2D search_extent{SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT}; @@ -52,9 +50,9 @@ void SMAA::CreateImages(const Device& device) { m_static_images[Search] = CreateWrappedImage(m_allocator, search_extent, VK_FORMAT_R8_UNORM); m_static_image_views[Area] = - CreateWrappedImageView(device, m_static_images[Area], VK_FORMAT_R8G8_UNORM); + CreateWrappedImageView(m_device, m_static_images[Area], VK_FORMAT_R8G8_UNORM); m_static_image_views[Search] = - CreateWrappedImageView(device, m_static_images[Search], VK_FORMAT_R8_UNORM); + CreateWrappedImageView(m_device, m_static_images[Search], VK_FORMAT_R8_UNORM); for (u32 i = 0; i < m_image_count; i++) { Images& images = m_dynamic_images.emplace_back(); @@ -66,39 +64,39 @@ void SMAA::CreateImages(const Device& device) { CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT); images.image_views[Blend] = - CreateWrappedImageView(device, images.images[Blend], VK_FORMAT_R16G16B16A16_SFLOAT); + CreateWrappedImageView(m_device, images.images[Blend], VK_FORMAT_R16G16B16A16_SFLOAT); images.image_views[Edges] = - CreateWrappedImageView(device, images.images[Edges], VK_FORMAT_R16G16_SFLOAT); + CreateWrappedImageView(m_device, images.images[Edges], VK_FORMAT_R16G16_SFLOAT); images.image_views[Output] = - CreateWrappedImageView(device, images.images[Output], VK_FORMAT_R16G16B16A16_SFLOAT); + CreateWrappedImageView(m_device, images.images[Output], VK_FORMAT_R16G16B16A16_SFLOAT); } } -void SMAA::CreateRenderPasses(const Device& device) { - m_renderpasses[EdgeDetection] = CreateWrappedRenderPass(device, VK_FORMAT_R16G16_SFLOAT); +void SMAA::CreateRenderPasses() { + m_renderpasses[EdgeDetection] = CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16_SFLOAT); m_renderpasses[BlendingWeightCalculation] = - CreateWrappedRenderPass(device, VK_FORMAT_R16G16B16A16_SFLOAT); + CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16B16A16_SFLOAT); m_renderpasses[NeighborhoodBlending] = - CreateWrappedRenderPass(device, VK_FORMAT_R16G16B16A16_SFLOAT); + CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16B16A16_SFLOAT); for (auto& images : m_dynamic_images) { images.framebuffers[EdgeDetection] = CreateWrappedFramebuffer( - device, m_renderpasses[EdgeDetection], images.image_views[Edges], m_extent); + m_device, m_renderpasses[EdgeDetection], images.image_views[Edges], m_extent); images.framebuffers[BlendingWeightCalculation] = - CreateWrappedFramebuffer(device, m_renderpasses[BlendingWeightCalculation], + CreateWrappedFramebuffer(m_device, m_renderpasses[BlendingWeightCalculation], images.image_views[Blend], m_extent); images.framebuffers[NeighborhoodBlending] = CreateWrappedFramebuffer( - device, m_renderpasses[NeighborhoodBlending], images.image_views[Output], m_extent); + m_device, m_renderpasses[NeighborhoodBlending], images.image_views[Output], m_extent); } } -void SMAA::CreateSampler(const Device& device) { - m_sampler = CreateWrappedSampler(device); +void SMAA::CreateSampler() { + m_sampler = CreateWrappedSampler(m_device); } -void SMAA::CreateShaders(const Device& device) { +void SMAA::CreateShaders() { // These match the order of the SMAAStage enum static constexpr std::array vert_shader_sources{ ARRAY_TO_SPAN(SMAA_EDGE_DETECTION_VERT_SPV), @@ -112,33 +110,33 @@ void SMAA::CreateShaders(const Device& device) { }; for (size_t i = 0; i < MaxSMAAStage; i++) { - m_vertex_shaders[i] = CreateWrappedShaderModule(device, vert_shader_sources[i]); - m_fragment_shaders[i] = CreateWrappedShaderModule(device, frag_shader_sources[i]); + m_vertex_shaders[i] = CreateWrappedShaderModule(m_device, vert_shader_sources[i]); + m_fragment_shaders[i] = CreateWrappedShaderModule(m_device, frag_shader_sources[i]); } } -void SMAA::CreateDescriptorPool(const Device& device) { +void SMAA::CreateDescriptorPool() { // Edge detection: 1 descriptor // Blending weight calculation: 3 descriptors // Neighborhood blending: 2 descriptors // 6 descriptors, 3 descriptor sets per image - m_descriptor_pool = CreateWrappedDescriptorPool(device, 6 * m_image_count, 3 * m_image_count); + m_descriptor_pool = CreateWrappedDescriptorPool(m_device, 6 * m_image_count, 3 * m_image_count); } -void SMAA::CreateDescriptorSetLayouts(const Device& device) { +void SMAA::CreateDescriptorSetLayouts() { m_descriptor_set_layouts[EdgeDetection] = - CreateWrappedDescriptorSetLayout(device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}); + CreateWrappedDescriptorSetLayout(m_device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}); m_descriptor_set_layouts[BlendingWeightCalculation] = - CreateWrappedDescriptorSetLayout(device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + CreateWrappedDescriptorSetLayout(m_device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}); m_descriptor_set_layouts[NeighborhoodBlending] = - CreateWrappedDescriptorSetLayout(device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + CreateWrappedDescriptorSetLayout(m_device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}); } -void SMAA::CreateDescriptorSets(const Device& device) { +void SMAA::CreateDescriptorSets() { std::vector layouts(m_descriptor_set_layouts.size()); std::ranges::transform(m_descriptor_set_layouts, layouts.begin(), [](auto& layout) { return *layout; }); @@ -148,21 +146,21 @@ void SMAA::CreateDescriptorSets(const Device& device) { } } -void SMAA::CreatePipelineLayouts(const Device& device) { +void SMAA::CreatePipelineLayouts() { for (size_t i = 0; i < MaxSMAAStage; i++) { - m_pipeline_layouts[i] = CreateWrappedPipelineLayout(device, m_descriptor_set_layouts[i]); + m_pipeline_layouts[i] = CreateWrappedPipelineLayout(m_device, m_descriptor_set_layouts[i]); } } -void SMAA::CreatePipelines(const Device& device) { +void SMAA::CreatePipelines() { for (size_t i = 0; i < MaxSMAAStage; i++) { m_pipelines[i] = - CreateWrappedPipeline(device, m_renderpasses[i], m_pipeline_layouts[i], + CreateWrappedPipeline(m_device, m_renderpasses[i], m_pipeline_layouts[i], std::tie(m_vertex_shaders[i], m_fragment_shaders[i])); } } -void SMAA::UpdateDescriptorSets(const Device& device, VkImageView image_view, size_t image_index) { +void SMAA::UpdateDescriptorSets(VkImageView image_view, size_t image_index) { Images& images = m_dynamic_images[image_index]; std::vector image_infos; std::vector updates; @@ -186,10 +184,10 @@ void SMAA::UpdateDescriptorSets(const Device& device, VkImageView image_view, si updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, *images.image_views[Blend], images.descriptor_sets[NeighborhoodBlending], 1)); - device.GetLogical().UpdateDescriptorSets(updates, {}); + m_device.GetLogical().UpdateDescriptorSets(updates, {}); } -void SMAA::UploadImages(const Device& device, Scheduler& scheduler) { +void SMAA::UploadImages(Scheduler& scheduler) { if (m_images_ready) { return; } @@ -197,9 +195,9 @@ void SMAA::UploadImages(const Device& device, Scheduler& scheduler) { static constexpr VkExtent2D area_extent{AREATEX_WIDTH, AREATEX_HEIGHT}; static constexpr VkExtent2D search_extent{SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT}; - UploadImage(device, m_allocator, scheduler, m_static_images[Area], area_extent, + UploadImage(m_device, m_allocator, scheduler, m_static_images[Area], area_extent, VK_FORMAT_R8G8_UNORM, ARRAY_TO_SPAN(areaTexBytes)); - UploadImage(device, m_allocator, scheduler, m_static_images[Search], search_extent, + UploadImage(m_device, m_allocator, scheduler, m_static_images[Search], search_extent, VK_FORMAT_R8_UNORM, ARRAY_TO_SPAN(searchTexBytes)); scheduler.Record([&](vk::CommandBuffer cmdbuf) { @@ -214,7 +212,8 @@ void SMAA::UploadImages(const Device& device, Scheduler& scheduler) { m_images_ready = true; } -void SMAA::Draw(const Device& device, Scheduler& scheduler, size_t image_index, VkImage* inout_image, VkImageView* inout_image_view) { +void SMAA::Draw(Scheduler& scheduler, size_t image_index, VkImage* inout_image, + VkImageView* inout_image_view) { Images& images = m_dynamic_images[image_index]; VkImage input_image = *inout_image; @@ -233,8 +232,8 @@ void SMAA::Draw(const Device& device, Scheduler& scheduler, size_t image_index, *images.framebuffers[BlendingWeightCalculation]; VkFramebuffer neighborhood_blending_framebuffer = *images.framebuffers[NeighborhoodBlending]; - UploadImages(device, scheduler); - UpdateDescriptorSets(device, *inout_image_view, image_index); + UploadImages(scheduler); + UpdateDescriptorSets(*inout_image_view, image_index); scheduler.RequestOutsideRenderPassOperationContext(); scheduler.Record([=, this](vk::CommandBuffer cmdbuf) { diff --git a/src/video_core/renderer_vulkan/present/smaa.h b/src/video_core/renderer_vulkan/present/smaa.h index a547161395..fdf6def070 100644 --- a/src/video_core/renderer_vulkan/present/smaa.h +++ b/src/video_core/renderer_vulkan/present/smaa.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -19,10 +16,11 @@ class StagingBufferPool; class SMAA final : public AntiAliasPass { public: - explicit SMAA(const Device& device, MemoryAllocator& allocator, size_t image_count, VkExtent2D extent); + explicit SMAA(const Device& device, MemoryAllocator& allocator, size_t image_count, + VkExtent2D extent); ~SMAA() override; - void Draw(const Device& device, Scheduler& scheduler, size_t image_index, VkImage* inout_image, + void Draw(Scheduler& scheduler, size_t image_index, VkImage* inout_image, VkImageView* inout_image_view) override; private: @@ -46,18 +44,19 @@ private: MaxDynamicImage = 3, }; - void CreateImages(const Device& device); - void CreateRenderPasses(const Device& device); - void CreateSampler(const Device& device); - void CreateShaders(const Device& device); - void CreateDescriptorPool(const Device& device); - void CreateDescriptorSetLayouts(const Device& device); - void CreateDescriptorSets(const Device& device); - void CreatePipelineLayouts(const Device& device); - void CreatePipelines(const Device& device); - void UpdateDescriptorSets(const Device& device, VkImageView image_view, size_t image_index); - void UploadImages(const Device& device, Scheduler& scheduler); + void CreateImages(); + void CreateRenderPasses(); + void CreateSampler(); + void CreateShaders(); + void CreateDescriptorPool(); + void CreateDescriptorSetLayouts(); + void CreateDescriptorSets(); + void CreatePipelineLayouts(); + void CreatePipelines(); + void UpdateDescriptorSets(VkImageView image_view, size_t image_index); + void UploadImages(Scheduler& scheduler); + const Device& m_device; MemoryAllocator& m_allocator; const VkExtent2D m_extent; const u32 m_image_count; diff --git a/src/video_core/renderer_vulkan/present/window_adapt_pass.cpp b/src/video_core/renderer_vulkan/present/window_adapt_pass.cpp index 549b0660c1..22ffacf119 100644 --- a/src/video_core/renderer_vulkan/present/window_adapt_pass.cpp +++ b/src/video_core/renderer_vulkan/present/window_adapt_pass.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -18,20 +15,19 @@ namespace Vulkan { -WindowAdaptPass::WindowAdaptPass(const Device& device, VkFormat frame_format, vk::Sampler&& sampler_, vk::ShaderModule&& fragment_shader_) - : sampler(std::move(sampler_)) - , fragment_shader(std::move(fragment_shader_)) -{ - CreateDescriptorSetLayout(device); - CreatePipelineLayout(device); - CreateVertexShader(device); - CreateRenderPass(device, frame_format); - CreatePipelines(device); +WindowAdaptPass::WindowAdaptPass(const Device& device_, VkFormat frame_format, + vk::Sampler&& sampler_, vk::ShaderModule&& fragment_shader_) + : device(device_), sampler(std::move(sampler_)), fragment_shader(std::move(fragment_shader_)) { + CreateDescriptorSetLayout(); + CreatePipelineLayout(); + CreateVertexShader(); + CreateRenderPass(frame_format); + CreatePipelines(); } WindowAdaptPass::~WindowAdaptPass() = default; -void WindowAdaptPass::Draw(const Device& device, RasterizerVulkan& rasterizer, Scheduler& scheduler, size_t image_index, +void WindowAdaptPass::Draw(RasterizerVulkan& rasterizer, Scheduler& scheduler, size_t image_index, std::list& layers, std::span configs, const Layout::FramebufferLayout& layout, Frame* dst) { @@ -64,7 +60,7 @@ void WindowAdaptPass::Draw(const Device& device, RasterizerVulkan& rasterizer, S break; } - layer_it->ConfigureDraw(device, &push_constants[i], &descriptor_sets[i], rasterizer, *sampler, + layer_it->ConfigureDraw(&push_constants[i], &descriptor_sets[i], rasterizer, *sampler, image_index, configs[i], layout); layer_it++; } @@ -115,12 +111,12 @@ VkRenderPass WindowAdaptPass::GetRenderPass() { return *render_pass; } -void WindowAdaptPass::CreateDescriptorSetLayout(const Device& device) { +void WindowAdaptPass::CreateDescriptorSetLayout() { descriptor_set_layout = CreateWrappedDescriptorSetLayout(device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}); } -void WindowAdaptPass::CreatePipelineLayout(const Device& device) { +void WindowAdaptPass::CreatePipelineLayout() { const VkPushConstantRange range{ .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, .offset = 0, @@ -138,15 +134,15 @@ void WindowAdaptPass::CreatePipelineLayout(const Device& device) { }); } -void WindowAdaptPass::CreateVertexShader(const Device& device) { +void WindowAdaptPass::CreateVertexShader() { vertex_shader = BuildShader(device, VULKAN_PRESENT_VERT_SPV); } -void WindowAdaptPass::CreateRenderPass(const Device& device, VkFormat frame_format) { +void WindowAdaptPass::CreateRenderPass(VkFormat frame_format) { render_pass = CreateWrappedRenderPass(device, frame_format, VK_IMAGE_LAYOUT_UNDEFINED); } -void WindowAdaptPass::CreatePipelines(const Device& device) { +void WindowAdaptPass::CreatePipelines() { opaque_pipeline = CreateWrappedPipeline(device, render_pass, pipeline_layout, std::tie(vertex_shader, fragment_shader)); premultiplied_pipeline = CreateWrappedPremultipliedBlendingPipeline( diff --git a/src/video_core/renderer_vulkan/present/window_adapt_pass.h b/src/video_core/renderer_vulkan/present/window_adapt_pass.h index 58d6fc01c0..cf667a4fc6 100644 --- a/src/video_core/renderer_vulkan/present/window_adapt_pass.h +++ b/src/video_core/renderer_vulkan/present/window_adapt_pass.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -33,7 +30,7 @@ public: vk::ShaderModule&& fragment_shader); ~WindowAdaptPass(); - void Draw(const Device& device, RasterizerVulkan& rasterizer, Scheduler& scheduler, size_t image_index, + void Draw(RasterizerVulkan& rasterizer, Scheduler& scheduler, size_t image_index, std::list& layers, std::span configs, const Layout::FramebufferLayout& layout, Frame* dst); @@ -41,12 +38,14 @@ public: VkRenderPass GetRenderPass(); private: - void CreateDescriptorSetLayout(const Device& device); - void CreatePipelineLayout(const Device& device); - void CreateVertexShader(const Device& device); - void CreateRenderPass(const Device& device, VkFormat frame_format); - void CreatePipelines(const Device& device); + void CreateDescriptorSetLayout(); + void CreatePipelineLayout(); + void CreateVertexShader(); + void CreateRenderPass(VkFormat frame_format); + void CreatePipelines(); +private: + const Device& device; vk::DescriptorSetLayout descriptor_set_layout; vk::PipelineLayout pipeline_layout; vk::Sampler sampler; diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index b0a7d0c579..30a39ef81e 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -188,7 +188,7 @@ void RendererVulkan::Composite(std::span framebu Frame* frame = present_manager.GetRenderFrame(); scheduler.RequestOutsideRenderPassOperationContext(); - blit_swapchain.DrawToFrame(device, rasterizer, frame, framebuffers, + blit_swapchain.DrawToFrame(rasterizer, frame, framebuffers, render_window.GetFramebufferLayout(), swapchain.GetImageCount(), swapchain.GetImageViewFormat()); scheduler.Flush(*frame->render_ready); @@ -226,12 +226,12 @@ vk::Buffer RendererVulkan::RenderToBuffer(std::span framebuffers, const Layout::FramebufferLayout& layout, size_t current_swapchain_image_count, @@ -110,8 +107,8 @@ void BlitScreen::DrawToFrame(const Device& device, RasterizerVulkan& rasterizer, } if (resource_update_required) { - WaitIdle(device); - SetWindowAdaptPass(device); + WaitIdle(); + SetWindowAdaptPass(); if (presentation_recreate_required) { present_manager.RecreateFrame(frame, layout.width, layout.height, swapchain_view_format, @@ -134,22 +131,22 @@ void BlitScreen::DrawToFrame(const Device& device, RasterizerVulkan& rasterizer, } } - window_adapt->Draw(device, rasterizer, scheduler, image_index, layers, framebuffers, layout, frame); + window_adapt->Draw(rasterizer, scheduler, image_index, layers, framebuffers, layout, frame); if (++image_index >= image_count) { image_index = 0; } } -vk::Framebuffer BlitScreen::CreateFramebuffer(const Device& device, const Layout::FramebufferLayout& layout, +vk::Framebuffer BlitScreen::CreateFramebuffer(const Layout::FramebufferLayout& layout, VkImageView image_view, VkFormat current_view_format) { bool format_updated = swapchain_view_format != current_view_format; swapchain_view_format = current_view_format; if (!window_adapt || scaling_filter != filters.get_scaling_filter() || format_updated) { - WaitIdle(device); - SetWindowAdaptPass(device); + WaitIdle(); + SetWindowAdaptPass(); image_index = 0; } @@ -158,10 +155,10 @@ vk::Framebuffer BlitScreen::CreateFramebuffer(const Device& device, const Layout .height = layout.height, }; - return CreateFramebuffer(device, image_view, extent, window_adapt->GetRenderPass()); + return CreateFramebuffer(image_view, extent, window_adapt->GetRenderPass()); } -vk::Framebuffer BlitScreen::CreateFramebuffer(const Device& device, const VkImageView& image_view, VkExtent2D extent, +vk::Framebuffer BlitScreen::CreateFramebuffer(const VkImageView& image_view, VkExtent2D extent, VkRenderPass render_pass) { return device.GetLogical().CreateFramebuffer(VkFramebufferCreateInfo{ .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.h b/src/video_core/renderer_vulkan/vk_blit_screen.h index e50f0bcf33..531c57fc5c 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.h +++ b/src/video_core/renderer_vulkan/vk_blit_screen.h @@ -1,6 +1,3 @@ -// 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 @@ -55,22 +52,23 @@ public: Scheduler& scheduler, const PresentFilters& filters); ~BlitScreen(); - void DrawToFrame(const Device& device, RasterizerVulkan& rasterizer, Frame* frame, + void DrawToFrame(RasterizerVulkan& rasterizer, Frame* frame, std::span framebuffers, const Layout::FramebufferLayout& layout, size_t current_swapchain_image_count, VkFormat current_swapchain_view_format); - [[nodiscard]] vk::Framebuffer CreateFramebuffer(const Device& device, const Layout::FramebufferLayout& layout, + [[nodiscard]] vk::Framebuffer CreateFramebuffer(const Layout::FramebufferLayout& layout, VkImageView image_view, VkFormat current_view_format); private: - void WaitIdle(const Device& device); - void SetWindowAdaptPass(const Device& device); - vk::Framebuffer CreateFramebuffer(const Device& device, const VkImageView& image_view, VkExtent2D extent, + void WaitIdle(); + void SetWindowAdaptPass(); + vk::Framebuffer CreateFramebuffer(const VkImageView& image_view, VkExtent2D extent, VkRenderPass render_pass); Tegra::MaxwellDeviceMemoryManager& device_memory; + const Device& device; MemoryAllocator& memory_allocator; PresentManager& present_manager; Scheduler& scheduler; diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.cpp b/src/video_core/renderer_vulkan/vk_compute_pass.cpp index c24b7a5757..55e8a9b3f0 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pass.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pass.cpp @@ -234,7 +234,7 @@ struct ConditionalRenderingResolvePushConstants { }; } // Anonymous namespace -ComputePass::ComputePass(const Device& device_, Scheduler& scheduler, DescriptorPool& descriptor_pool, +ComputePass::ComputePass(const Device& device_, DescriptorPool& descriptor_pool, vk::Span bindings, vk::Span templates, const DescriptorBankInfo& bank_info, @@ -270,7 +270,7 @@ ComputePass::ComputePass(const Device& device_, Scheduler& scheduler, Descriptor .pipelineLayout = *layout, .set = 0, }); - descriptor_allocator = descriptor_pool.Allocator(device, scheduler, *descriptor_set_layout, bank_info); + descriptor_allocator = descriptor_pool.Allocator(*descriptor_set_layout, bank_info); } if (code.empty()) { return; @@ -313,7 +313,7 @@ ComputePass::~ComputePass() = default; Uint8Pass::Uint8Pass(const Device& device_, Scheduler& scheduler_, DescriptorPool& descriptor_pool, StagingBufferPool& staging_buffer_pool_, ComputePassDescriptorQueue& compute_pass_descriptor_queue_) - : ComputePass(device_, scheduler_, descriptor_pool, INPUT_OUTPUT_DESCRIPTOR_SET_BINDINGS, + : ComputePass(device_, descriptor_pool, INPUT_OUTPUT_DESCRIPTOR_SET_BINDINGS, INPUT_OUTPUT_DESCRIPTOR_UPDATE_TEMPLATE, INPUT_OUTPUT_BANK_INFO, {}, VULKAN_UINT8_COMP_SPV), scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_}, @@ -355,7 +355,7 @@ QuadIndexedPass::QuadIndexedPass(const Device& device_, Scheduler& scheduler_, DescriptorPool& descriptor_pool_, StagingBufferPool& staging_buffer_pool_, ComputePassDescriptorQueue& compute_pass_descriptor_queue_) - : ComputePass(device_, scheduler_, descriptor_pool_, INPUT_OUTPUT_DESCRIPTOR_SET_BINDINGS, + : ComputePass(device_, descriptor_pool_, INPUT_OUTPUT_DESCRIPTOR_SET_BINDINGS, INPUT_OUTPUT_DESCRIPTOR_UPDATE_TEMPLATE, INPUT_OUTPUT_BANK_INFO, COMPUTE_PUSH_CONSTANT_RANGE, VULKAN_QUAD_INDEXED_COMP_SPV), scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_}, @@ -416,7 +416,7 @@ std::pair QuadIndexedPass::Assemble( ConditionalRenderingResolvePass::ConditionalRenderingResolvePass( const Device& device_, Scheduler& scheduler_, DescriptorPool& descriptor_pool_, ComputePassDescriptorQueue& compute_pass_descriptor_queue_) - : ComputePass(device_, scheduler_, descriptor_pool_, INPUT_OUTPUT_DESCRIPTOR_SET_BINDINGS, + : ComputePass(device_, descriptor_pool_, INPUT_OUTPUT_DESCRIPTOR_SET_BINDINGS, INPUT_OUTPUT_DESCRIPTOR_UPDATE_TEMPLATE, INPUT_OUTPUT_BANK_INFO, COMPUTE_PUSH_CONSTANT_RANGE, RESOLVE_CONDITIONAL_RENDER_COMP_SPV), @@ -470,7 +470,7 @@ QueriesPrefixScanPass::QueriesPrefixScanPass( const Device& device_, Scheduler& scheduler_, DescriptorPool& descriptor_pool_, ComputePassDescriptorQueue& compute_pass_descriptor_queue_) : ComputePass( - device_, scheduler_, descriptor_pool_, QUERIES_SCAN_DESCRIPTOR_SET_BINDINGS, + device_, descriptor_pool_, QUERIES_SCAN_DESCRIPTOR_SET_BINDINGS, QUERIES_SCAN_DESCRIPTOR_UPDATE_TEMPLATE, QUERIES_SCAN_BANK_INFO, COMPUTE_PUSH_CONSTANT_RANGE, device_.IsSubgroupFeatureSupported(VK_SUBGROUP_FEATURE_BASIC_BIT) && @@ -547,7 +547,7 @@ ASTCDecoderPass::ASTCDecoderPass(const Device& device_, Scheduler& scheduler_, StagingBufferPool& staging_buffer_pool_, ComputePassDescriptorQueue& compute_pass_descriptor_queue_, MemoryAllocator& memory_allocator_) - : ComputePass(device_, scheduler_, descriptor_pool_, ASTC_DESCRIPTOR_SET_BINDINGS, + : ComputePass(device_, descriptor_pool_, ASTC_DESCRIPTOR_SET_BINDINGS, ASTC_PASS_DESCRIPTOR_UPDATE_TEMPLATE_ENTRY, ASTC_BANK_INFO, COMPUTE_PUSH_CONSTANT_RANGE, ASTC_DECODER_COMP_SPV), scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_}, @@ -746,7 +746,7 @@ BlockLinearUnswizzle3DPass::BlockLinearUnswizzle3DPass( StagingBufferPool& staging_buffer_pool_, ComputePassDescriptorQueue& compute_pass_descriptor_queue_) : ComputePass( - device_, scheduler_, descriptor_pool_, + device_, descriptor_pool_, BL3D_DESCRIPTOR_SET_BINDINGS, BL3D_DESCRIPTOR_UPDATE_TEMPLATE_ENTRY, BL3D_BANK_INFO, @@ -941,7 +941,7 @@ MSAACopyPass::MSAACopyPass(const Device& device_, Scheduler& scheduler_, DescriptorPool& descriptor_pool_, StagingBufferPool& staging_buffer_pool_, ComputePassDescriptorQueue& compute_pass_descriptor_queue_) - : ComputePass(device_, scheduler_, descriptor_pool_, MSAA_DESCRIPTOR_SET_BINDINGS, + : ComputePass(device_, descriptor_pool_, MSAA_DESCRIPTOR_SET_BINDINGS, MSAA_DESCRIPTOR_UPDATE_TEMPLATE, MSAA_BANK_INFO, {}, CONVERT_NON_MSAA_TO_MSAA_COMP_SPV), scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_}, diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.h b/src/video_core/renderer_vulkan/vk_compute_pass.h index cb213dae7e..0e5badce01 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pass.h +++ b/src/video_core/renderer_vulkan/vk_compute_pass.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project @@ -35,7 +35,7 @@ struct StagingBufferRef; class ComputePass { public: - explicit ComputePass(const Device& device, Scheduler& scheduler, DescriptorPool& descriptor_pool, + explicit ComputePass(const Device& device, DescriptorPool& descriptor_pool, vk::Span bindings, vk::Span templates, const DescriptorBankInfo& bank_info, diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp index 2c1fd94e67..81ff8fe31a 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp @@ -30,7 +30,7 @@ using Shader::ImageBufferDescriptor; using Shader::Backend::SPIRV::RESCALING_LAYOUT_WORDS_OFFSET; using Tegra::Texture::TexturePair; -ComputePipeline::ComputePipeline(const Device& device_, Scheduler& scheduler, vk::PipelineCache& pipeline_cache_, +ComputePipeline::ComputePipeline(const Device& device_, vk::PipelineCache& pipeline_cache_, DescriptorPool& descriptor_pool, GuestDescriptorQueue& guest_descriptor_queue_, Common::ThreadWorker* thread_worker, @@ -46,7 +46,7 @@ ComputePipeline::ComputePipeline(const Device& device_, Scheduler& scheduler, vk std::copy_n(info.constant_buffer_used_sizes.begin(), uniform_buffer_sizes.size(), uniform_buffer_sizes.begin()); - auto func{[this, &scheduler, &descriptor_pool, shader_notify, pipeline_statistics] { + auto func{[this, &descriptor_pool, shader_notify, pipeline_statistics] { DescriptorLayoutBuilder builder{device}; builder.Add(info, VK_SHADER_STAGE_COMPUTE_BIT); @@ -56,7 +56,7 @@ ComputePipeline::ComputePipeline(const Device& device_, Scheduler& scheduler, vk descriptor_update_template = builder.CreateTemplate(*descriptor_set_layout, *pipeline_layout, uses_push_descriptor); if (!uses_push_descriptor) { - descriptor_allocator = descriptor_pool.Allocator(device, scheduler, *descriptor_set_layout, info); + descriptor_allocator = descriptor_pool.Allocator(*descriptor_set_layout, info); } const VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT subgroup_size_ci{ .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT, @@ -94,7 +94,7 @@ ComputePipeline::ComputePipeline(const Device& device_, Scheduler& scheduler, vk } if (pipeline_statistics) { - pipeline_statistics->Collect(device, *pipeline); + pipeline_statistics->Collect(*pipeline); } std::scoped_lock lock{build_mutex}; is_built = true; diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.h b/src/video_core/renderer_vulkan/vk_compute_pipeline.h index f3abe4c931..aa84c00e12 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.h @@ -31,7 +31,7 @@ class Scheduler; class ComputePipeline { public: - explicit ComputePipeline(const Device& device, Scheduler& scheduler, vk::PipelineCache& pipeline_cache, + explicit ComputePipeline(const Device& device, vk::PipelineCache& pipeline_cache, DescriptorPool& descriptor_pool, GuestDescriptorQueue& guest_descriptor_queue, Common::ThreadWorker* thread_worker, diff --git a/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp b/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp index b020d99b93..3af9758a31 100644 --- a/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp +++ b/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project @@ -125,22 +125,27 @@ vk::DescriptorSets DescriptorAllocator::AllocateDescriptors(size_t count) { throw vk::Exception(VK_ERROR_OUT_OF_POOL_MEMORY); } -DescriptorPool::DescriptorPool(const Device& device_, Scheduler& scheduler) {} +DescriptorPool::DescriptorPool(const Device& device_, Scheduler& scheduler) + : device{device_}, master_semaphore{scheduler.GetMasterSemaphore()} {} + DescriptorPool::~DescriptorPool() = default; -DescriptorAllocator DescriptorPool::Allocator(const Device& device, Scheduler& scheduler, VkDescriptorSetLayout layout, std::span infos) { - return Allocator(device, scheduler, layout, MakeBankInfo(infos)); +DescriptorAllocator DescriptorPool::Allocator(VkDescriptorSetLayout layout, + std::span infos) { + return Allocator(layout, MakeBankInfo(infos)); } -DescriptorAllocator DescriptorPool::Allocator(const Device& device, Scheduler& scheduler, VkDescriptorSetLayout layout, const Shader::Info& info) { - return Allocator(device, scheduler, layout, MakeBankInfo(std::array{info})); +DescriptorAllocator DescriptorPool::Allocator(VkDescriptorSetLayout layout, + const Shader::Info& info) { + return Allocator(layout, MakeBankInfo(std::array{info})); } -DescriptorAllocator DescriptorPool::Allocator(const Device& device, Scheduler& scheduler, VkDescriptorSetLayout layout, const DescriptorBankInfo& info) { - return DescriptorAllocator(device, scheduler.GetMasterSemaphore(), Bank(device, info), layout); +DescriptorAllocator DescriptorPool::Allocator(VkDescriptorSetLayout layout, + const DescriptorBankInfo& info) { + return DescriptorAllocator(device, master_semaphore, Bank(info), layout); } -DescriptorBank& DescriptorPool::Bank(const Device& device, const DescriptorBankInfo& reqs) { +DescriptorBank& DescriptorPool::Bank(const DescriptorBankInfo& reqs) { std::shared_lock read_lock{banks_mutex}; const auto it = std::ranges::find_if(bank_infos, [&reqs](const DescriptorBankInfo& bank) { return std::abs(bank.score - reqs.score) < SCORE_THRESHOLD && bank.IsSuperset(reqs); diff --git a/src/video_core/renderer_vulkan/vk_descriptor_pool.h b/src/video_core/renderer_vulkan/vk_descriptor_pool.h index 4efeb60373..4aada5a006 100644 --- a/src/video_core/renderer_vulkan/vk_descriptor_pool.h +++ b/src/video_core/renderer_vulkan/vk_descriptor_pool.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -71,12 +68,17 @@ public: DescriptorPool& operator=(const DescriptorPool&) = delete; DescriptorPool(const DescriptorPool&) = delete; - DescriptorAllocator Allocator(const Device& device, Scheduler& scheduler, VkDescriptorSetLayout layout, std::span infos); - DescriptorAllocator Allocator(const Device& device, Scheduler& scheduler, VkDescriptorSetLayout layout, const Shader::Info& info); - DescriptorAllocator Allocator(const Device& device, Scheduler& scheduler, VkDescriptorSetLayout layout, const DescriptorBankInfo& info); + DescriptorAllocator Allocator(VkDescriptorSetLayout layout, + std::span infos); + DescriptorAllocator Allocator(VkDescriptorSetLayout layout, const Shader::Info& info); + DescriptorAllocator Allocator(VkDescriptorSetLayout layout, const DescriptorBankInfo& info); private: - DescriptorBank& Bank(const Device& device, const DescriptorBankInfo& reqs); + DescriptorBank& Bank(const DescriptorBankInfo& reqs); + + const Device& device; + MasterSemaphore& master_semaphore; + std::shared_mutex banks_mutex; std::vector bank_infos; std::vector> banks; diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 3b5338a058..728554d6e6 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -276,7 +276,7 @@ GraphicsPipeline::GraphicsPipeline( descriptor_set_layout = builder.CreateDescriptorSetLayout(uses_push_descriptor); if (!uses_push_descriptor) { - descriptor_allocator = descriptor_pool.Allocator(device, scheduler, *descriptor_set_layout, stage_infos); + descriptor_allocator = descriptor_pool.Allocator(*descriptor_set_layout, stage_infos); } const VkDescriptorSetLayout set_layout{*descriptor_set_layout}; @@ -288,7 +288,7 @@ GraphicsPipeline::GraphicsPipeline( Validate(); MakePipeline(render_pass); if (pipeline_statistics) { - pipeline_statistics->Collect(device, *pipeline); + pipeline_statistics->Collect(*pipeline); } std::scoped_lock lock{build_mutex}; diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 798499141e..23bfbceccb 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -915,7 +915,7 @@ std::unique_ptr PipelineCache::CreateComputePipeline( spv_module.SetObjectNameEXT(name.c_str()); } Common::ThreadWorker* const thread_worker{build_in_parallel ? &workers : nullptr}; - return std::make_unique(device, scheduler, vulkan_pipeline_cache, descriptor_pool, + return std::make_unique(device, vulkan_pipeline_cache, descriptor_pool, guest_descriptor_queue, thread_worker, statistics, &shader_notify, program.info, std::move(spv_module)); diff --git a/src/video_core/renderer_vulkan/vk_query_cache.cpp b/src/video_core/renderer_vulkan/vk_query_cache.cpp index 06d405c2f5..f0c704b700 100644 --- a/src/video_core/renderer_vulkan/vk_query_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp @@ -126,14 +126,16 @@ public: current_query = nullptr; amend_value = 0; accumulation_value = 0; - queries_prefix_scan_pass.emplace(device, scheduler, descriptor_pool, compute_pass_descriptor_queue); + queries_prefix_scan_pass = std::make_unique( + device, scheduler, descriptor_pool, compute_pass_descriptor_queue); const VkBufferCreateInfo buffer_ci = { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .pNext = nullptr, .flags = 0, .size = 8, - .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, + .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, .sharingMode = VK_SHARING_MODE_EXCLUSIVE, .queueFamilyIndexCount = 0, .pQueueFamilyIndices = nullptr, @@ -590,7 +592,8 @@ private: VideoCommon::HostQueryBase* current_query; bool has_started{}; std::mutex flush_guard; - std::optional queries_prefix_scan_pass; + + std::unique_ptr queries_prefix_scan_pass; }; // Transform feedback queries @@ -1263,23 +1266,41 @@ private: } // namespace struct QueryCacheRuntimeImpl { - QueryCacheRuntimeImpl(QueryCacheRuntime& runtime, VideoCore::RasterizerInterface* rasterizer_, Tegra::MaxwellDeviceMemoryManager& device_memory_, Vulkan::BufferCache& buffer_cache_, const Device& device_, const MemoryAllocator& memory_allocator_, Scheduler& scheduler_, StagingBufferPool& staging_pool_, ComputePassDescriptorQueue& compute_pass_descriptor_queue, DescriptorPool& descriptor_pool, TextureCache& texture_cache_) - : rasterizer{rasterizer_}, device_memory{device_memory_}, buffer_cache{buffer_cache_} - , device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_} - , staging_pool{staging_pool_}, guest_streamer(0, runtime) - , sample_streamer(size_t(QueryType::ZPassPixelCount64), runtime, rasterizer, texture_cache_, device, scheduler, memory_allocator, compute_pass_descriptor_queue, descriptor_pool) - , tfb_streamer(size_t(QueryType::StreamingByteCount), runtime, device, scheduler, memory_allocator, staging_pool) - , primitives_succeeded_streamer(size_t(QueryType::StreamingPrimitivesSucceeded), runtime, tfb_streamer, device_memory_) - , primitives_needed_minus_succeeded_streamer(size_t(QueryType::StreamingPrimitivesNeededMinusSucceeded), runtime, 0u) - , hcr_setup{}, hcr_is_set{}, is_hcr_running{}, maxwell3d{} { + QueryCacheRuntimeImpl(QueryCacheRuntime& runtime, VideoCore::RasterizerInterface* rasterizer_, + Tegra::MaxwellDeviceMemoryManager& device_memory_, + Vulkan::BufferCache& buffer_cache_, const Device& device_, + const MemoryAllocator& memory_allocator_, Scheduler& scheduler_, + StagingBufferPool& staging_pool_, + ComputePassDescriptorQueue& compute_pass_descriptor_queue, + DescriptorPool& descriptor_pool, TextureCache& texture_cache_) + : rasterizer{rasterizer_}, device_memory{device_memory_}, buffer_cache{buffer_cache_}, + device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_}, + staging_pool{staging_pool_}, guest_streamer(0, runtime), + sample_streamer(static_cast(QueryType::ZPassPixelCount64), runtime, rasterizer, + texture_cache_, device, scheduler, memory_allocator, + compute_pass_descriptor_queue, descriptor_pool), + tfb_streamer(static_cast(QueryType::StreamingByteCount), runtime, device, + scheduler, memory_allocator, staging_pool), + primitives_succeeded_streamer( + static_cast(QueryType::StreamingPrimitivesSucceeded), runtime, tfb_streamer, + device_memory_), + primitives_needed_minus_succeeded_streamer( + static_cast(QueryType::StreamingPrimitivesNeededMinusSucceeded), runtime, 0u), + hcr_setup{}, hcr_is_set{}, is_hcr_running{}, maxwell3d{} { hcr_setup.sType = VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT; hcr_setup.pNext = nullptr; hcr_setup.flags = 0; - VkBufferUsageFlags hcr_buffer_usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; - if (device.IsExtConditionalRendering()) { - conditional_resolve_pass.emplace(device, scheduler, descriptor_pool, compute_pass_descriptor_queue); + const bool has_conditional_rendering = device.IsExtConditionalRendering(); + if (has_conditional_rendering) { + conditional_resolve_pass = std::make_unique( + device, scheduler, descriptor_pool, compute_pass_descriptor_queue); + } + + VkBufferUsageFlags hcr_buffer_usage = + VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + if (has_conditional_rendering) { hcr_buffer_usage |= VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT; } @@ -1318,7 +1339,7 @@ struct QueryCacheRuntimeImpl { std::vector> copies_setup; // Host conditional rendering data - std::optional conditional_resolve_pass; + std::unique_ptr conditional_resolve_pass; vk::Buffer hcr_resolve_buffer; VkConditionalRenderingBeginInfoEXT hcr_setup; VkBuffer hcr_buffer; @@ -1330,7 +1351,13 @@ struct QueryCacheRuntimeImpl { Maxwell3D* maxwell3d; }; -QueryCacheRuntime::QueryCacheRuntime(VideoCore::RasterizerInterface* rasterizer, Tegra::MaxwellDeviceMemoryManager& device_memory_, Vulkan::BufferCache& buffer_cache_, const Device& device_, const MemoryAllocator& memory_allocator_, Scheduler& scheduler_, StagingBufferPool& staging_pool_, ComputePassDescriptorQueue& compute_pass_descriptor_queue, DescriptorPool& descriptor_pool, TextureCache& texture_cache_) { +QueryCacheRuntime::QueryCacheRuntime(VideoCore::RasterizerInterface* rasterizer, + Tegra::MaxwellDeviceMemoryManager& device_memory_, + Vulkan::BufferCache& buffer_cache_, const Device& device_, + const MemoryAllocator& memory_allocator_, + Scheduler& scheduler_, StagingBufferPool& staging_pool_, + ComputePassDescriptorQueue& compute_pass_descriptor_queue, + DescriptorPool& descriptor_pool, TextureCache& texture_cache_) { impl = std::make_unique( *this, rasterizer, device_memory_, buffer_cache_, device_, memory_allocator_, scheduler_, staging_pool_, compute_pass_descriptor_queue, descriptor_pool, texture_cache_); @@ -1659,7 +1686,8 @@ void QueryCacheRuntime::SyncValues(std::span values, VkBuffer ba } impl->scheduler.RequestOutsideRenderPassOperationContext(); - impl->scheduler.Record([src_buffer, dst_buffers = std::move(impl->buffers_to_upload_to), vk_copies = std::move(impl->copies_setup)](vk::CommandBuffer cmdbuf) { + impl->scheduler.Record([src_buffer, dst_buffers = std::move(impl->buffers_to_upload_to), + vk_copies = std::move(impl->copies_setup)](vk::CommandBuffer cmdbuf) { size_t size = dst_buffers.size(); for (size_t i = 0; i < size; i++) { cmdbuf.CopyBuffer(src_buffer, dst_buffers[i].first, vk_copies[i]); diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.cpp b/src/video_core/renderer_vulkan/vk_state_tracker.cpp index 0b132c97d6..a7b7c46f39 100644 --- a/src/video_core/renderer_vulkan/vk_state_tracker.cpp +++ b/src/video_core/renderer_vulkan/vk_state_tracker.cpp @@ -235,7 +235,7 @@ void SetupRasterModes(Maxwell3D::DirtyState::Tables &tables) { } // Anonymous namespace void StateTracker::SetupTables(Tegra::Control::ChannelState& channel_state) { - auto& tables{channel_state.payload->maxwell_3d.dirty.tables}; + auto& tables{channel_state.maxwell_3d->dirty.tables}; SetupDirtyFlags(tables); SetupDirtyViewports(tables); SetupDirtyScissors(tables); @@ -258,7 +258,7 @@ void StateTracker::SetupTables(Tegra::Control::ChannelState& channel_state) { } void StateTracker::ChangeChannel(Tegra::Control::ChannelState& channel_state) { - flags = &channel_state.payload->maxwell_3d.dirty.flags; + flags = &channel_state.maxwell_3d->dirty.flags; } void StateTracker::InvalidateState() { diff --git a/src/video_core/renderer_vulkan/vk_update_descriptor.h b/src/video_core/renderer_vulkan/vk_update_descriptor.h index 1497108b16..82fce298da 100644 --- a/src/video_core/renderer_vulkan/vk_update_descriptor.h +++ b/src/video_core/renderer_vulkan/vk_update_descriptor.h @@ -1,13 +1,10 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once #include -#include + #include "video_core/vulkan_common/vulkan_wrapper.h" namespace Vulkan { @@ -15,15 +12,20 @@ namespace Vulkan { class Device; class Scheduler; -union DescriptorUpdateEntry { +struct DescriptorUpdateEntry { + struct Empty {}; + DescriptorUpdateEntry() = default; DescriptorUpdateEntry(VkDescriptorImageInfo image_) : image{image_} {} DescriptorUpdateEntry(VkDescriptorBufferInfo buffer_) : buffer{buffer_} {} DescriptorUpdateEntry(VkBufferView texel_buffer_) : texel_buffer{texel_buffer_} {} - std::monostate empty{}; - VkDescriptorImageInfo image; - VkDescriptorBufferInfo buffer; - VkBufferView texel_buffer; + + union { + Empty empty{}; + VkDescriptorImageInfo image; + VkDescriptorBufferInfo buffer; + VkBufferView texel_buffer; + }; }; class UpdateDescriptorQueue final { diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp index 54fb8f6239..1ac7a0bc35 100644 --- a/src/video_core/video_core.cpp +++ b/src/video_core/video_core.cpp @@ -45,23 +45,23 @@ std::unique_ptr CreateRenderer(Core::System& system, Co namespace VideoCore { -/// @brief Creates an emulated GPU instance using the given system context. -void CreateGPU(std::optional& gpu, Core::Frontend::EmuWindow& emu_window, Core::System& system) { +std::unique_ptr CreateGPU(Core::Frontend::EmuWindow& emu_window, Core::System& system) { Settings::UpdateRescalingInfo(); const auto nvdec_value = Settings::values.nvdec_emulation.GetValue(); const bool use_nvdec = nvdec_value != Settings::NvdecEmulation::Off; const bool use_async = Settings::values.use_asynchronous_gpu_emulation.GetValue(); - gpu.emplace(system, use_async, use_nvdec); + auto gpu = std::make_unique(system, use_async, use_nvdec); auto context = emu_window.CreateSharedContext(); auto scope = context->Acquire(); try { auto renderer = CreateRenderer(system, emu_window, *gpu, std::move(context)); gpu->BindRenderer(std::move(renderer)); + return gpu; } catch (const std::runtime_error& exception) { scope.Cancel(); LOG_ERROR(HW_GPU, "Failed to initialize GPU: {}", exception.what()); - gpu.reset(); + return nullptr; } } diff --git a/src/video_core/video_core.h b/src/video_core/video_core.h index 1a56dd99b6..f8e2444f33 100644 --- a/src/video_core/video_core.h +++ b/src/video_core/video_core.h @@ -1,13 +1,9 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: 2014 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once #include -#include namespace Core { class System; @@ -24,6 +20,8 @@ class GPU; namespace VideoCore { class RendererBase; -void CreateGPU(std::optional& gpu, Core::Frontend::EmuWindow& emu_window, Core::System& system); + +/// Creates an emulated GPU instance using the given system context. +std::unique_ptr CreateGPU(Core::Frontend::EmuWindow& emu_window, Core::System& system); } // namespace VideoCore