summaryrefslogtreecommitdiff
path: root/src/core/hw/gpu.cpp
diff options
context:
space:
mode:
authorGravatar bunnei2014-12-24 02:49:09 -0500
committerGravatar bunnei2014-12-25 22:46:55 -0500
commit5799025ac4dc8bf211bce254b87938b42880029d (patch)
treeb6774ad1356d11e3fe134e733de547eb31f8bedc /src/core/hw/gpu.cpp
parentARM: Add a mechanism for faking CPU time elapsed during HLE. (diff)
downloadyuzu-5799025ac4dc8bf211bce254b87938b42880029d.tar.gz
yuzu-5799025ac4dc8bf211bce254b87938b42880029d.tar.xz
yuzu-5799025ac4dc8bf211bce254b87938b42880029d.zip
GPU: Further improve synchronization.
Diffstat (limited to 'src/core/hw/gpu.cpp')
-rw-r--r--src/core/hw/gpu.cpp42
1 files changed, 20 insertions, 22 deletions
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp
index 67a8bc324..7e70b34c1 100644
--- a/src/core/hw/gpu.cpp
+++ b/src/core/hw/gpu.cpp
@@ -21,12 +21,10 @@ namespace GPU {
21 21
22Regs g_regs; 22Regs g_regs;
23 23
24u32 g_cur_line = 0; ///< Current vertical screen line 24static u64 frame_ticks = 0; ///< 268MHz / 60 frames per second
25u64 g_last_line_ticks = 0; ///< CPU tick count from last vertical screen line 25static u32 cur_line = 0; ///< Current vertical screen line
26u64 g_last_frame_ticks = 0; ///< CPU tick count from last frame 26static u64 last_frame_ticks = 0; ///< CPU tick count from last frame
27 27static u64 last_update_tick = 0; ///< CPU ticl count from last GPU update
28static u32 kFrameCycles = 0; ///< 268MHz / 60 frames per second
29static u32 kFrameTicks = 0; ///< Approximate number of instructions/frame
30 28
31template <typename T> 29template <typename T>
32inline void Read(T &var, const u32 raw_addr) { 30inline void Read(T &var, const u32 raw_addr) {
@@ -34,7 +32,7 @@ inline void Read(T &var, const u32 raw_addr) {
34 u32 index = addr / 4; 32 u32 index = addr / 4;
35 33
36 // Reads other than u32 are untested, so I'd rather have them abort than silently fail 34 // Reads other than u32 are untested, so I'd rather have them abort than silently fail
37 if (index >= Regs::NumIds() || !std::is_same<T,u32>::value) { 35 if (index >= Regs::NumIds() || !std::is_same<T, u32>::value) {
38 LOG_ERROR(HW_GPU, "unknown Read%lu @ 0x%08X", sizeof(var) * 8, addr); 36 LOG_ERROR(HW_GPU, "unknown Read%lu @ 0x%08X", sizeof(var) * 8, addr);
39 return; 37 return;
40 } 38 }
@@ -48,7 +46,7 @@ inline void Write(u32 addr, const T data) {
48 u32 index = addr / 4; 46 u32 index = addr / 4;
49 47
50 // Writes other than u32 are untested, so I'd rather have them abort than silently fail 48 // Writes other than u32 are untested, so I'd rather have them abort than silently fail
51 if (index >= Regs::NumIds() || !std::is_same<T,u32>::value) { 49 if (index >= Regs::NumIds() || !std::is_same<T, u32>::value) {
52 LOG_ERROR(HW_GPU, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, addr); 50 LOG_ERROR(HW_GPU, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, addr);
53 return; 51 return;
54 } 52 }
@@ -179,7 +177,6 @@ template void Write<u8>(u32 addr, const u8 data);
179/// Update hardware 177/// Update hardware
180void Update() { 178void Update() {
181 auto& framebuffer_top = g_regs.framebuffer_config[0]; 179 auto& framebuffer_top = g_regs.framebuffer_config[0];
182 u64 current_ticks = Core::g_app_core->GetTicks();
183 180
184 // Update the frame after a certain number of CPU ticks have elapsed. This assumes that the 181 // Update the frame after a certain number of CPU ticks have elapsed. This assumes that the
185 // active frame in memory is always complete to render. There also may be issues with this 182 // active frame in memory is always complete to render. There also may be issues with this
@@ -189,9 +186,9 @@ void Update() {
189 // primitive homebrew relies on a vertical blank interrupt to happen inevitably (regardless of a 186 // primitive homebrew relies on a vertical blank interrupt to happen inevitably (regardless of a
190 // threading reschedule). 187 // threading reschedule).
191 188
192 if ((current_ticks - g_last_frame_ticks) > GPU::kFrameTicks) { 189 if ((Core::g_app_core->GetTicks() - last_frame_ticks) > (GPU::frame_ticks)) {
193 VideoCore::g_renderer->SwapBuffers(); 190 VideoCore::g_renderer->SwapBuffers();
194 g_last_frame_ticks = current_ticks; 191 last_frame_ticks = Core::g_app_core->GetTicks();
195 } 192 }
196 193
197 // Synchronize GPU on a thread reschedule: Because we cannot accurately predict a vertical 194 // Synchronize GPU on a thread reschedule: Because we cannot accurately predict a vertical
@@ -199,17 +196,20 @@ void Update() {
199 // accurately when this is signalled between thread switches. 196 // accurately when this is signalled between thread switches.
200 197
201 if (HLE::g_reschedule) { 198 if (HLE::g_reschedule) {
199 u64 current_ticks = Core::g_app_core->GetTicks();
200 u64 line_ticks = (GPU::frame_ticks / framebuffer_top.height) * 16;
202 201
203 // Synchronize line... 202 //// Synchronize line...
204 if ((current_ticks - g_last_line_ticks) >= GPU::kFrameTicks / framebuffer_top.height) { 203 if ((current_ticks - last_update_tick) >= line_ticks) {
205 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PDC0); 204 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PDC0);
206 g_cur_line++; 205 cur_line++;
207 g_last_line_ticks = current_ticks; 206 last_update_tick += line_ticks;
208 } 207 }
209 208
210 // Synchronize frame... 209 // Synchronize frame...
211 if (g_cur_line >= framebuffer_top.height) { 210 if (cur_line >= framebuffer_top.height) {
212 g_cur_line = 0; 211 cur_line = 0;
212 VideoCore::g_renderer->SwapBuffers();
213 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PDC1); 213 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PDC1);
214 } 214 }
215 } 215 }
@@ -217,11 +217,9 @@ void Update() {
217 217
218/// Initialize hardware 218/// Initialize hardware
219void Init() { 219void Init() {
220 kFrameCycles = 268123480 / Settings::values.gpu_refresh_rate; 220 frame_ticks = 268123480 / Settings::values.gpu_refresh_rate;
221 kFrameTicks = kFrameCycles / 3; 221 cur_line = 0;
222 222 last_update_tick = last_frame_ticks = Core::g_app_core->GetTicks();
223 g_cur_line = 0;
224 g_last_frame_ticks = g_last_line_ticks = Core::g_app_core->GetTicks();
225 223
226 auto& framebuffer_top = g_regs.framebuffer_config[0]; 224 auto& framebuffer_top = g_regs.framebuffer_config[0];
227 auto& framebuffer_sub = g_regs.framebuffer_config[1]; 225 auto& framebuffer_sub = g_regs.framebuffer_config[1];