diff options
| author | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-10-27 13:56:54 -0400 |
|---|---|---|
| committer | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-10-27 13:56:54 -0400 |
| commit | 360ea914c7eecc1b211f1362bd593c61b76d289c (patch) | |
| tree | 703f5decbd2237ef18c009f9b41846ed86dc228f /src | |
| parent | 5511fa9f9a9225e926a15e8c786e8ef1b8844f8d (diff) | |
service: Switch 2 GPU placeholder session (gsv 497)
gsv 497 returns the session nn::gpu::sdk::BootWithRemoteMemory keeps.
On it: TIPC 11 returns an id range, 12(id) returns that id's event, 21(id)
starts an operation the SDK then waits for (signalled at once here), 22
returns another session. With this nn::gs::sdk::BootGraphicsSystem
returns and boot moves on to nn::vi.
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/service/nx2_gsv.h | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/src/core/hle/service/nx2_gsv.h b/src/core/hle/service/nx2_gsv.h index 18ae9a6bc3..7619f56d71 100644 --- a/src/core/hle/service/nx2_gsv.h +++ b/src/core/hle/service/nx2_gsv.h @@ -78,6 +78,79 @@ private: } }; +// Placeholder for the Switch 2 GPU session (nn::gpu::sdk), handed out by gsv 497. +// - TIPC 11: [first, last] id range (first <= min(last, 64)); ids outside it are masked out. +// - TIPC 12(id): event handle for that id (handle at word 3, result at word 4); the SDK attaches +// it as a SystemEvent. +// - TIPC 21(id): starts an operation; the SDK then waits on the id's event. Nothing runs here, so +// the event is signalled at once. +// - TIPC 22: another handle the SDK keeps like a session; a placeholder session is returned. +class INx2GpuSession final : public ServiceFramework<INx2GpuSession> { +public: + explicit INx2GpuSession(Core::System& system_) + : ServiceFramework{system_, "nx2:gpu"}, m_context{system_, "nx2:gpu"} { + RegisterHandlersTipc({ + {11, &INx2GpuSession::GetIdRange, "GetIdRange (guessed)"}, + {12, &INx2GpuSession::GetIdEvent, "GetIdEvent (guessed)"}, + {21, &INx2GpuSession::Start, "Start (guessed)"}, + {22, &INx2GpuSession::OpenSubSession, "OpenSubSession (guessed)"}, + }); + } + + ~INx2GpuSession() override { + for (auto* event : m_events) { + if (event != nullptr) { + m_context.CloseEvent(event); + } + } + } + +private: + static constexpr u32 NumIds = 32; + + Kernel::KEvent* EventFor(u32 id) { + id %= NumIds; + if (m_events[id] == nullptr) { + m_events[id] = m_context.CreateEvent(fmt::format("nx2:gpu:Event{}", id)); + } + return m_events[id]; + } + + void GetIdRange(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) nx2:gpu TIPC 11, returning [0, {}]", NumIds - 1); + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(ResultSuccess); + rb.Push<u32>(0); + rb.Push<u32>(NumIds - 1); + } + + void GetIdEvent(HLERequestContext& ctx) { + const u32 id = ctx.CommandBuffer()[2]; + LOG_WARNING(Service, "(STUBBED) nx2:gpu TIPC 12 id={}", id); + IPC::ResponseBuilder rb{ctx, 2, 1, 0}; + rb.Push(ResultSuccess); + rb.PushCopyObjects(ctx, EventFor(id)->GetReadableEvent()); + } + + void Start(HLERequestContext& ctx) { + const u32 id = ctx.CommandBuffer()[2]; + LOG_WARNING(Service, "(STUBBED) nx2:gpu TIPC 21 id={}, signalling completion", id); + EventFor(id)->Signal(system.Kernel()); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); + } + + void OpenSubSession(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) nx2:gpu TIPC 22, returning a nx2:gpu-sub session"); + ReturnRawSession(system, ctx, + std::make_shared<INx2StubInterface>( + system, INx2StubInterface::InternName("nx2:gpu-sub"))); + } + + KernelHelpers::ServiceContext m_context; + std::array<Kernel::KEvent*, NumIds> m_events{}; +}; + // Placeholder for the Switch 2 graphics-system server that nn::gsv::BootWithRemoteMemory talks // to over TIPC. Nothing behind it is emulated: commands succeed and are logged, so boot can show // what comes next. Commands 202 and 1402 hand out the syncpt and nvsrv sessions the SDK uses. @@ -91,6 +164,7 @@ public: {101, &INx2GraphicsSystemSession::Stub, "Unknown101"}, {202, &INx2GraphicsSystemSession::OpenSyncptSession, "OpenSyncptSession (guessed)"}, {204, &INx2GraphicsSystemSession::AttachSyncptMemory, "AttachSyncptMemory (guessed)"}, + {497, &INx2GraphicsSystemSession::OpenGpuSession, "OpenGpuSession (guessed)"}, {1402, &INx2GraphicsSystemSession::OpenNvsrvSession, "OpenNvsrvSession (guessed)"}, }); } @@ -160,6 +234,16 @@ private: m_syncpt_events[1]->GetReadableEvent()); } + void OpenGpuSession(HLERequestContext& ctx) { + // Used by nn::gpu::sdk::BootWithRemoteMemory; takes one u64, returns a session (handle at + // word 3, result at word 4) that the GPU SDK keeps. + const auto* cmd_buf = ctx.CommandBuffer(); + const size_t data = TipcDataOffset(cmd_buf); + LOG_WARNING(Service, "(STUBBED) nx2:gsv TIPC 497 arg={:#x}, returning a nx2:gpu session", + u64{cmd_buf[data]} | (u64{cmd_buf[data + 1]} << 32)); + ReturnRawSession(system, ctx, std::make_shared<INx2GpuSession>(system)); + } + void OpenNvsrvSession(HLERequestContext& ctx) { // The SDK reads the handle at word 3 and the result at word 4. LOG_WARNING(Service, "(STUBBED) nx2:gsv TIPC 1402, returning a nx2:nvsrv session"); |
