diff options
| -rw-r--r-- | src/core/hle/service/gsp_gpu.cpp | 23 | ||||
| -rw-r--r-- | src/core/hw/gpu.cpp | 3 | ||||
| -rw-r--r-- | src/core/hw/gpu.h | 2 | ||||
| -rw-r--r-- | src/video_core/command_processor.cpp | 9 | ||||
| -rw-r--r-- | src/video_core/pica.h | 10 |
5 files changed, 33 insertions, 14 deletions
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp index de1bd3f61..34eabac45 100644 --- a/src/core/hle/service/gsp_gpu.cpp +++ b/src/core/hle/service/gsp_gpu.cpp | |||
| @@ -162,7 +162,8 @@ static void RegisterInterruptRelayQueue(Service::Interface* self) { | |||
| 162 | 162 | ||
| 163 | _assert_msg_(GSP, (g_interrupt_event != 0), "handle is not valid!"); | 163 | _assert_msg_(GSP, (g_interrupt_event != 0), "handle is not valid!"); |
| 164 | 164 | ||
| 165 | cmd_buff[2] = g_thread_id++; // ThreadID | 165 | cmd_buff[1] = 0x2A07; // Value verified by 3dmoo team, purpose unknown, but needed for GSP init |
| 166 | cmd_buff[2] = g_thread_id++; // Thread ID | ||
| 166 | cmd_buff[4] = g_shared_memory; // GSP shared memory | 167 | cmd_buff[4] = g_shared_memory; // GSP shared memory |
| 167 | 168 | ||
| 168 | Kernel::SignalEvent(g_interrupt_event); // TODO(bunnei): Is this correct? | 169 | Kernel::SignalEvent(g_interrupt_event); // TODO(bunnei): Is this correct? |
| @@ -172,6 +173,7 @@ static void RegisterInterruptRelayQueue(Service::Interface* self) { | |||
| 172 | * Signals that the specified interrupt type has occurred to userland code | 173 | * Signals that the specified interrupt type has occurred to userland code |
| 173 | * @param interrupt_id ID of interrupt that is being signalled | 174 | * @param interrupt_id ID of interrupt that is being signalled |
| 174 | * @todo This should probably take a thread_id parameter and only signal this thread? | 175 | * @todo This should probably take a thread_id parameter and only signal this thread? |
| 176 | * @todo This probably does not belong in the GSP module, instead move to video_core | ||
| 175 | */ | 177 | */ |
| 176 | void SignalInterrupt(InterruptId interrupt_id) { | 178 | void SignalInterrupt(InterruptId interrupt_id) { |
| 177 | if (0 == g_interrupt_event) { | 179 | if (0 == g_interrupt_event) { |
| @@ -210,6 +212,7 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { | |||
| 210 | memcpy(Memory::GetPointer(command.dma_request.dest_address), | 212 | memcpy(Memory::GetPointer(command.dma_request.dest_address), |
| 211 | Memory::GetPointer(command.dma_request.source_address), | 213 | Memory::GetPointer(command.dma_request.source_address), |
| 212 | command.dma_request.size); | 214 | command.dma_request.size); |
| 215 | SignalInterrupt(InterruptId::DMA); | ||
| 213 | break; | 216 | break; |
| 214 | 217 | ||
| 215 | // ctrulib homebrew sends all relevant command list data with this command, | 218 | // ctrulib homebrew sends all relevant command list data with this command, |
| @@ -218,13 +221,13 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { | |||
| 218 | case CommandId::SET_COMMAND_LIST_LAST: | 221 | case CommandId::SET_COMMAND_LIST_LAST: |
| 219 | { | 222 | { |
| 220 | auto& params = command.set_command_list_last; | 223 | auto& params = command.set_command_list_last; |
| 224 | |||
| 221 | WriteGPURegister(GPU_REG_INDEX(command_processor_config.address), Memory::VirtualToPhysicalAddress(params.address) >> 3); | 225 | WriteGPURegister(GPU_REG_INDEX(command_processor_config.address), Memory::VirtualToPhysicalAddress(params.address) >> 3); |
| 222 | WriteGPURegister(GPU_REG_INDEX(command_processor_config.size), params.size >> 3); | 226 | WriteGPURegister(GPU_REG_INDEX(command_processor_config.size), params.size); |
| 223 | 227 | ||
| 224 | // TODO: Not sure if we are supposed to always write this .. seems to trigger processing though | 228 | // TODO: Not sure if we are supposed to always write this .. seems to trigger processing though |
| 225 | WriteGPURegister(GPU_REG_INDEX(command_processor_config.trigger), 1); | 229 | WriteGPURegister(GPU_REG_INDEX(command_processor_config.trigger), 1); |
| 226 | 230 | ||
| 227 | SignalInterrupt(InterruptId::P3D); | ||
| 228 | break; | 231 | break; |
| 229 | } | 232 | } |
| 230 | 233 | ||
| @@ -242,6 +245,8 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { | |||
| 242 | WriteGPURegister(GPU_REG_INDEX(memory_fill_config[1].address_end), Memory::VirtualToPhysicalAddress(params.end2) >> 3); | 245 | WriteGPURegister(GPU_REG_INDEX(memory_fill_config[1].address_end), Memory::VirtualToPhysicalAddress(params.end2) >> 3); |
| 243 | WriteGPURegister(GPU_REG_INDEX(memory_fill_config[1].size), params.end2 - params.start2); | 246 | WriteGPURegister(GPU_REG_INDEX(memory_fill_config[1].size), params.end2 - params.start2); |
| 244 | WriteGPURegister(GPU_REG_INDEX(memory_fill_config[1].value), params.value2); | 247 | WriteGPURegister(GPU_REG_INDEX(memory_fill_config[1].value), params.value2); |
| 248 | |||
| 249 | SignalInterrupt(InterruptId::PSC0); | ||
| 245 | break; | 250 | break; |
| 246 | } | 251 | } |
| 247 | 252 | ||
| @@ -255,14 +260,9 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { | |||
| 255 | WriteGPURegister(GPU_REG_INDEX(display_transfer_config.flags), params.flags); | 260 | WriteGPURegister(GPU_REG_INDEX(display_transfer_config.flags), params.flags); |
| 256 | WriteGPURegister(GPU_REG_INDEX(display_transfer_config.trigger), 1); | 261 | WriteGPURegister(GPU_REG_INDEX(display_transfer_config.trigger), 1); |
| 257 | 262 | ||
| 258 | // TODO(bunnei): Signalling all of these interrupts here is totally wrong, but it seems to | 263 | // TODO(bunnei): Determine if these interrupts should be signalled here. |
| 259 | // work well enough for running demos. Need to figure out how these all work and trigger | ||
| 260 | // them correctly. | ||
| 261 | SignalInterrupt(InterruptId::PSC0); | ||
| 262 | SignalInterrupt(InterruptId::PSC1); | 264 | SignalInterrupt(InterruptId::PSC1); |
| 263 | SignalInterrupt(InterruptId::PPF); | 265 | SignalInterrupt(InterruptId::PPF); |
| 264 | SignalInterrupt(InterruptId::P3D); | ||
| 265 | SignalInterrupt(InterruptId::DMA); | ||
| 266 | 266 | ||
| 267 | // Update framebuffer information if requested | 267 | // Update framebuffer information if requested |
| 268 | for (int screen_id = 0; screen_id < 2; ++screen_id) { | 268 | for (int screen_id = 0; screen_id < 2; ++screen_id) { |
| @@ -305,6 +305,8 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { | |||
| 305 | /// This triggers handling of the GX command written to the command buffer in shared memory. | 305 | /// This triggers handling of the GX command written to the command buffer in shared memory. |
| 306 | static void TriggerCmdReqQueue(Service::Interface* self) { | 306 | static void TriggerCmdReqQueue(Service::Interface* self) { |
| 307 | 307 | ||
| 308 | DEBUG_LOG(GSP, "called"); | ||
| 309 | |||
| 308 | // Iterate through each thread's command queue... | 310 | // Iterate through each thread's command queue... |
| 309 | for (unsigned thread_id = 0; thread_id < 0x4; ++thread_id) { | 311 | for (unsigned thread_id = 0; thread_id < 0x4; ++thread_id) { |
| 310 | CommandBuffer* command_buffer = (CommandBuffer*)GetCommandBuffer(thread_id); | 312 | CommandBuffer* command_buffer = (CommandBuffer*)GetCommandBuffer(thread_id); |
| @@ -320,6 +322,9 @@ static void TriggerCmdReqQueue(Service::Interface* self) { | |||
| 320 | command_buffer->number_commands = command_buffer->number_commands - 1; | 322 | command_buffer->number_commands = command_buffer->number_commands - 1; |
| 321 | } | 323 | } |
| 322 | } | 324 | } |
| 325 | |||
| 326 | u32* cmd_buff = Service::GetCommandBuffer(); | ||
| 327 | cmd_buff[1] = 0; // No error | ||
| 323 | } | 328 | } |
| 324 | 329 | ||
| 325 | const Interface::FunctionInfo FunctionTable[] = { | 330 | const Interface::FunctionInfo FunctionTable[] = { |
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp index af5e1b39b..77557e582 100644 --- a/src/core/hw/gpu.cpp +++ b/src/core/hw/gpu.cpp | |||
| @@ -154,8 +154,7 @@ inline void Write(u32 addr, const T data) { | |||
| 154 | if (config.trigger & 1) | 154 | if (config.trigger & 1) |
| 155 | { | 155 | { |
| 156 | u32* buffer = (u32*)Memory::GetPointer(Memory::PhysicalToVirtualAddress(config.GetPhysicalAddress())); | 156 | u32* buffer = (u32*)Memory::GetPointer(Memory::PhysicalToVirtualAddress(config.GetPhysicalAddress())); |
| 157 | u32 size = config.size << 3; | 157 | Pica::CommandProcessor::ProcessCommandList(buffer, config.size); |
| 158 | Pica::CommandProcessor::ProcessCommandList(buffer, size); | ||
| 159 | } | 158 | } |
| 160 | break; | 159 | break; |
| 161 | } | 160 | } |
diff --git a/src/core/hw/gpu.h b/src/core/hw/gpu.h index 3fa7b9ccf..86cd5e680 100644 --- a/src/core/hw/gpu.h +++ b/src/core/hw/gpu.h | |||
| @@ -169,7 +169,7 @@ struct Regs { | |||
| 169 | INSERT_PADDING_WORDS(0x331); | 169 | INSERT_PADDING_WORDS(0x331); |
| 170 | 170 | ||
| 171 | struct { | 171 | struct { |
| 172 | // command list size | 172 | // command list size (in bytes) |
| 173 | u32 size; | 173 | u32 size; |
| 174 | 174 | ||
| 175 | INSERT_PADDING_WORDS(0x1); | 175 | INSERT_PADDING_WORDS(0x1); |
diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp index 298b04c51..431139cc2 100644 --- a/src/video_core/command_processor.cpp +++ b/src/video_core/command_processor.cpp | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include "pica.h" | 8 | #include "pica.h" |
| 9 | #include "primitive_assembly.h" | 9 | #include "primitive_assembly.h" |
| 10 | #include "vertex_shader.h" | 10 | #include "vertex_shader.h" |
| 11 | #include "core/hle/service/gsp_gpu.h" | ||
| 11 | 12 | ||
| 12 | #include "debug_utils/debug_utils.h" | 13 | #include "debug_utils/debug_utils.h" |
| 13 | 14 | ||
| @@ -40,6 +41,11 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { | |||
| 40 | DebugUtils::OnPicaRegWrite(id, registers[id]); | 41 | DebugUtils::OnPicaRegWrite(id, registers[id]); |
| 41 | 42 | ||
| 42 | switch(id) { | 43 | switch(id) { |
| 44 | // Trigger IRQ | ||
| 45 | case PICA_REG_INDEX(trigger_irq): | ||
| 46 | GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::P3D); | ||
| 47 | return; | ||
| 48 | |||
| 43 | // It seems like these trigger vertex rendering | 49 | // It seems like these trigger vertex rendering |
| 44 | case PICA_REG_INDEX(trigger_draw): | 50 | case PICA_REG_INDEX(trigger_draw): |
| 45 | case PICA_REG_INDEX(trigger_draw_indexed): | 51 | case PICA_REG_INDEX(trigger_draw_indexed): |
| @@ -272,8 +278,9 @@ static std::ptrdiff_t ExecuteCommandBlock(const u32* first_command_word) { | |||
| 272 | 278 | ||
| 273 | void ProcessCommandList(const u32* list, u32 size) { | 279 | void ProcessCommandList(const u32* list, u32 size) { |
| 274 | u32* read_pointer = (u32*)list; | 280 | u32* read_pointer = (u32*)list; |
| 281 | u32 list_length = size / sizeof(u32); | ||
| 275 | 282 | ||
| 276 | while (read_pointer < list + size) { | 283 | while (read_pointer < list + list_length) { |
| 277 | read_pointer += ExecuteCommandBlock(read_pointer); | 284 | read_pointer += ExecuteCommandBlock(read_pointer); |
| 278 | } | 285 | } |
| 279 | } | 286 | } |
diff --git a/src/video_core/pica.h b/src/video_core/pica.h index e7ca38978..8bac178ca 100644 --- a/src/video_core/pica.h +++ b/src/video_core/pica.h | |||
| @@ -45,10 +45,16 @@ struct Regs { | |||
| 45 | #define INSERT_PADDING_WORDS_HELPER2(x, y) INSERT_PADDING_WORDS_HELPER1(x, y) | 45 | #define INSERT_PADDING_WORDS_HELPER2(x, y) INSERT_PADDING_WORDS_HELPER1(x, y) |
| 46 | #define INSERT_PADDING_WORDS(num_words) u32 INSERT_PADDING_WORDS_HELPER2(pad, __LINE__)[(num_words)]; | 46 | #define INSERT_PADDING_WORDS(num_words) u32 INSERT_PADDING_WORDS_HELPER2(pad, __LINE__)[(num_words)]; |
| 47 | 47 | ||
| 48 | INSERT_PADDING_WORDS(0x41); | 48 | INSERT_PADDING_WORDS(0x10); |
| 49 | |||
| 50 | u32 trigger_irq; | ||
| 51 | |||
| 52 | INSERT_PADDING_WORDS(0x30); | ||
| 49 | 53 | ||
| 50 | BitField<0, 24, u32> viewport_size_x; | 54 | BitField<0, 24, u32> viewport_size_x; |
| 55 | |||
| 51 | INSERT_PADDING_WORDS(0x1); | 56 | INSERT_PADDING_WORDS(0x1); |
| 57 | |||
| 52 | BitField<0, 24, u32> viewport_size_y; | 58 | BitField<0, 24, u32> viewport_size_y; |
| 53 | 59 | ||
| 54 | INSERT_PADDING_WORDS(0x9); | 60 | INSERT_PADDING_WORDS(0x9); |
| @@ -544,6 +550,7 @@ struct Regs { | |||
| 544 | map.insert({i, #name + std::string("+") + std::to_string(i-PICA_REG_INDEX(name))}); \ | 550 | map.insert({i, #name + std::string("+") + std::to_string(i-PICA_REG_INDEX(name))}); \ |
| 545 | } while(false) | 551 | } while(false) |
| 546 | 552 | ||
| 553 | ADD_FIELD(trigger_irq); | ||
| 547 | ADD_FIELD(viewport_size_x); | 554 | ADD_FIELD(viewport_size_x); |
| 548 | ADD_FIELD(viewport_size_y); | 555 | ADD_FIELD(viewport_size_y); |
| 549 | ADD_FIELD(viewport_depth_range); | 556 | ADD_FIELD(viewport_depth_range); |
| @@ -607,6 +614,7 @@ private: | |||
| 607 | #ifndef _MSC_VER | 614 | #ifndef _MSC_VER |
| 608 | #define ASSERT_REG_POSITION(field_name, position) static_assert(offsetof(Regs, field_name) == position * 4, "Field "#field_name" has invalid position") | 615 | #define ASSERT_REG_POSITION(field_name, position) static_assert(offsetof(Regs, field_name) == position * 4, "Field "#field_name" has invalid position") |
| 609 | 616 | ||
| 617 | ASSERT_REG_POSITION(trigger_irq, 0x10); | ||
| 610 | ASSERT_REG_POSITION(viewport_size_x, 0x41); | 618 | ASSERT_REG_POSITION(viewport_size_x, 0x41); |
| 611 | ASSERT_REG_POSITION(viewport_size_y, 0x43); | 619 | ASSERT_REG_POSITION(viewport_size_y, 0x43); |
| 612 | ASSERT_REG_POSITION(viewport_depth_range, 0x4d); | 620 | ASSERT_REG_POSITION(viewport_depth_range, 0x4d); |