diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index 6b6415832..f684985d0 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h @@ -72,7 +72,7 @@ public: protected: /// Creates the storage for the session data of the service. - virtual std::unique_ptr MakeSessionData() const = 0; + virtual std::unique_ptr MakeSessionData() = 0; /// Returns the session data associated with the server session. template diff --git a/src/core/hle/service/gsp/gsp_gpu.cpp b/src/core/hle/service/gsp/gsp_gpu.cpp index 129139014..1eb4aae52 100644 --- a/src/core/hle/service/gsp/gsp_gpu.cpp +++ b/src/core/hle/service/gsp/gsp_gpu.cpp @@ -50,12 +50,6 @@ constexpr ResultCode ERR_REGS_INVALID_SIZE(ErrorDescription::InvalidSize, ErrorM ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E02BEC -/// Maximum number of threads that can be registered at the same time in the GSP module. -constexpr u32 MaxGSPThreads = 4; - -/// Thread ids currently in use by the sessions connected to the GSPGPU service. -static std::array used_thread_ids = {false, false, false, false}; - static PAddr VirtualToPhysicalAddress(VAddr addr) { if (addr == 0) { return 0; @@ -79,7 +73,7 @@ static PAddr VirtualToPhysicalAddress(VAddr addr) { return addr | 0x80000000; } -static u32 GetUnusedThreadId() { +u32 GSP_GPU::GetUnusedThreadId() { for (u32 id = 0; id < MaxGSPThreads; ++id) { if (!used_thread_ids[id]) return id; @@ -821,17 +815,25 @@ GSP_GPU::GSP_GPU(Core::System& system) : ServiceFramework("gsp::Gpu", 2), system first_initialization = true; }; +std::unique_ptr GSP_GPU::MakeSessionData() { + return std::make_unique(this); +} + SessionData::SessionData() { + UNREACHABLE(); +} + +SessionData::SessionData(GSP_GPU* gsp) : gsp(gsp) { // Assign a new thread id to this session when it connects. Note: In the real GSP service this // is done through a real thread (svcCreateThread) but we have to simulate it since our HLE // services don't have threads. - thread_id = GetUnusedThreadId(); - used_thread_ids[thread_id] = true; + thread_id = gsp->GetUnusedThreadId(); + gsp->used_thread_ids[thread_id] = true; } SessionData::~SessionData() { // Free the thread id slot so that other sessions can use it. - used_thread_ids[thread_id] = false; + gsp->used_thread_ids[thread_id] = false; } } // namespace Service::GSP diff --git a/src/core/hle/service/gsp/gsp_gpu.h b/src/core/hle/service/gsp/gsp_gpu.h index b1ab6807f..1c264837c 100644 --- a/src/core/hle/service/gsp/gsp_gpu.h +++ b/src/core/hle/service/gsp/gsp_gpu.h @@ -183,10 +183,15 @@ struct CommandBuffer { }; static_assert(sizeof(CommandBuffer) == 0x200, "CommandBuffer struct has incorrect size"); +class GSP_GPU; + struct SessionData : public Kernel::SessionRequestHandler::SessionDataBase { SessionData(); + SessionData(GSP_GPU* gsp); ~SessionData(); + GSP_GPU* gsp; + /// Event triggered when GSP interrupt has been signalled std::shared_ptr interrupt_event; /// Thread index into interrupt relay queue @@ -404,6 +409,10 @@ private: /// Returns the session data for the specified registered thread id, or nullptr if not found. SessionData* FindRegisteredThreadData(u32 thread_id); + u32 GetUnusedThreadId(); + + std::unique_ptr MakeSessionData() override; + Core::System& system; /// GSP shared memory @@ -413,6 +422,14 @@ private: int active_thread_id = -1; bool first_initialization = true; + + /// Maximum number of threads that can be registered at the same time in the GSP module. + static constexpr u32 MaxGSPThreads = 4; + + /// Thread ids currently in use by the sessions connected to the GSPGPU service. + std::array used_thread_ids = {false, false, false, false}; + + friend class SessionData; }; ResultCode SetBufferSwap(u32 screen_id, const FrameBufferInfo& info); diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 0e8d7222e..1d9e800e2 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -156,7 +156,7 @@ protected: RegisterHandlersBase(functions, n); } - std::unique_ptr MakeSessionData() const override { + std::unique_ptr MakeSessionData() override { return std::make_unique(); }