diff options
Diffstat (limited to 'src/core/hw/gpu.cpp')
| -rw-r--r-- | src/core/hw/gpu.cpp | 33 |
1 files changed, 18 insertions, 15 deletions
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp index 3b730a0de..ad39fdc49 100644 --- a/src/core/hw/gpu.cpp +++ b/src/core/hw/gpu.cpp | |||
| @@ -27,8 +27,6 @@ Regs g_regs; | |||
| 27 | bool g_skip_frame = false; ///< True if the current frame was skipped | 27 | bool g_skip_frame = false; ///< True if the current frame was skipped |
| 28 | 28 | ||
| 29 | static u64 frame_ticks = 0; ///< 268MHz / gpu_refresh_rate frames per second | 29 | static u64 frame_ticks = 0; ///< 268MHz / gpu_refresh_rate frames per second |
| 30 | static u64 line_ticks = 0; ///< Number of ticks for a screen line | ||
| 31 | static u32 cur_line = 0; ///< Current screen line | ||
| 32 | static u64 last_update_tick = 0; ///< CPU ticl count from last GPU update | 30 | static u64 last_update_tick = 0; ///< CPU ticl count from last GPU update |
| 33 | static u64 frame_count = 0; ///< Number of frames drawn | 31 | static u64 frame_count = 0; ///< Number of frames drawn |
| 34 | static bool last_skip_frame = false; ///< True if the last frame was skipped | 32 | static bool last_skip_frame = false; ///< True if the last frame was skipped |
| @@ -79,6 +77,12 @@ inline void Write(u32 addr, const T data) { | |||
| 79 | *ptr = bswap32(config.value); // TODO: This is just a workaround to missing framebuffer format emulation | 77 | *ptr = bswap32(config.value); // TODO: This is just a workaround to missing framebuffer format emulation |
| 80 | 78 | ||
| 81 | LOG_TRACE(HW_GPU, "MemoryFill from 0x%08x to 0x%08x", config.GetStartAddress(), config.GetEndAddress()); | 79 | LOG_TRACE(HW_GPU, "MemoryFill from 0x%08x to 0x%08x", config.GetStartAddress(), config.GetEndAddress()); |
| 80 | |||
| 81 | if (!is_second_filler) { | ||
| 82 | GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PSC0); | ||
| 83 | } else { | ||
| 84 | GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PSC1); | ||
| 85 | } | ||
| 82 | } | 86 | } |
| 83 | break; | 87 | break; |
| 84 | } | 88 | } |
| @@ -152,6 +156,8 @@ inline void Write(u32 addr, const T data) { | |||
| 152 | config.GetPhysicalInputAddress(), (u32)config.input_width, (u32)config.input_height, | 156 | config.GetPhysicalInputAddress(), (u32)config.input_width, (u32)config.input_height, |
| 153 | config.GetPhysicalOutputAddress(), (u32)config.output_width, (u32)config.output_height, | 157 | config.GetPhysicalOutputAddress(), (u32)config.output_width, (u32)config.output_height, |
| 154 | config.output_format.Value()); | 158 | config.output_format.Value()); |
| 159 | |||
| 160 | GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PPF); | ||
| 155 | } | 161 | } |
| 156 | break; | 162 | break; |
| 157 | } | 163 | } |
| @@ -193,20 +199,14 @@ void Update() { | |||
| 193 | // blank, we need to simulate it. Based on testing, it seems that retail applications work more | 199 | // blank, we need to simulate it. Based on testing, it seems that retail applications work more |
| 194 | // accurately when this is signalled between thread switches. | 200 | // accurately when this is signalled between thread switches. |
| 195 | 201 | ||
| 196 | if (HLE::g_reschedule) { | 202 | u64 current_ticks = Core::g_app_core->GetTicks(); |
| 197 | u64 current_ticks = Core::g_app_core->GetTicks(); | ||
| 198 | u32 num_lines = static_cast<u32>((current_ticks - last_update_tick) / line_ticks); | ||
| 199 | 203 | ||
| 200 | // Synchronize line... | 204 | |
| 201 | if (num_lines > 0) { | 205 | if (HLE::g_reschedule) { |
| 202 | GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PDC0); | ||
| 203 | cur_line += num_lines; | ||
| 204 | last_update_tick += (num_lines * line_ticks); | ||
| 205 | } | ||
| 206 | 206 | ||
| 207 | // Synchronize frame... | 207 | // Synchronize frame... |
| 208 | if (cur_line >= framebuffer_top.height) { | 208 | if ((current_ticks - last_update_tick) >= frame_ticks) { |
| 209 | cur_line = 0; | 209 | last_update_tick += frame_ticks; |
| 210 | frame_count++; | 210 | frame_count++; |
| 211 | last_skip_frame = g_skip_frame; | 211 | last_skip_frame = g_skip_frame; |
| 212 | g_skip_frame = (frame_count & Settings::values.frame_skip) != 0; | 212 | g_skip_frame = (frame_count & Settings::values.frame_skip) != 0; |
| @@ -223,6 +223,11 @@ void Update() { | |||
| 223 | } | 223 | } |
| 224 | 224 | ||
| 225 | // Signal to GSP that GPU interrupt has occurred | 225 | // Signal to GSP that GPU interrupt has occurred |
| 226 | // TODO(yuriks): hwtest to determine if PDC0 is for the Top screen and PDC1 for the Sub | ||
| 227 | // screen, or if both use the same interrupts and these two instead determine the | ||
| 228 | // beginning and end of the VBlank period. If needed, split the interrupt firing into | ||
| 229 | // two different intervals. | ||
| 230 | GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PDC0); | ||
| 226 | GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PDC1); | 231 | GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PDC1); |
| 227 | 232 | ||
| 228 | // TODO(bunnei): Fake a DSP interrupt on each frame. This does not belong here, but | 233 | // TODO(bunnei): Fake a DSP interrupt on each frame. This does not belong here, but |
| @@ -264,8 +269,6 @@ void Init() { | |||
| 264 | framebuffer_sub.active_fb = 0; | 269 | framebuffer_sub.active_fb = 0; |
| 265 | 270 | ||
| 266 | frame_ticks = 268123480 / Settings::values.gpu_refresh_rate; | 271 | frame_ticks = 268123480 / Settings::values.gpu_refresh_rate; |
| 267 | line_ticks = (GPU::frame_ticks / framebuffer_top.height); | ||
| 268 | cur_line = 0; | ||
| 269 | last_update_tick = Core::g_app_core->GetTicks(); | 272 | last_update_tick = Core::g_app_core->GetTicks(); |
| 270 | last_skip_frame = false; | 273 | last_skip_frame = false; |
| 271 | g_skip_frame = false; | 274 | g_skip_frame = false; |