summaryrefslogtreecommitdiff
path: root/src/core/hw/gpu.cpp
diff options
context:
space:
mode:
authorGravatar Yuri Kunde Schlesner2015-01-13 23:52:59 -0200
committerGravatar Yuri Kunde Schlesner2015-01-14 05:07:35 -0200
commit98e3274935c1de94f3e54c145b20d3f08b525647 (patch)
treecfc50a08be9a565b0f6e2284aca2ec64fe497b59 /src/core/hw/gpu.cpp
parentMerge pull request #473 from archshift/pp3ports (diff)
downloadyuzu-98e3274935c1de94f3e54c145b20d3f08b525647.tar.gz
yuzu-98e3274935c1de94f3e54c145b20d3f08b525647.tar.xz
yuzu-98e3274935c1de94f3e54c145b20d3f08b525647.zip
GPU: Fire GPU interrupts at the correct places.
PDC0 and PDC1 are both VBlank interrupts. PDC0 was being treated as a HBlank interrupt and fired many more times than it should. They now both fire together at 60 Hz. This puzzlingly *improves* apparent framerate on many applications. A few other interrupts were being fired inside the GSP command processing instead of on the actual GPU register writes, so they were moved there, which should cover direct writes tho those registers not going through the GX command queue.
Diffstat (limited to 'src/core/hw/gpu.cpp')
-rw-r--r--src/core/hw/gpu.cpp33
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;
27bool g_skip_frame = false; ///< True if the current frame was skipped 27bool g_skip_frame = false; ///< True if the current frame was skipped
28 28
29static u64 frame_ticks = 0; ///< 268MHz / gpu_refresh_rate frames per second 29static u64 frame_ticks = 0; ///< 268MHz / gpu_refresh_rate frames per second
30static u64 line_ticks = 0; ///< Number of ticks for a screen line
31static u32 cur_line = 0; ///< Current screen line
32static u64 last_update_tick = 0; ///< CPU ticl count from last GPU update 30static u64 last_update_tick = 0; ///< CPU ticl count from last GPU update
33static u64 frame_count = 0; ///< Number of frames drawn 31static u64 frame_count = 0; ///< Number of frames drawn
34static bool last_skip_frame = false; ///< True if the last frame was skipped 32static 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;