diff --git a/include/services/gsp_gpu.hpp b/include/services/gsp_gpu.hpp index 19b63c08..cab6fbff 100644 --- a/include/services/gsp_gpu.hpp +++ b/include/services/gsp_gpu.hpp @@ -1,5 +1,6 @@ #pragma once #include +#include #include "PICA/gpu.hpp" #include "helpers.hpp" #include "kernel_types.hpp" @@ -16,16 +17,21 @@ enum class GPUInterrupt : u8 { DMA = 6 }; +// More circular dependencies +class Kernel; + class GPUService { Handle handle = KernelHandles::GPU; Memory& mem; GPU& gpu; + Kernel& kernel; u32& currentPID; // Process ID of the current process u8* sharedMem; // Pointer to GSP shared memory // At any point in time only 1 process has privileges to use rendering functions // This is the PID of that process u32 privilegedProcess; + std::optional interruptEvent; MAKE_LOG_FUNCTION(log, gspGPULogger) void processCommandBuffer(); @@ -51,7 +57,8 @@ class GPUService { void flushCacheRegions(u32* cmd); public: - GPUService(Memory& mem, GPU& gpu, u32& currentPID) : mem(mem), gpu(gpu), currentPID(currentPID) {} + GPUService(Memory& mem, GPU& gpu, Kernel& kernel, u32& currentPID) : mem(mem), gpu(gpu), + kernel(kernel), currentPID(currentPID) {} void reset(); void handleSyncRequest(u32 messagePointer); void requestInterrupt(GPUInterrupt type); diff --git a/src/core/kernel/events.cpp b/src/core/kernel/events.cpp index e923170f..54773345 100644 --- a/src/core/kernel/events.cpp +++ b/src/core/kernel/events.cpp @@ -213,9 +213,8 @@ void Kernel::waitSynchronizationN() { return; } - Helpers::panic("WaitSyncAny can't instantly acquire :("); - regs[0] = SVCResult::Success; - regs[1] = handleCount - 1; // FIX THIS + regs[0] = SVCResult::Success; // If the thread times out, this should be adjusted to SVCResult::Timeout + regs[1] = handleCount - 1; // When the thread exits, this will be adjusted to mirror which handle woke us up t.waitList.resize(handleCount); t.status = ThreadStatus::WaitSyncAny; t.outPointer = outPointer; diff --git a/src/core/services/gsp_gpu.cpp b/src/core/services/gsp_gpu.cpp index 896a4d54..44d6cfee 100644 --- a/src/core/services/gsp_gpu.cpp +++ b/src/core/services/gsp_gpu.cpp @@ -1,5 +1,6 @@ #include "services/gsp_gpu.hpp" #include "ipc.hpp" +#include "kernel.hpp" // Commands used with SendSyncRequest targetted to the GSP::GPU service namespace ServiceCommands { @@ -38,6 +39,7 @@ namespace Result { void GPUService::reset() { privilegedProcess = 0xFFFFFFFF; // Set the privileged process to an invalid handle + interruptEvent = std::nullopt; sharedMem = nullptr; } @@ -90,6 +92,13 @@ void GPUService::registerInterruptRelayQueue(u32 messagePointer) { const u32 eventHandle = mem.read32(messagePointer + 12); log("GSP::GPU::RegisterInterruptRelayQueue (flags = %X, event handle = %X)\n", flags, eventHandle); + const auto event = kernel.getObject(eventHandle, KernelObjectType::Event); + if (event == nullptr) { // Check if interrupt event is invalid + Helpers::panic("Invalid event passed to GSP::GPU::RegisterInterruptRelayQueue"); + } else { + interruptEvent = eventHandle; + } + mem.write32(messagePointer, IPC::responseHeader(0x13, 2, 2)); mem.write32(messagePointer + 4, Result::SuccessRegisterIRQ); // First init returns a unique result mem.write32(messagePointer + 8, 0); // TODO: GSP module thread index @@ -109,6 +118,11 @@ void GPUService::requestInterrupt(GPUInterrupt type) { sharedMem[2] = 0; // Set error code to 0 sharedMem[0xC + flagIndex] = static_cast(type); // Write interrupt type to queue + + // Signal interrupt event + if (interruptEvent.has_value()) { + kernel.signalEvent(interruptEvent.value()); + } } void GPUService::writeHwRegs(u32 messagePointer) { diff --git a/src/core/services/service_manager.cpp b/src/core/services/service_manager.cpp index 0e32fb9a..091e3575 100644 --- a/src/core/services/service_manager.cpp +++ b/src/core/services/service_manager.cpp @@ -5,7 +5,7 @@ ServiceManager::ServiceManager(std::array& regs, Memory& mem, GPU& gpu, u32& currentPID, Kernel& kernel) : regs(regs), mem(mem), kernel(kernel), ac(mem), am(mem), boss(mem), apt(mem, kernel), cam(mem), cecd(mem), cfg(mem), - dsp(mem), hid(mem), frd(mem), fs(mem, kernel), gsp_gpu(mem, gpu, currentPID), gsp_lcd(mem), ldr(mem), mic(mem), + dsp(mem), hid(mem), frd(mem), fs(mem, kernel), gsp_gpu(mem, gpu, kernel, currentPID), gsp_lcd(mem), ldr(mem), mic(mem), nim(mem), ndm(mem), ptm(mem), y2r(mem, kernel) {} static constexpr int MAX_NOTIFICATION_COUNT = 16;