Panda3DS/include/services/gsp_gpu.hpp
wheremyfoodat dc80828397
Fix typo (#680)
Co-authored-by: Noumi <139501014+noumidev@users.noreply.github.com>
2024-12-10 18:52:53 +02:00

124 lines
No EOL
3.8 KiB
C++

#pragma once
#include <cstring>
#include <optional>
#include "PICA/gpu.hpp"
#include "helpers.hpp"
#include "kernel_types.hpp"
#include "logger.hpp"
#include "memory.hpp"
#include "result/result.hpp"
enum class GPUInterrupt : u8 {
PSC0 = 0, // Memory fill completed
PSC1 = 1, // ?
VBlank0 = 2, // ?
VBlank1 = 3, // ?
PPF = 4, // Display transfer finished
P3D = 5, // Command list processing finished
DMA = 6
};
// More circular dependencies
class Kernel;
class GPUService {
using Handle = HorizonHandle;
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<Handle> interruptEvent;
// Number of threads registered via RegisterInterruptRelayQueue
u32 gspThreadCount = 0;
MAKE_LOG_FUNCTION(log, gspGPULogger)
void processCommandBuffer();
struct FramebufferInfo {
u32 activeFb;
u32 leftFramebufferVaddr;
u32 rightFramebufferVaddr;
u32 stride;
u32 format;
u32 displayFb;
u32 attribute;
};
static_assert(sizeof(FramebufferInfo) == 28, "GSP::GPU::FramebufferInfo has the wrong size");
struct FramebufferUpdate {
u8 index;
u8 dirtyFlag;
u16 pad0;
std::array<FramebufferInfo, 2> framebufferInfo;
u32 pad1;
};
static_assert(sizeof(FramebufferUpdate) == 64, "GSP::GPU::FramebufferUpdate has the wrong size");
// Used for saving and restoring GPU state via ImportDisplayCaptureInfo
struct CaptureInfo {
u32 leftFramebuffer; // Left framebuffer VA
u32 rightFramebuffer; // Right framebuffer VA (Top screen only)
u32 format;
u32 stride;
};
static_assert(sizeof(CaptureInfo) == 16, "GSP::GPU::CaptureInfo has the wrong size");
// Service commands
void acquireRight(u32 messagePointer);
void flushDataCache(u32 messagePointer);
void invalidateDataCache(u32 messagePointer);
void importDisplayCaptureInfo(u32 messagePointer);
void readHwRegs(u32 messagePointer);
void registerInterruptRelayQueue(u32 messagePointer);
void releaseRight(u32 messagePointer);
void restoreVramSysArea(u32 messagePointer);
void saveVramSysArea(u32 messagePointer);
void setAxiConfigQoSMode(u32 messagePointer);
void setBufferSwap(u32 messagePointer);
void setInternalPriorities(u32 messagePointer);
void setLCDForceBlack(u32 messagePointer);
void storeDataCache(u32 messagePointer);
void triggerCmdReqQueue(u32 messagePointer);
void writeHwRegs(u32 messagePointer);
void writeHwRegsWithMask(u32 messagePointer);
// GSP commands processed via TriggerCmdReqQueue
void processCommandList(u32* cmd);
void memoryFill(u32* cmd);
void triggerDisplayTransfer(u32* cmd);
void triggerDMARequest(u32* cmd);
void triggerTextureCopy(u32* cmd);
void flushCacheRegions(u32* cmd);
void setBufferSwapImpl(u32 screen_id, const FramebufferInfo& info);
// Get the framebuffer info in shared memory for a given screen
FramebufferUpdate* getFramebufferInfo(int screen) {
// TODO: Offset depends on GSP thread being triggered
return reinterpret_cast<FramebufferUpdate*>(&sharedMem[0x200 + screen * sizeof(FramebufferUpdate)]);
}
FramebufferUpdate* getTopFramebufferInfo() { return getFramebufferInfo(0); }
FramebufferUpdate* getBottomFramebufferInfo() { return getFramebufferInfo(1); }
public:
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);
void setSharedMem(u8* ptr) {
sharedMem = ptr;
if (ptr != nullptr) { // Zero-fill shared memory in case the process tries to read stale service data or vice versa
std::memset(ptr, 0, 0x1000);
}
}
};