From 18447ac6ac48046cbb3b7bc1dc5a397ca1c70952 Mon Sep 17 00:00:00 2001 From: PabloMK7 Date: Wed, 7 May 2025 19:31:13 +0200 Subject: [PATCH] Fix savestates with the OpenGL renderer --- src/core/core.cpp | 12 ++++++++++++ src/core/hle/kernel/kernel.h | 3 +++ src/core/hle/kernel/thread.cpp | 14 +++++++++++++- src/core/hle/kernel/thread.h | 2 +- src/core/hle/service/gsp/gsp_gpu.cpp | 3 +++ src/core/hle/service/gsp/gsp_gpu.h | 12 +++++++++++- 6 files changed, 43 insertions(+), 3 deletions(-) diff --git a/src/core/core.cpp b/src/core/core.cpp index 98ac85eba..d5064787d 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -826,6 +826,18 @@ void System::serialize(Archive& ar, const unsigned int file_version) { auto gsp = service_manager->GetService("gsp::Gpu"); gpu->SetInterruptHandler( [gsp](Service::GSP::InterruptId interrupt_id) { gsp->SignalInterrupt(interrupt_id); }); + + // Switch the shader cache to the title running when the savestate was created + const u32 thread_id = gsp->GetActiveClientThreadId(); + if (thread_id != std::numeric_limits::max()) { + const auto thread = kernel->GetThreadByID(thread_id); + if (thread) { + const std::shared_ptr process = thread->owner_process.lock(); + if (process) { + gpu->Renderer().Rasterizer()->SwitchDiskResources(process->codeset->program_id); + } + } + } } else { u32 cheats_pid = cheat_engine.GetConnectedPID(); ar & cheats_pid; diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 5704cdda0..d3b0bc53e 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -270,6 +270,9 @@ public: /// Retrieves a process from the current list of processes. std::shared_ptr GetProcessById(u32 process_id) const; + /// Retrieves a thread from the current list of threads. + std::shared_ptr GetThreadByID(u32 thread_id) const; + std::span> GetProcessList() const { return process_list; } diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 0170cef3d..22789369b 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -528,8 +528,20 @@ ThreadManager::~ThreadManager() { } } -std::span> ThreadManager::GetThreadList() { +std::span> ThreadManager::GetThreadList() const { return thread_list; } +std::shared_ptr KernelSystem::GetThreadByID(u32 thread_id) const { + for (u32 core_id = 0; core_id < Core::System::GetInstance().GetNumCores(); core_id++) { + const auto thread_list = GetThreadManager(core_id).GetThreadList(); + for (auto& thread : thread_list) { + if (thread->thread_id == thread_id) { + return thread; + } + } + } + return nullptr; +} + } // namespace Kernel diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 09291d567..8853384f4 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -124,7 +124,7 @@ public: /** * Get a const reference to the thread list for debug use */ - std::span> GetThreadList(); + std::span> GetThreadList() const; void SetCPU(Core::ARM_Interface& cpu_) { cpu = &cpu_; diff --git a/src/core/hle/service/gsp/gsp_gpu.cpp b/src/core/hle/service/gsp/gsp_gpu.cpp index 6887de663..35157cd08 100644 --- a/src/core/hle/service/gsp/gsp_gpu.cpp +++ b/src/core/hle/service/gsp/gsp_gpu.cpp @@ -626,6 +626,7 @@ Result GSP_GPU::AcquireGpuRight(const Kernel::HLERequestContext& ctx, } active_thread_id = session_data->thread_id; + active_client_thread_id = ctx.ClientThread()->thread_id; return ResultSuccess; } @@ -654,6 +655,7 @@ void GSP_GPU::ReleaseRight(const SessionData* session_data) { ASSERT_MSG(active_thread_id == session_data->thread_id, "Wrong thread tried to release GPU right"); active_thread_id = std::numeric_limits::max(); + active_client_thread_id = std::numeric_limits::max(); } void GSP_GPU::ReleaseRight(Kernel::HLERequestContext& ctx) { @@ -723,6 +725,7 @@ void GSP_GPU::serialize(Archive& ar, const unsigned int) { ar& boost::serialization::base_object(*this); ar & shared_memory; ar & active_thread_id; + ar & active_client_thread_id; ar & first_initialization; ar & used_thread_ids; ar & saved_vram; diff --git a/src/core/hle/service/gsp/gsp_gpu.h b/src/core/hle/service/gsp/gsp_gpu.h index e1bc5eb4f..f5f810c44 100644 --- a/src/core/hle/service/gsp/gsp_gpu.h +++ b/src/core/hle/service/gsp/gsp_gpu.h @@ -1,4 +1,4 @@ -// Copyright 2014 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -123,6 +123,13 @@ public: return active_thread_id; } + /** + * Retreives the ID of the client thread with GPU rights. + */ + u32 GetActiveClientThreadId() { + return active_client_thread_id; + } + private: /** * Signals that the specified interrupt type has occurred to userland code for the specified GSP @@ -378,6 +385,9 @@ private: /// Thread id that currently has GPU rights or std::numeric_limits::max() if none. u32 active_thread_id = std::numeric_limits::max(); + /// Thread id of the client thread that has GPU rights + u32 active_client_thread_id = std::numeric_limits::max(); + bool first_initialization = true; /// VRAM copy saved using SaveVramSysArea.