mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	gsp_gpu: Implement TryAcquireRight and stub SetInternalPriorities. (#7285)
* gsp_gpu: Implement TryAcquireRight. * gsp_gpu: Stub SetInternalPriorities. * gsp_gpu: Move serialization logic into implementation. * gsp_gpu: Replace UINT32_MAX with std::numeric_limits<u32>::max().
This commit is contained in:
		
							parent
							
								
									b6b98af105
								
							
						
					
					
						commit
						bd4ec251cd
					
				
					 2 changed files with 119 additions and 46 deletions
				
			
		|  | @ -4,6 +4,9 @@ | ||||||
| 
 | 
 | ||||||
| #include <span> | #include <span> | ||||||
| #include <vector> | #include <vector> | ||||||
|  | #include <boost/serialization/base_object.hpp> | ||||||
|  | #include <boost/serialization/optional.hpp> | ||||||
|  | #include <boost/serialization/shared_ptr.hpp> | ||||||
| #include "common/archives.h" | #include "common/archives.h" | ||||||
| #include "common/bit_field.h" | #include "common/bit_field.h" | ||||||
| #include "common/microprofile.h" | #include "common/microprofile.h" | ||||||
|  | @ -478,7 +481,7 @@ void GSP_GPU::SignalInterrupt(InterruptId interrupt_id) { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // For normal interrupts, don't do anything if no process has acquired the GPU right.
 |     // For normal interrupts, don't do anything if no process has acquired the GPU right.
 | ||||||
|     if (active_thread_id == UINT32_MAX) { |     if (active_thread_id == std::numeric_limits<u32>::max()) { | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -664,7 +667,7 @@ void GSP_GPU::TriggerCmdReqQueue(Kernel::HLERequestContext& ctx) { | ||||||
| void GSP_GPU::ImportDisplayCaptureInfo(Kernel::HLERequestContext& ctx) { | void GSP_GPU::ImportDisplayCaptureInfo(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(ctx); |     IPC::RequestParser rp(ctx); | ||||||
| 
 | 
 | ||||||
|     if (active_thread_id == UINT32_MAX) { |     if (active_thread_id == std::numeric_limits<u32>::max()) { | ||||||
|         LOG_WARNING(Service_GSP, "Called without an active thread."); |         LOG_WARNING(Service_GSP, "Called without an active thread."); | ||||||
| 
 | 
 | ||||||
|         // TODO: Find the right error code.
 |         // TODO: Find the right error code.
 | ||||||
|  | @ -792,37 +795,57 @@ void GSP_GPU::RestoreVramSysArea(Kernel::HLERequestContext& ctx) { | ||||||
|     rb.Push(RESULT_SUCCESS); |     rb.Push(RESULT_SUCCESS); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GSP_GPU::AcquireRight(Kernel::HLERequestContext& ctx) { | ResultCode GSP_GPU::AcquireGpuRight(const Kernel::HLERequestContext& ctx, | ||||||
|     IPC::RequestParser rp(ctx); |                                     const std::shared_ptr<Kernel::Process>& process, u32 flag, | ||||||
|  |                                     bool blocking) { | ||||||
|  |     const auto session_data = GetSessionData(ctx.Session()); | ||||||
| 
 | 
 | ||||||
|     u32 flag = rp.Pop<u32>(); |     LOG_DEBUG(Service_GSP, "called flag={:08X} process={} thread_id={}", flag, process->process_id, | ||||||
|     auto process = rp.PopObject<Kernel::Process>(); |               session_data->thread_id); | ||||||
| 
 |  | ||||||
|     SessionData* session_data = GetSessionData(ctx.Session()); |  | ||||||
| 
 |  | ||||||
|     LOG_WARNING(Service_GSP, "called flag={:08X} process={} thread_id={}", flag, |  | ||||||
|                 process->process_id, session_data->thread_id); |  | ||||||
| 
 |  | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); |  | ||||||
| 
 | 
 | ||||||
|     if (active_thread_id == session_data->thread_id) { |     if (active_thread_id == session_data->thread_id) { | ||||||
|         rb.Push(ResultCode(ErrorDescription::AlreadyDone, ErrorModule::GX, ErrorSummary::Success, |         return {ErrorDescription::AlreadyDone, ErrorModule::GX, ErrorSummary::Success, | ||||||
|                            ErrorLevel::Success)); |                 ErrorLevel::Success}; | ||||||
|         return; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // TODO(Subv): This case should put the caller thread to sleep until the right is released.
 |     if (blocking) { | ||||||
|     ASSERT_MSG(active_thread_id == UINT32_MAX, "GPU right has already been acquired"); |         // TODO: The thread should be put to sleep until acquired.
 | ||||||
|  |         ASSERT_MSG(active_thread_id == std::numeric_limits<u32>::max(), | ||||||
|  |                    "Sleeping for GPU right is not yet supported."); | ||||||
|  |     } else if (active_thread_id != std::numeric_limits<u32>::max()) { | ||||||
|  |         return {ErrorDescription::Busy, ErrorModule::GX, ErrorSummary::WouldBlock, | ||||||
|  |                 ErrorLevel::Status}; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     active_thread_id = session_data->thread_id; |     active_thread_id = session_data->thread_id; | ||||||
|  |     return RESULT_SUCCESS; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
|     rb.Push(RESULT_SUCCESS); | void GSP_GPU::TryAcquireRight(Kernel::HLERequestContext& ctx) { | ||||||
|  |     IPC::RequestParser rp(ctx); | ||||||
|  |     const auto process = rp.PopObject<Kernel::Process>(); | ||||||
|  | 
 | ||||||
|  |     const auto result = AcquireGpuRight(ctx, process, 0, false); | ||||||
|  | 
 | ||||||
|  |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|  |     rb.Push(result); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void GSP_GPU::AcquireRight(Kernel::HLERequestContext& ctx) { | ||||||
|  |     IPC::RequestParser rp(ctx); | ||||||
|  |     const auto flag = rp.Pop<u32>(); | ||||||
|  |     const auto process = rp.PopObject<Kernel::Process>(); | ||||||
|  | 
 | ||||||
|  |     const auto result = AcquireGpuRight(ctx, process, flag, true); | ||||||
|  | 
 | ||||||
|  |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|  |     rb.Push(result); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GSP_GPU::ReleaseRight(const SessionData* session_data) { | void GSP_GPU::ReleaseRight(const SessionData* session_data) { | ||||||
|     ASSERT_MSG(active_thread_id == session_data->thread_id, |     ASSERT_MSG(active_thread_id == session_data->thread_id, | ||||||
|                "Wrong thread tried to release GPU right"); |                "Wrong thread tried to release GPU right"); | ||||||
|     active_thread_id = UINT32_MAX; |     active_thread_id = std::numeric_limits<u32>::max(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GSP_GPU::ReleaseRight(Kernel::HLERequestContext& ctx) { | void GSP_GPU::ReleaseRight(Kernel::HLERequestContext& ctx) { | ||||||
|  | @ -863,6 +886,18 @@ void GSP_GPU::SetLedForceOff(Kernel::HLERequestContext& ctx) { | ||||||
|     LOG_DEBUG(Service_GSP, "(STUBBED) called"); |     LOG_DEBUG(Service_GSP, "(STUBBED) called"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void GSP_GPU::SetInternalPriorities(Kernel::HLERequestContext& ctx) { | ||||||
|  |     IPC::RequestParser rp(ctx); | ||||||
|  |     const auto priority = rp.Pop<u32>(); | ||||||
|  |     const auto priority_with_rights = rp.Pop<u32>(); | ||||||
|  | 
 | ||||||
|  |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|  |     rb.Push(RESULT_SUCCESS); | ||||||
|  | 
 | ||||||
|  |     LOG_DEBUG(Service_GSP, "(STUBBED) called priority={:#02X}, priority_with_rights={:#02X}", | ||||||
|  |               priority, priority_with_rights); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| SessionData* GSP_GPU::FindRegisteredThreadData(u32 thread_id) { | SessionData* GSP_GPU::FindRegisteredThreadData(u32 thread_id) { | ||||||
|     for (auto& session_info : connected_sessions) { |     for (auto& session_info : connected_sessions) { | ||||||
|         SessionData* data = static_cast<SessionData*>(session_info.data.get()); |         SessionData* data = static_cast<SessionData*>(session_info.data.get()); | ||||||
|  | @ -874,6 +909,17 @@ SessionData* GSP_GPU::FindRegisteredThreadData(u32 thread_id) { | ||||||
|     return nullptr; |     return nullptr; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | template <class Archive> | ||||||
|  | void GSP_GPU::serialize(Archive& ar, const unsigned int) { | ||||||
|  |     ar& boost::serialization::base_object<Kernel::SessionRequestHandler>(*this); | ||||||
|  |     ar& shared_memory; | ||||||
|  |     ar& active_thread_id; | ||||||
|  |     ar& first_initialization; | ||||||
|  |     ar& used_thread_ids; | ||||||
|  |     ar& saved_vram; | ||||||
|  | } | ||||||
|  | SERIALIZE_IMPL(GSP_GPU) | ||||||
|  | 
 | ||||||
| GSP_GPU::GSP_GPU(Core::System& system) : ServiceFramework("gsp::Gpu", 4), system(system) { | GSP_GPU::GSP_GPU(Core::System& system) : ServiceFramework("gsp::Gpu", 4), system(system) { | ||||||
|     static const FunctionInfo functions[] = { |     static const FunctionInfo functions[] = { | ||||||
|         // clang-format off
 |         // clang-format off
 | ||||||
|  | @ -897,7 +943,7 @@ GSP_GPU::GSP_GPU(Core::System& system) : ServiceFramework("gsp::Gpu", 4), system | ||||||
|         {0x0012, nullptr, "GetPerfLog"}, |         {0x0012, nullptr, "GetPerfLog"}, | ||||||
|         {0x0013, &GSP_GPU::RegisterInterruptRelayQueue, "RegisterInterruptRelayQueue"}, |         {0x0013, &GSP_GPU::RegisterInterruptRelayQueue, "RegisterInterruptRelayQueue"}, | ||||||
|         {0x0014, &GSP_GPU::UnregisterInterruptRelayQueue, "UnregisterInterruptRelayQueue"}, |         {0x0014, &GSP_GPU::UnregisterInterruptRelayQueue, "UnregisterInterruptRelayQueue"}, | ||||||
|         {0x0015, nullptr, "TryAcquireRight"}, |         {0x0015, &GSP_GPU::TryAcquireRight, "TryAcquireRight"}, | ||||||
|         {0x0016, &GSP_GPU::AcquireRight, "AcquireRight"}, |         {0x0016, &GSP_GPU::AcquireRight, "AcquireRight"}, | ||||||
|         {0x0017, &GSP_GPU::ReleaseRight, "ReleaseRight"}, |         {0x0017, &GSP_GPU::ReleaseRight, "ReleaseRight"}, | ||||||
|         {0x0018, &GSP_GPU::ImportDisplayCaptureInfo, "ImportDisplayCaptureInfo"}, |         {0x0018, &GSP_GPU::ImportDisplayCaptureInfo, "ImportDisplayCaptureInfo"}, | ||||||
|  | @ -906,7 +952,7 @@ GSP_GPU::GSP_GPU(Core::System& system) : ServiceFramework("gsp::Gpu", 4), system | ||||||
|         {0x001B, nullptr, "ResetGpuCore"}, |         {0x001B, nullptr, "ResetGpuCore"}, | ||||||
|         {0x001C, &GSP_GPU::SetLedForceOff, "SetLedForceOff"}, |         {0x001C, &GSP_GPU::SetLedForceOff, "SetLedForceOff"}, | ||||||
|         {0x001D, nullptr, "SetTestCommand"}, |         {0x001D, nullptr, "SetTestCommand"}, | ||||||
|         {0x001E, nullptr, "SetInternalPriorities"}, |         {0x001E, &GSP_GPU::SetInternalPriorities, "SetInternalPriorities"}, | ||||||
|         {0x001F, &GSP_GPU::StoreDataCache, "StoreDataCache"}, |         {0x001F, &GSP_GPU::StoreDataCache, "StoreDataCache"}, | ||||||
|         // clang-format on
 |         // clang-format on
 | ||||||
|     }; |     }; | ||||||
|  | @ -926,6 +972,16 @@ std::unique_ptr<Kernel::SessionRequestHandler::SessionDataBase> GSP_GPU::MakeSes | ||||||
|     return std::make_unique<SessionData>(this); |     return std::make_unique<SessionData>(this); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | template <class Archive> | ||||||
|  | void SessionData::serialize(Archive& ar, const unsigned int) { | ||||||
|  |     ar& boost::serialization::base_object<Kernel::SessionRequestHandler::SessionDataBase>(*this); | ||||||
|  |     ar& gsp; | ||||||
|  |     ar& interrupt_event; | ||||||
|  |     ar& thread_id; | ||||||
|  |     ar& registered; | ||||||
|  | } | ||||||
|  | SERIALIZE_IMPL(SessionData) | ||||||
|  | 
 | ||||||
| SessionData::SessionData(GSP_GPU* gsp) : gsp(gsp) { | 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
 |     // 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
 |     // is done through a real thread (svcCreateThread) but we have to simulate it since our HLE
 | ||||||
|  |  | ||||||
|  | @ -7,9 +7,8 @@ | ||||||
| #include <cstddef> | #include <cstddef> | ||||||
| #include <memory> | #include <memory> | ||||||
| #include <string> | #include <string> | ||||||
| #include <boost/serialization/base_object.hpp> | #include <boost/optional/optional.hpp> | ||||||
| #include <boost/serialization/optional.hpp> | #include <boost/serialization/export.hpp> | ||||||
| #include <boost/serialization/shared_ptr.hpp> |  | ||||||
| #include "common/bit_field.h" | #include "common/bit_field.h" | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "core/hle/kernel/event.h" | #include "core/hle/kernel/event.h" | ||||||
|  | @ -22,6 +21,8 @@ class System; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| namespace Kernel { | namespace Kernel { | ||||||
|  | class HLERequestContext; | ||||||
|  | class Process; | ||||||
| class SharedMemory; | class SharedMemory; | ||||||
| } // namespace Kernel
 | } // namespace Kernel
 | ||||||
| 
 | 
 | ||||||
|  | @ -214,14 +215,7 @@ public: | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     template <class Archive> |     template <class Archive> | ||||||
|     void serialize(Archive& ar, const unsigned int) { |     void serialize(Archive& ar, const unsigned int); | ||||||
|         ar& boost::serialization::base_object<Kernel::SessionRequestHandler::SessionDataBase>( |  | ||||||
|             *this); |  | ||||||
|         ar& gsp; |  | ||||||
|         ar& interrupt_event; |  | ||||||
|         ar& thread_id; |  | ||||||
|         ar& registered; |  | ||||||
|     } |  | ||||||
|     friend class boost::serialization::access; |     friend class boost::serialization::access; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -379,9 +373,25 @@ private: | ||||||
|     void UnregisterInterruptRelayQueue(Kernel::HLERequestContext& ctx); |     void UnregisterInterruptRelayQueue(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * GSP_GPU::AcquireRight service function |      * GSP_GPU::TryAcquireRight service function | ||||||
|  |      *  Inputs: | ||||||
|  |      *      0 : Header code [0x00150002] | ||||||
|  |      *      1 : Handle translate header (0x0) | ||||||
|  |      *      2 : Process handle | ||||||
|      *  Outputs: |      *  Outputs: | ||||||
|      *      1: Result code |      *      1 : Result of function, 0 on success, otherwise error code | ||||||
|  |      */ | ||||||
|  |     void TryAcquireRight(Kernel::HLERequestContext& ctx); | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * GSP_GPU::AcquireRight service function | ||||||
|  |      *  Inputs: | ||||||
|  |      *      0 : Header code [0x00160042] | ||||||
|  |      *      1 : Flags | ||||||
|  |      *      2 : Handle translate header (0x0) | ||||||
|  |      *      3 : Process handle | ||||||
|  |      *  Outputs: | ||||||
|  |      *      1 : Result of function, 0 on success, otherwise error code | ||||||
|      */ |      */ | ||||||
|     void AcquireRight(Kernel::HLERequestContext& ctx); |     void AcquireRight(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
|  | @ -464,6 +474,17 @@ private: | ||||||
|     /// Force the 3D LED State (0 = On, Non-Zero = Off)
 |     /// Force the 3D LED State (0 = On, Non-Zero = Off)
 | ||||||
|     void SetLedForceOff(Kernel::HLERequestContext& ctx); |     void SetLedForceOff(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
|  |     /**
 | ||||||
|  |      * GSP_GPU::SetInternalPriorities service function | ||||||
|  |      *  Inputs: | ||||||
|  |      *      0 : Header code [0x001E0080] | ||||||
|  |      *      1 : Session thread priority | ||||||
|  |      *      2 : Session thread priority with rights | ||||||
|  |      *  Outputs: | ||||||
|  |      *      1 : Result of function, 0 on success, otherwise error code | ||||||
|  |      */ | ||||||
|  |     void SetInternalPriorities(Kernel::HLERequestContext& ctx); | ||||||
|  | 
 | ||||||
|     /// Returns the session data for the specified registered thread id, or nullptr if not found.
 |     /// Returns the session data for the specified registered thread id, or nullptr if not found.
 | ||||||
|     SessionData* FindRegisteredThreadData(u32 thread_id); |     SessionData* FindRegisteredThreadData(u32 thread_id); | ||||||
| 
 | 
 | ||||||
|  | @ -471,13 +492,17 @@ private: | ||||||
| 
 | 
 | ||||||
|     std::unique_ptr<Kernel::SessionRequestHandler::SessionDataBase> MakeSessionData() override; |     std::unique_ptr<Kernel::SessionRequestHandler::SessionDataBase> MakeSessionData() override; | ||||||
| 
 | 
 | ||||||
|  |     ResultCode AcquireGpuRight(const Kernel::HLERequestContext& ctx, | ||||||
|  |                                const std::shared_ptr<Kernel::Process>& process, u32 flag, | ||||||
|  |                                bool blocking); | ||||||
|  | 
 | ||||||
|     Core::System& system; |     Core::System& system; | ||||||
| 
 | 
 | ||||||
|     /// GSP shared memory
 |     /// GSP shared memory
 | ||||||
|     std::shared_ptr<Kernel::SharedMemory> shared_memory; |     std::shared_ptr<Kernel::SharedMemory> shared_memory; | ||||||
| 
 | 
 | ||||||
|     /// Thread id that currently has GPU rights or UINT32_MAX if none.
 |     /// Thread id that currently has GPU rights or std::numeric_limits<u32>::max() if none.
 | ||||||
|     u32 active_thread_id = UINT32_MAX; |     u32 active_thread_id = std::numeric_limits<u32>::max(); | ||||||
| 
 | 
 | ||||||
|     bool first_initialization = true; |     bool first_initialization = true; | ||||||
| 
 | 
 | ||||||
|  | @ -493,15 +518,7 @@ private: | ||||||
|     friend class SessionData; |     friend class SessionData; | ||||||
| 
 | 
 | ||||||
|     template <class Archive> |     template <class Archive> | ||||||
|     void serialize(Archive& ar, const unsigned int) { |     void serialize(Archive& ar, const unsigned int); | ||||||
|         ar& boost::serialization::base_object<Kernel::SessionRequestHandler>(*this); |  | ||||||
|         ar& shared_memory; |  | ||||||
|         ar& active_thread_id; |  | ||||||
|         ar& first_initialization; |  | ||||||
|         ar& used_thread_ids; |  | ||||||
|         ar& saved_vram; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     friend class boost::serialization::access; |     friend class boost::serialization::access; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue