diff options
| author | 2014-07-22 23:26:28 -0400 | |
|---|---|---|
| committer | 2014-08-05 23:58:00 -0400 | |
| commit | 4e9f305ed214ef0fbffd83042c86f41cd233ec3b (patch) | |
| tree | 51787c34f01a244d28ee3b41bdbfc0b93c38bbff /src/core | |
| parent | GSP: Removed unnecessary GX_FinishCommand function. (diff) | |
| download | yuzu-4e9f305ed214ef0fbffd83042c86f41cd233ec3b.tar.gz yuzu-4e9f305ed214ef0fbffd83042c86f41cd233ec3b.tar.xz yuzu-4e9f305ed214ef0fbffd83042c86f41cd233ec3b.zip | |
GSP: Removed dumb GX prefixes to functions/structs in GSP namespace.
- Various other cleanups.
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/hle/service/gsp.cpp | 88 | ||||
| -rw-r--r-- | src/core/hle/service/gsp.h | 67 | ||||
| -rw-r--r-- | src/core/hw/gpu.cpp | 4 |
3 files changed, 80 insertions, 79 deletions
diff --git a/src/core/hle/service/gsp.cpp b/src/core/hle/service/gsp.cpp index bf85b1d86..8a3011e34 100644 --- a/src/core/hle/service/gsp.cpp +++ b/src/core/hle/service/gsp.cpp | |||
| @@ -11,53 +11,13 @@ | |||
| 11 | #include "core/hle/kernel/event.h" | 11 | #include "core/hle/kernel/event.h" |
| 12 | #include "core/hle/kernel/shared_memory.h" | 12 | #include "core/hle/kernel/shared_memory.h" |
| 13 | #include "core/hle/service/gsp.h" | 13 | #include "core/hle/service/gsp.h" |
| 14 | |||
| 15 | #include "core/hw/gpu.h" | 14 | #include "core/hw/gpu.h" |
| 16 | 15 | ||
| 17 | #include "video_core/gpu_debugger.h" | 16 | #include "video_core/gpu_debugger.h" |
| 18 | 17 | ||
| 19 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 20 | |||
| 21 | // Main graphics debugger object - TODO: Here is probably not the best place for this | 18 | // Main graphics debugger object - TODO: Here is probably not the best place for this |
| 22 | GraphicsDebugger g_debugger; | 19 | GraphicsDebugger g_debugger; |
| 23 | 20 | ||
| 24 | /// GSP thread interrupt queue header | ||
| 25 | struct GX_InterruptQueue { | ||
| 26 | union { | ||
| 27 | u32 hex; | ||
| 28 | |||
| 29 | // Index of last interrupt in the queue | ||
| 30 | BitField<0,8,u32> index; | ||
| 31 | |||
| 32 | // Number of interrupts remaining to be processed by the userland code | ||
| 33 | BitField<8,8,u32> number_interrupts; | ||
| 34 | |||
| 35 | // Error code - zero on success, otherwise an error has occurred | ||
| 36 | BitField<16,8,u32> error_code; | ||
| 37 | }; | ||
| 38 | |||
| 39 | u32 unk0; | ||
| 40 | u32 unk1; | ||
| 41 | |||
| 42 | GSP_GPU::GXInterruptId slot[0x34]; ///< Interrupt ID slots | ||
| 43 | }; | ||
| 44 | |||
| 45 | /// GSP shared memory GX command buffer header | ||
| 46 | union GX_CmdBufferHeader { | ||
| 47 | u32 hex; | ||
| 48 | |||
| 49 | // Current command index. This index is updated by GSP module after loading the command data, | ||
| 50 | // right before the command is processed. When this index is updated by GSP module, the total | ||
| 51 | // commands field is decreased by one as well. | ||
| 52 | BitField<0,8,u32> index; | ||
| 53 | |||
| 54 | // Total commands to process, must not be value 0 when GSP module handles commands. This must be | ||
| 55 | // <=15 when writing a command to shared memory. This is incremented by the application when | ||
| 56 | // writing a command to shared memory, after increasing this value TriggerCmdReqQueue is only | ||
| 57 | // used if this field is value 1. | ||
| 58 | BitField<8,8,u32> number_commands; | ||
| 59 | }; | ||
| 60 | |||
| 61 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 21 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 62 | // Namespace GSP_GPU | 22 | // Namespace GSP_GPU |
| 63 | 23 | ||
| @@ -69,15 +29,15 @@ Handle g_shared_memory = 0; | |||
| 69 | u32 g_thread_id = 1; | 29 | u32 g_thread_id = 1; |
| 70 | 30 | ||
| 71 | /// Gets a pointer to the start (header) of a command buffer in GSP shared memory | 31 | /// Gets a pointer to the start (header) of a command buffer in GSP shared memory |
| 72 | static inline u8* GX_GetCmdBufferPointer(u32 thread_id, u32 offset=0) { | 32 | static inline u8* GetCmdBufferPointer(u32 thread_id, u32 offset=0) { |
| 73 | if (0 == g_shared_memory) return nullptr; | 33 | if (0 == g_shared_memory) return nullptr; |
| 74 | 34 | ||
| 75 | return Kernel::GetSharedMemoryPointer(g_shared_memory, 0x800 + (thread_id * 0x200) + offset); | 35 | return Kernel::GetSharedMemoryPointer(g_shared_memory, 0x800 + (thread_id * 0x200) + offset); |
| 76 | } | 36 | } |
| 77 | 37 | ||
| 78 | /// Gets a pointer to the start (header) of a command buffer in GSP shared memory | 38 | /// Gets a pointer to the start (header) of a command buffer in GSP shared memory |
| 79 | static inline GX_InterruptQueue* GetInterruptQueue(u32 thread_id) { | 39 | static inline InterruptQueue* GetInterruptQueue(u32 thread_id) { |
| 80 | return (GX_InterruptQueue*)Kernel::GetSharedMemoryPointer(g_shared_memory, sizeof(GX_InterruptQueue) * thread_id); | 40 | return (InterruptQueue*)Kernel::GetSharedMemoryPointer(g_shared_memory, sizeof(InterruptQueue) * thread_id); |
| 81 | } | 41 | } |
| 82 | 42 | ||
| 83 | /// Write a GSP GPU hardware register | 43 | /// Write a GSP GPU hardware register |
| @@ -166,7 +126,7 @@ void RegisterInterruptRelayQueue(Service::Interface* self) { | |||
| 166 | * Signals that the specified interrupt type has occurred to userland code | 126 | * Signals that the specified interrupt type has occurred to userland code |
| 167 | * @param interrupt_id ID of interrupt that is being signalled | 127 | * @param interrupt_id ID of interrupt that is being signalled |
| 168 | */ | 128 | */ |
| 169 | void SignalInterrupt(GXInterruptId interrupt_id) { | 129 | void SignalInterrupt(InterruptId interrupt_id) { |
| 170 | if (0 == GSP_GPU::g_event) { | 130 | if (0 == GSP_GPU::g_event) { |
| 171 | WARN_LOG(GSP, "cannot synchronize until GSP event has been created!"); | 131 | WARN_LOG(GSP, "cannot synchronize until GSP event has been created!"); |
| 172 | return; | 132 | return; |
| @@ -176,7 +136,7 @@ void SignalInterrupt(GXInterruptId interrupt_id) { | |||
| 176 | return; | 136 | return; |
| 177 | } | 137 | } |
| 178 | for (int thread_id = 0; thread_id < 0x4; ++thread_id) { | 138 | for (int thread_id = 0; thread_id < 0x4; ++thread_id) { |
| 179 | GX_InterruptQueue* interrupt_queue = GetInterruptQueue(thread_id); | 139 | InterruptQueue* interrupt_queue = GetInterruptQueue(thread_id); |
| 180 | interrupt_queue->number_interrupts = interrupt_queue->number_interrupts + 1; | 140 | interrupt_queue->number_interrupts = interrupt_queue->number_interrupts + 1; |
| 181 | 141 | ||
| 182 | u8 next = interrupt_queue->index; | 142 | u8 next = interrupt_queue->index; |
| @@ -190,24 +150,24 @@ void SignalInterrupt(GXInterruptId interrupt_id) { | |||
| 190 | } | 150 | } |
| 191 | 151 | ||
| 192 | /// Executes the next GSP command | 152 | /// Executes the next GSP command |
| 193 | void ExecuteCommand(int thread_id, int command_index) { | 153 | void ExecuteCommand(u32 thread_id, u32 command_index) { |
| 194 | 154 | ||
| 195 | // Utility function to convert register ID to address | 155 | // Utility function to convert register ID to address |
| 196 | auto WriteGPURegister = [](u32 id, u32 data) { | 156 | auto WriteGPURegister = [](u32 id, u32 data) { |
| 197 | GPU::Write<u32>(0x1EF00000 + 4 * id, data); | 157 | GPU::Write<u32>(0x1EF00000 + 4 * id, data); |
| 198 | }; | 158 | }; |
| 199 | 159 | ||
| 200 | GX_CmdBufferHeader* header = (GX_CmdBufferHeader*)GX_GetCmdBufferPointer(thread_id); | 160 | CmdBufferHeader* header = (CmdBufferHeader*)GetCmdBufferPointer(thread_id); |
| 201 | auto& command = *(const GXCommand*)GX_GetCmdBufferPointer(thread_id, (command_index + 1) * 0x20); | 161 | auto& command = *(const Command*)GetCmdBufferPointer(thread_id, (command_index + 1) * 0x20); |
| 202 | 162 | ||
| 203 | g_debugger.GXCommandProcessed(GX_GetCmdBufferPointer(thread_id, 0x20 + (header->index * 0x20))); | 163 | g_debugger.GXCommandProcessed(GetCmdBufferPointer(thread_id, 0x20 + (header->index * 0x20))); |
| 204 | 164 | ||
| 205 | NOTICE_LOG(GSP, "decoding command 0x%08X", (int)command.id.Value()); | 165 | NOTICE_LOG(GSP, "decoding command 0x%08X", (int)command.id.Value()); |
| 206 | 166 | ||
| 207 | switch (command.id) { | 167 | switch (command.id) { |
| 208 | 168 | ||
| 209 | // GX request DMA - typically used for copying memory from GSP heap to VRAM | 169 | // GX request DMA - typically used for copying memory from GSP heap to VRAM |
| 210 | case GXCommandId::REQUEST_DMA: | 170 | case CommandId::REQUEST_DMA: |
| 211 | memcpy(Memory::GetPointer(command.dma_request.dest_address), | 171 | memcpy(Memory::GetPointer(command.dma_request.dest_address), |
| 212 | Memory::GetPointer(command.dma_request.source_address), | 172 | Memory::GetPointer(command.dma_request.source_address), |
| 213 | command.dma_request.size); | 173 | command.dma_request.size); |
| @@ -216,7 +176,7 @@ void ExecuteCommand(int thread_id, int command_index) { | |||
| 216 | // ctrulib homebrew sends all relevant command list data with this command, | 176 | // ctrulib homebrew sends all relevant command list data with this command, |
| 217 | // hence we do all "interesting" stuff here and do nothing in SET_COMMAND_LIST_FIRST. | 177 | // hence we do all "interesting" stuff here and do nothing in SET_COMMAND_LIST_FIRST. |
| 218 | // TODO: This will need some rework in the future. | 178 | // TODO: This will need some rework in the future. |
| 219 | case GXCommandId::SET_COMMAND_LIST_LAST: | 179 | case CommandId::SET_COMMAND_LIST_LAST: |
| 220 | { | 180 | { |
| 221 | auto& params = command.set_command_list_last; | 181 | auto& params = command.set_command_list_last; |
| 222 | WriteGPURegister(GPU::Regs::CommandProcessor + 2, params.address >> 3); | 182 | WriteGPURegister(GPU::Regs::CommandProcessor + 2, params.address >> 3); |
| @@ -228,13 +188,13 @@ void ExecuteCommand(int thread_id, int command_index) { | |||
| 228 | g_debugger.CommandListCalled(params.address, | 188 | g_debugger.CommandListCalled(params.address, |
| 229 | (u32*)Memory::GetPointer(params.address), | 189 | (u32*)Memory::GetPointer(params.address), |
| 230 | params.size); | 190 | params.size); |
| 231 | SignalInterrupt(GXInterruptId::P3D); | 191 | SignalInterrupt(InterruptId::P3D); |
| 232 | break; | 192 | break; |
| 233 | } | 193 | } |
| 234 | 194 | ||
| 235 | // It's assumed that the two "blocks" behave equivalently. | 195 | // It's assumed that the two "blocks" behave equivalently. |
| 236 | // Presumably this is done simply to allow two memory fills to run in parallel. | 196 | // Presumably this is done simply to allow two memory fills to run in parallel. |
| 237 | case GXCommandId::SET_MEMORY_FILL: | 197 | case CommandId::SET_MEMORY_FILL: |
| 238 | { | 198 | { |
| 239 | auto& params = command.memory_fill; | 199 | auto& params = command.memory_fill; |
| 240 | WriteGPURegister(GPU::Regs::MemoryFill, params.start1 >> 3); | 200 | WriteGPURegister(GPU::Regs::MemoryFill, params.start1 >> 3); |
| @@ -250,18 +210,18 @@ void ExecuteCommand(int thread_id, int command_index) { | |||
| 250 | } | 210 | } |
| 251 | 211 | ||
| 252 | // TODO: Check if texture copies are implemented correctly.. | 212 | // TODO: Check if texture copies are implemented correctly.. |
| 253 | case GXCommandId::SET_DISPLAY_TRANSFER: | 213 | case CommandId::SET_DISPLAY_TRANSFER: |
| 254 | // TODO(bunnei): Signalling all of these interrupts here is totally wrong, but it seems to | 214 | // TODO(bunnei): Signalling all of these interrupts here is totally wrong, but it seems to |
| 255 | // work well enough for running demos. Need to figure out how these all work and trigger | 215 | // work well enough for running demos. Need to figure out how these all work and trigger |
| 256 | // them correctly. | 216 | // them correctly. |
| 257 | SignalInterrupt(GXInterruptId::PSC0); | 217 | SignalInterrupt(InterruptId::PSC0); |
| 258 | SignalInterrupt(GXInterruptId::PSC1); | 218 | SignalInterrupt(InterruptId::PSC1); |
| 259 | SignalInterrupt(GXInterruptId::PPF); | 219 | SignalInterrupt(InterruptId::PPF); |
| 260 | SignalInterrupt(GXInterruptId::P3D); | 220 | SignalInterrupt(InterruptId::P3D); |
| 261 | SignalInterrupt(GXInterruptId::DMA); | 221 | SignalInterrupt(InterruptId::DMA); |
| 262 | break; | 222 | break; |
| 263 | 223 | ||
| 264 | case GXCommandId::SET_TEXTURE_COPY: | 224 | case CommandId::SET_TEXTURE_COPY: |
| 265 | { | 225 | { |
| 266 | auto& params = command.image_copy; | 226 | auto& params = command.image_copy; |
| 267 | WriteGPURegister(GPU::Regs::DisplayTransfer, params.in_buffer_address >> 3); | 227 | WriteGPURegister(GPU::Regs::DisplayTransfer, params.in_buffer_address >> 3); |
| @@ -278,7 +238,7 @@ void ExecuteCommand(int thread_id, int command_index) { | |||
| 278 | 238 | ||
| 279 | // TODO: Figure out what exactly SET_COMMAND_LIST_FIRST and SET_COMMAND_LIST_LAST | 239 | // TODO: Figure out what exactly SET_COMMAND_LIST_FIRST and SET_COMMAND_LIST_LAST |
| 280 | // are supposed to do. | 240 | // are supposed to do. |
| 281 | case GXCommandId::SET_COMMAND_LIST_FIRST: | 241 | case CommandId::SET_COMMAND_LIST_FIRST: |
| 282 | { | 242 | { |
| 283 | break; | 243 | break; |
| 284 | } | 244 | } |
| @@ -294,11 +254,11 @@ void ExecuteCommand(int thread_id, int command_index) { | |||
| 294 | void TriggerCmdReqQueue(Service::Interface* self) { | 254 | void TriggerCmdReqQueue(Service::Interface* self) { |
| 295 | 255 | ||
| 296 | // Iterate through each thread's command queue... | 256 | // Iterate through each thread's command queue... |
| 297 | for (int thread_id = 0; thread_id < 0x4; ++thread_id) { | 257 | for (u32 thread_id = 0; thread_id < 0x4; ++thread_id) { |
| 298 | GX_CmdBufferHeader* header = (GX_CmdBufferHeader*)GX_GetCmdBufferPointer(thread_id); | 258 | CmdBufferHeader* header = (CmdBufferHeader*)GetCmdBufferPointer(thread_id); |
| 299 | 259 | ||
| 300 | // Iterate through each command... | 260 | // Iterate through each command... |
| 301 | for (int command_index = 0; command_index < header->number_commands; ++command_index) { | 261 | for (u32 command_index = 0; command_index < header->number_commands; ++command_index) { |
| 302 | ExecuteCommand(thread_id, command_index); | 262 | ExecuteCommand(thread_id, command_index); |
| 303 | } | 263 | } |
| 304 | } | 264 | } |
diff --git a/src/core/hle/service/gsp.h b/src/core/hle/service/gsp.h index 5a649d2df..66b99e94a 100644 --- a/src/core/hle/service/gsp.h +++ b/src/core/hle/service/gsp.h | |||
| @@ -12,7 +12,19 @@ | |||
| 12 | 12 | ||
| 13 | namespace GSP_GPU { | 13 | namespace GSP_GPU { |
| 14 | 14 | ||
| 15 | enum class GXCommandId : u32 { | 15 | /// GSP interrupt ID |
| 16 | enum class InterruptId : u8 { | ||
| 17 | PSC0 = 0x00, | ||
| 18 | PSC1 = 0x01, | ||
| 19 | PDC0 = 0x02, // Seems called every vertical screen line | ||
| 20 | PDC1 = 0x03, // Seems called every frame | ||
| 21 | PPF = 0x04, | ||
| 22 | P3D = 0x05, | ||
| 23 | DMA = 0x06, | ||
| 24 | }; | ||
| 25 | |||
| 26 | /// GSP command ID | ||
| 27 | enum class CommandId : u32 { | ||
| 16 | REQUEST_DMA = 0x00, | 28 | REQUEST_DMA = 0x00, |
| 17 | SET_COMMAND_LIST_LAST = 0x01, | 29 | SET_COMMAND_LIST_LAST = 0x01, |
| 18 | 30 | ||
| @@ -29,18 +41,47 @@ enum class GXCommandId : u32 { | |||
| 29 | SET_COMMAND_LIST_FIRST = 0x05, | 41 | SET_COMMAND_LIST_FIRST = 0x05, |
| 30 | }; | 42 | }; |
| 31 | 43 | ||
| 32 | enum class GXInterruptId : u8 { | 44 | /// GSP thread interrupt queue header |
| 33 | PSC0 = 0x00, | 45 | struct InterruptQueue { |
| 34 | PSC1 = 0x01, | 46 | union { |
| 35 | PDC0 = 0x02, // Seems called every vertical screen line | 47 | u32 hex; |
| 36 | PDC1 = 0x03, // Seems called every frame | 48 | |
| 37 | PPF = 0x04, | 49 | // Index of last interrupt in the queue |
| 38 | P3D = 0x05, | 50 | BitField<0,8,u32> index; |
| 39 | DMA = 0x06, | 51 | |
| 52 | // Number of interrupts remaining to be processed by the userland code | ||
| 53 | BitField<8,8,u32> number_interrupts; | ||
| 54 | |||
| 55 | // Error code - zero on success, otherwise an error has occurred | ||
| 56 | BitField<16,8,u32> error_code; | ||
| 57 | }; | ||
| 58 | |||
| 59 | u32 unk0; | ||
| 60 | u32 unk1; | ||
| 61 | |||
| 62 | InterruptId slot[0x34]; ///< Interrupt ID slots | ||
| 63 | }; | ||
| 64 | static_assert(sizeof(InterruptQueue) == 0x40, "InterruptQueue struct has incorrect size"); | ||
| 65 | |||
| 66 | /// GSP shared memory GX command buffer header | ||
| 67 | union CmdBufferHeader { | ||
| 68 | u32 hex; | ||
| 69 | |||
| 70 | // Current command index. This index is updated by GSP module after loading the command data, | ||
| 71 | // right before the command is processed. When this index is updated by GSP module, the total | ||
| 72 | // commands field is decreased by one as well. | ||
| 73 | BitField<0,8,u32> index; | ||
| 74 | |||
| 75 | // Total commands to process, must not be value 0 when GSP module handles commands. This must be | ||
| 76 | // <=15 when writing a command to shared memory. This is incremented by the application when | ||
| 77 | // writing a command to shared memory, after increasing this value TriggerCmdReqQueue is only | ||
| 78 | // used if this field is value 1. | ||
| 79 | BitField<8,8,u32> number_commands; | ||
| 40 | }; | 80 | }; |
| 41 | 81 | ||
| 42 | struct GXCommand { | 82 | /// GSP command |
| 43 | BitField<0, 8, GXCommandId> id; | 83 | struct Command { |
| 84 | BitField<0, 8, CommandId> id; | ||
| 44 | 85 | ||
| 45 | union { | 86 | union { |
| 46 | struct { | 87 | struct { |
| @@ -74,7 +115,7 @@ struct GXCommand { | |||
| 74 | u8 raw_data[0x1C]; | 115 | u8 raw_data[0x1C]; |
| 75 | }; | 116 | }; |
| 76 | }; | 117 | }; |
| 77 | static_assert(sizeof(GXCommand) == 0x20, "GXCommand struct has incorrect size"); | 118 | static_assert(sizeof(Command) == 0x20, "Command struct has incorrect size"); |
| 78 | 119 | ||
| 79 | /// Interface to "srv:" service | 120 | /// Interface to "srv:" service |
| 80 | class Interface : public Service::Interface { | 121 | class Interface : public Service::Interface { |
| @@ -98,6 +139,6 @@ public: | |||
| 98 | * Signals that the specified interrupt type has occurred to userland code | 139 | * Signals that the specified interrupt type has occurred to userland code |
| 99 | * @param interrupt_id ID of interrupt that is being signalled | 140 | * @param interrupt_id ID of interrupt that is being signalled |
| 100 | */ | 141 | */ |
| 101 | void SignalInterrupt(GXInterruptId interrupt_id); | 142 | void SignalInterrupt(InterruptId interrupt_id); |
| 102 | 143 | ||
| 103 | } // namespace | 144 | } // namespace |
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp index 41976d989..93b871470 100644 --- a/src/core/hw/gpu.cpp +++ b/src/core/hw/gpu.cpp | |||
| @@ -256,7 +256,7 @@ void Update() { | |||
| 256 | 256 | ||
| 257 | // Synchronize line... | 257 | // Synchronize line... |
| 258 | if ((current_ticks - g_last_ticks) >= GPU::kFrameTicks / 400) { | 258 | if ((current_ticks - g_last_ticks) >= GPU::kFrameTicks / 400) { |
| 259 | GSP_GPU::SignalInterrupt(GSP_GPU::GXInterruptId::PDC0); | 259 | GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PDC0); |
| 260 | g_cur_line++; | 260 | g_cur_line++; |
| 261 | g_last_ticks = current_ticks; | 261 | g_last_ticks = current_ticks; |
| 262 | } | 262 | } |
| @@ -264,7 +264,7 @@ void Update() { | |||
| 264 | // Synchronize frame... | 264 | // Synchronize frame... |
| 265 | if (g_cur_line >= 400) { | 265 | if (g_cur_line >= 400) { |
| 266 | g_cur_line = 0; | 266 | g_cur_line = 0; |
| 267 | GSP_GPU::SignalInterrupt(GSP_GPU::GXInterruptId::PDC1); | 267 | GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PDC1); |
| 268 | VideoCore::g_renderer->SwapBuffers(); | 268 | VideoCore::g_renderer->SwapBuffers(); |
| 269 | Kernel::WaitCurrentThread(WAITTYPE_VBLANK); | 269 | Kernel::WaitCurrentThread(WAITTYPE_VBLANK); |
| 270 | HLE::Reschedule(__func__); | 270 | HLE::Reschedule(__func__); |