summaryrefslogtreecommitdiff
path: root/src/core/hw/gpu.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hw/gpu.cpp')
-rw-r--r--src/core/hw/gpu.cpp78
1 files changed, 51 insertions, 27 deletions
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp
index a1789f9c7..a3a7d128f 100644
--- a/src/core/hw/gpu.cpp
+++ b/src/core/hw/gpu.cpp
@@ -21,12 +21,17 @@
21#include "core/hw/hw.h" 21#include "core/hw/hw.h"
22#include "core/hw/gpu.h" 22#include "core/hw/gpu.h"
23 23
24#include "core/tracer/recorder.h"
25
24#include "video_core/command_processor.h" 26#include "video_core/command_processor.h"
25#include "video_core/hwrasterizer_base.h" 27#include "video_core/hwrasterizer_base.h"
26#include "video_core/renderer_base.h" 28#include "video_core/renderer_base.h"
27#include "video_core/utils.h" 29#include "video_core/utils.h"
28#include "video_core/video_core.h" 30#include "video_core/video_core.h"
29 31
32#include "video_core/debug_utils/debug_utils.h"
33
34
30namespace GPU { 35namespace GPU {
31 36
32Regs g_regs; 37Regs g_regs;
@@ -101,39 +106,43 @@ inline void Write(u32 addr, const T data) {
101 const bool is_second_filler = (index != GPU_REG_INDEX(memory_fill_config[0].trigger)); 106 const bool is_second_filler = (index != GPU_REG_INDEX(memory_fill_config[0].trigger));
102 auto& config = g_regs.memory_fill_config[is_second_filler]; 107 auto& config = g_regs.memory_fill_config[is_second_filler];
103 108
104 if (config.address_start && config.trigger) { 109 if (config.trigger) {
105 u8* start = Memory::GetPhysicalPointer(config.GetStartAddress()); 110 if (config.address_start) { // Some games pass invalid values here
106 u8* end = Memory::GetPhysicalPointer(config.GetEndAddress()); 111 u8* start = Memory::GetPhysicalPointer(config.GetStartAddress());
107 112 u8* end = Memory::GetPhysicalPointer(config.GetEndAddress());
108 if (config.fill_24bit) { 113
109 // fill with 24-bit values 114 if (config.fill_24bit) {
110 for (u8* ptr = start; ptr < end; ptr += 3) { 115 // fill with 24-bit values
111 ptr[0] = config.value_24bit_r; 116 for (u8* ptr = start; ptr < end; ptr += 3) {
112 ptr[1] = config.value_24bit_g; 117 ptr[0] = config.value_24bit_r;
113 ptr[2] = config.value_24bit_b; 118 ptr[1] = config.value_24bit_g;
119 ptr[2] = config.value_24bit_b;
120 }
121 } else if (config.fill_32bit) {
122 // fill with 32-bit values
123 for (u32* ptr = (u32*)start; ptr < (u32*)end; ++ptr)
124 *ptr = config.value_32bit;
125 } else {
126 // fill with 16-bit values
127 for (u16* ptr = (u16*)start; ptr < (u16*)end; ++ptr)
128 *ptr = config.value_16bit;
114 } 129 }
115 } else if (config.fill_32bit) {
116 // fill with 32-bit values
117 for (u32* ptr = (u32*)start; ptr < (u32*)end; ++ptr)
118 *ptr = config.value_32bit;
119 } else {
120 // fill with 16-bit values
121 for (u16* ptr = (u16*)start; ptr < (u16*)end; ++ptr)
122 *ptr = config.value_16bit;
123 }
124 130
125 LOG_TRACE(HW_GPU, "MemoryFill from 0x%08x to 0x%08x", config.GetStartAddress(), config.GetEndAddress()); 131 LOG_TRACE(HW_GPU, "MemoryFill from 0x%08x to 0x%08x", config.GetStartAddress(), config.GetEndAddress());
126 132
127 config.trigger = 0; 133 if (!is_second_filler) {
128 config.finished = 1; 134 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PSC0);
135 } else {
136 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PSC1);
137 }
129 138
130 if (!is_second_filler) { 139 VideoCore::g_renderer->hw_rasterizer->NotifyFlush(config.GetStartAddress(), config.GetEndAddress() - config.GetStartAddress());
131 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PSC0);
132 } else {
133 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PSC1);
134 } 140 }
135 141
136 VideoCore::g_renderer->hw_rasterizer->NotifyFlush(config.GetStartAddress(), config.GetEndAddress() - config.GetStartAddress()); 142 // Reset "trigger" flag and set the "finish" flag
143 // NOTE: This was confirmed to happen on hardware even if "address_start" is zero.
144 config.trigger = 0;
145 config.finished = 1;
137 } 146 }
138 break; 147 break;
139 } 148 }
@@ -270,6 +279,7 @@ inline void Write(u32 addr, const T data) {
270 config.GetPhysicalOutputAddress(), output_width, output_height, 279 config.GetPhysicalOutputAddress(), output_width, output_height,
271 config.output_format.Value(), config.flags); 280 config.output_format.Value(), config.flags);
272 281
282 g_regs.display_transfer_config.trigger = 0;
273 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PPF); 283 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PPF);
274 284
275 VideoCore::g_renderer->hw_rasterizer->NotifyFlush(config.GetPhysicalOutputAddress(), output_size); 285 VideoCore::g_renderer->hw_rasterizer->NotifyFlush(config.GetPhysicalOutputAddress(), output_size);
@@ -284,7 +294,14 @@ inline void Write(u32 addr, const T data) {
284 if (config.trigger & 1) 294 if (config.trigger & 1)
285 { 295 {
286 u32* buffer = (u32*)Memory::GetPhysicalPointer(config.GetPhysicalAddress()); 296 u32* buffer = (u32*)Memory::GetPhysicalPointer(config.GetPhysicalAddress());
297
298 if (Pica::g_debug_context && Pica::g_debug_context->recorder) {
299 Pica::g_debug_context->recorder->MemoryAccessed((u8*)buffer, config.size * sizeof(u32), config.GetPhysicalAddress());
300 }
301
287 Pica::CommandProcessor::ProcessCommandList(buffer, config.size); 302 Pica::CommandProcessor::ProcessCommandList(buffer, config.size);
303
304 g_regs.command_processor_config.trigger = 0;
288 } 305 }
289 break; 306 break;
290 } 307 }
@@ -292,6 +309,13 @@ inline void Write(u32 addr, const T data) {
292 default: 309 default:
293 break; 310 break;
294 } 311 }
312
313 // Notify tracer about the register write
314 // This is happening *after* handling the write to make sure we properly catch all memory reads.
315 if (Pica::g_debug_context && Pica::g_debug_context->recorder) {
316 // addr + GPU VBase - IO VBase + IO PBase
317 Pica::g_debug_context->recorder->RegisterWritten<T>(addr + 0x1EF00000 - 0x1EC00000 + 0x10100000, data);
318 }
295} 319}
296 320
297// Explicitly instantiate template functions because we aren't defining this in the header: 321// Explicitly instantiate template functions because we aren't defining this in the header: