Fixup logic for GSP_GPU::TriggerCmdReqQueue (#177)

This commit is contained in:
PabloMK7 2024-07-12 13:22:31 +02:00 committed by GitHub
parent 4780a7134d
commit cc220928bd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 33 additions and 7 deletions

View file

@ -71,7 +71,12 @@ struct CacheFlushCommand {
/// GSP command /// GSP command
struct Command { struct Command {
union {
BitField<0, 8, CommandId> id; BitField<0, 8, CommandId> id;
BitField<8, 8, u32> unknown1;
BitField<16, 8, u32> stop;
BitField<24, 8, u32> unknown2;
};
union { union {
DmaCommand dma_request; DmaCommand dma_request;
SubmitCmdListCommand submit_gpu_cmdlist; SubmitCmdListCommand submit_gpu_cmdlist;
@ -86,6 +91,8 @@ static_assert(sizeof(Command) == 0x20, "Command struct has incorrect size");
/// GSP shared memory GX command buffer header /// GSP shared memory GX command buffer header
struct CommandBuffer { struct CommandBuffer {
static constexpr u32 STATUS_STOPPED = 0x1;
static constexpr u32 STATUS_CMD_FAILED = 0x80;
union { union {
u32 hex; u32 hex;
@ -99,6 +106,11 @@ struct CommandBuffer {
// application when writing a command to shared memory, after increasing this value // application when writing a command to shared memory, after increasing this value
// TriggerCmdReqQueue is only used if this field is value 1. // TriggerCmdReqQueue is only used if this field is value 1.
BitField<8, 8, u32> number_commands; BitField<8, 8, u32> number_commands;
// When any of the following flags are set to 1, the GSP module stops processing the
// commands in the command buffer.
BitField<16, 8, u32> status;
BitField<24, 8, u32> should_stop;
}; };
u32 unk[7]; u32 unk[7];

View file

@ -408,17 +408,31 @@ void GSP_GPU::SetLcdForceBlack(Kernel::HLERequestContext& ctx) {
void GSP_GPU::TriggerCmdReqQueue(Kernel::HLERequestContext& ctx) { void GSP_GPU::TriggerCmdReqQueue(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx); IPC::RequestParser rp(ctx);
// Iterate through each command.
auto* command_buffer = GetCommandBuffer(active_thread_id); auto* command_buffer = GetCommandBuffer(active_thread_id);
auto& gpu = system.GPU(); auto& gpu = system.GPU();
for (u32 i = 0; i < command_buffer->number_commands; i++) { while (command_buffer->number_commands) {
gpu.Debugger().GXCommandProcessed(command_buffer->commands[i]); if (command_buffer->should_stop) {
command_buffer->status.Assign(CommandBuffer::STATUS_STOPPED);
break;
}
if (command_buffer->status == CommandBuffer::STATUS_STOPPED) {
break;
}
Command command = command_buffer->commands[command_buffer->index];
// Decrease the number of commands remaining and increase the current index
command_buffer->number_commands.Assign(command_buffer->number_commands - 1);
command_buffer->index.Assign((command_buffer->index + 1) % 0xF);
gpu.Debugger().GXCommandProcessed(command);
// Decode and execute command // Decode and execute command
gpu.Execute(command_buffer->commands[i]); gpu.Execute(command);
// Indicates that command has completed if (command.stop) {
command_buffer->number_commands.Assign(command_buffer->number_commands - 1); command_buffer->should_stop.Assign(1);
}
} }
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);