mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-19 20:19:13 +12:00
[GPU] Start implementing commands
This commit is contained in:
parent
fef585ebb3
commit
8692e7fc6b
11 changed files with 132 additions and 21 deletions
|
@ -1,13 +1,22 @@
|
|||
#include "services/gsp_gpu.hpp"
|
||||
|
||||
namespace GPUCommands {
|
||||
// Commands used with SendSyncRequest targetted to the GSP::GPU service
|
||||
namespace ServiceCommands {
|
||||
enum : u32 {
|
||||
AcquireRight = 0x00160042,
|
||||
RegisterInterruptRelayQueue = 0x00130042,
|
||||
WriteHwRegs = 0x00010082,
|
||||
WriteHwRegsWithMask = 0x00020084,
|
||||
FlushDataCache = 0x00080082,
|
||||
SetLCDForceBlack = 0x000B0040
|
||||
SetLCDForceBlack = 0x000B0040,
|
||||
TriggerCmdReqQueue = 0x000C0000
|
||||
};
|
||||
}
|
||||
|
||||
// Commands written to shared memory and processed by TriggerCmdReqQueue
|
||||
namespace GPUCommands {
|
||||
enum : u32 {
|
||||
MemoryFill = 2
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -26,12 +35,13 @@ void GPUService::reset() {
|
|||
void GPUService::handleSyncRequest(u32 messagePointer) {
|
||||
const u32 command = mem.read32(messagePointer);
|
||||
switch (command) {
|
||||
case GPUCommands::AcquireRight: acquireRight(messagePointer); break;
|
||||
case GPUCommands::FlushDataCache: flushDataCache(messagePointer); break;
|
||||
case GPUCommands::RegisterInterruptRelayQueue: registerInterruptRelayQueue(messagePointer); break;
|
||||
case GPUCommands::SetLCDForceBlack: setLCDForceBlack(messagePointer); break;
|
||||
case GPUCommands::WriteHwRegs: writeHwRegs(messagePointer); break;
|
||||
case GPUCommands::WriteHwRegsWithMask: writeHwRegsWithMask(messagePointer); break;
|
||||
case ServiceCommands::AcquireRight: acquireRight(messagePointer); break;
|
||||
case ServiceCommands::FlushDataCache: flushDataCache(messagePointer); break;
|
||||
case ServiceCommands::RegisterInterruptRelayQueue: registerInterruptRelayQueue(messagePointer); break;
|
||||
case ServiceCommands::SetLCDForceBlack: setLCDForceBlack(messagePointer); break;
|
||||
case ServiceCommands::TriggerCmdReqQueue: triggerCmdReqQueue(messagePointer); break;
|
||||
case ServiceCommands::WriteHwRegs: writeHwRegs(messagePointer); break;
|
||||
case ServiceCommands::WriteHwRegsWithMask: writeHwRegsWithMask(messagePointer); break;
|
||||
; default: Helpers::panic("GPU service requested. Command: %08X\n", command);
|
||||
}
|
||||
}
|
||||
|
@ -58,6 +68,11 @@ void GPUService::acquireRight(u32 messagePointer) {
|
|||
// What is the "GSP module thread index" meant to be?
|
||||
// How does the shared memory handle thing work?
|
||||
void GPUService::registerInterruptRelayQueue(u32 messagePointer) {
|
||||
// Detect if this function is called a 2nd time because we'll likely need to impl threads properly for the GSP
|
||||
static bool beenHere = false;
|
||||
if (beenHere) Helpers::panic("RegisterInterruptRelayQueue called a second time. Need to implement GSP threads properly");
|
||||
beenHere = true;
|
||||
|
||||
const u32 flags = mem.read32(messagePointer + 4);
|
||||
const u32 eventHandle = mem.read32(messagePointer + 12);
|
||||
printf("GSP::GPU::RegisterInterruptRelayQueue (flags = %X, event handle = %X)\n", flags, eventHandle);
|
||||
|
@ -73,7 +88,7 @@ void GPUService::requestInterrupt(GPUInterrupt type) {
|
|||
return;
|
||||
}
|
||||
|
||||
u8 index = sharedMem[0];
|
||||
u8 index = sharedMem[0]; // The interrupt block is normally located at sharedMem + processGSPIndex*0x40
|
||||
u8& interruptCount = sharedMem[1];
|
||||
u8 flagIndex = (index + interruptCount) % 0x34;
|
||||
interruptCount++;
|
||||
|
@ -168,4 +183,64 @@ void GPUService::setLCDForceBlack(u32 messagePointer) {
|
|||
}
|
||||
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void GPUService::triggerCmdReqQueue(u32 messagePointer) {
|
||||
processCommands();
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
using namespace std::chrono_literals;
|
||||
void GPUService::processCommands() {
|
||||
if (sharedMem == nullptr) [[unlikely]] { // Shared memory hasn't been set up yet
|
||||
return;
|
||||
}
|
||||
|
||||
constexpr int threadCount = 1; // TODO: More than 1 thread can have GSP commands at a time
|
||||
for (int t = 0; t < threadCount; t++) {
|
||||
u8* cmdBuffer = &sharedMem[0x800 + t * 0x200];
|
||||
u8& commandsLeft = cmdBuffer[1];
|
||||
// Commands start at byte 0x20 of the command buffer, each being 0x20 bytes long
|
||||
u32* cmd = reinterpret_cast<u32*>(&cmdBuffer[0x20]);
|
||||
|
||||
printf("Processing %d GPU commands\n", commandsLeft);
|
||||
std::this_thread::sleep_for(1000ms);
|
||||
|
||||
while (commandsLeft != 0) {
|
||||
u32 cmdID = cmd[0] & 0xff;
|
||||
switch (cmdID) {
|
||||
case GPUCommands::MemoryFill: memoryFill(cmd); break;
|
||||
default: Helpers::panic("GSP::GPU::ProcessCommands: Unknown cmd ID %d", cmdID);
|
||||
}
|
||||
|
||||
commandsLeft--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fill 2 GPU framebuffers, buf0 and buf1, using a specific word value
|
||||
void GPUService::memoryFill(u32* cmd) {
|
||||
u32 control = cmd[7];
|
||||
|
||||
// buf0 parameters
|
||||
u32 start0 = cmd[1]; // Start address for the fill. If 0, don't fill anything
|
||||
u32 value0 = cmd[2]; // Value to fill the framebuffer with
|
||||
u32 end0 = cmd[3]; // End address for the fill
|
||||
u32 control0 = control & 0xffff;
|
||||
|
||||
// buf1 parameters
|
||||
u32 start1 = cmd[4];
|
||||
u32 value1 = cmd[5];
|
||||
u32 end1 = cmd[6];
|
||||
u32 control1 = control >> 16;
|
||||
|
||||
if (start0 != 0) {
|
||||
gpu.clearBuffer(start0, end0, value0, control0);
|
||||
}
|
||||
|
||||
if (start1 != 0) {
|
||||
gpu.clearBuffer(start1, end1, value1, control1);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue