From 03ebd3d59bcb09c7782c6b9af6c63e3acff65592 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sun, 19 Aug 2018 18:42:40 +0300 Subject: [PATCH] Lagless vsync changes. --- custom.cpp | 123 ++++++++++++++++++++++++++++-------------- events.cpp | 64 ++++++++++++++++++++-- include/events.h | 3 +- od-win32/win32.cpp | 17 +++--- od-win32/win32gfx.cpp | 20 ++++++- 5 files changed, 172 insertions(+), 55 deletions(-) diff --git a/custom.cpp b/custom.cpp index 60c16617..dd28e26a 100644 --- a/custom.cpp +++ b/custom.cpp @@ -7940,19 +7940,21 @@ static bool framewait (void) frame_rendered = render_screen(0, 1, false); t = read_processor_time () - start; } - while (!currprefs.turbo_emulation) { - float v = rpt_vsync (clockadjust) / (syncbase / 1000.0); - if (v >= -2) - break; - rtg_vsynccheck (); - maybe_process_pull_audio(); - if (cpu_sleep_millis(1) < 0) - break; - } - while (rpt_vsync (clockadjust) < 0) { - rtg_vsynccheck (); - if (audio_is_pull_event()) - break; + if (!currprefs.cpu_thread) { + while (!currprefs.turbo_emulation) { + float v = rpt_vsync(clockadjust) / (syncbase / 1000.0); + if (v >= -2) + break; + rtg_vsynccheck(); + maybe_process_pull_audio(); + if (cpu_sleep_millis(1) < 0) + break; + } + while (rpt_vsync(clockadjust) < 0) { + rtg_vsynccheck(); + if (audio_is_pull_event()) + break; + } } idletime += read_processor_time() - start; curr_time = read_processor_time (); @@ -8671,9 +8673,11 @@ static int display_slice_cnt; static int display_slice_lines; static int display_slices; static bool display_rendered; +static int vsyncnextstep; static bool linesync_beam_single_dual(void) { + bool was_syncline = is_syncline != 0; frame_time_t maxtime = read_processor_time() + 2 * vsynctimebase; int vp; @@ -8732,35 +8736,58 @@ static bool linesync_beam_single_dual(void) static bool linesync_beam_single_single(void) { + bool was_syncline = is_syncline != 0; frame_time_t maxtime = read_processor_time() + 2 * vsynctimebase; int vp; if (is_last_line()) { - do_render_slice(-1, 0, vpos); - while (!currprefs.turbo_emulation && sync_timeout_check(maxtime)) { - maybe_process_pull_audio(); - target_spin(0); - vp = target_get_display_scanline(-1); - if (vp >= 0) - break; + if (vsyncnextstep != 1) { + vsyncnextstep = 1; + do_render_slice(-1, 0, vpos); + while (!currprefs.turbo_emulation && sync_timeout_check(maxtime)) { + maybe_process_pull_audio(); + vp = target_get_display_scanline(-1); + if (vp >= 0) + break; + if (currprefs.m68k_speed < 0 && !was_syncline) { + is_syncline = -3; + return 0; + } + target_spin(0); + } } - vsync_clear(); - while (!currprefs.turbo_emulation && sync_timeout_check(maxtime)) { - maybe_process_pull_audio(); - vp = target_get_display_scanline(-1); - if (vp >= vsync_activeheight - 1 || vp < 0) - break; - scanlinesleep(vp, vsync_activeheight - 1); + if (vsyncnextstep != 2) { + vsyncnextstep = 2; + vsync_clear(); + while (!currprefs.turbo_emulation && sync_timeout_check(maxtime)) { + maybe_process_pull_audio(); + vp = target_get_display_scanline(-1); + if (vp >= vsync_activeheight - 1 || vp < 0) + break; + if (currprefs.m68k_speed < 0 && !was_syncline) { + is_syncline = -2; + is_syncline_end = vsync_activeheight - 1; + return 0; + } + scanlinesleep(vp, vsync_activeheight - 1); + } } - frame_rendered = true; - frame_shown = true; - do_display_slice(); - while (vp >= vsync_activeheight / 2 && !currprefs.turbo_emulation && sync_timeout_check(maxtime)) { - maybe_process_pull_audio(); - target_spin(0); - vp = target_get_display_scanline(-1); - if (vp < vsync_activeheight / 2) - break; + if (vsyncnextstep != 3) { + vsyncnextstep = 3; + do_display_slice(); + frame_rendered = true; + frame_shown = true; + while (!currprefs.turbo_emulation && sync_timeout_check(maxtime)) { + maybe_process_pull_audio(); + vp = target_get_display_scanline(-1); + if (vp < vsync_activeheight / 2) + break; + if (currprefs.m68k_speed < 0 && !was_syncline) { + is_syncline = -(100 + vsync_activeheight / 2); + return 0; + } + target_spin(0); + } } return true; } @@ -8941,6 +8968,10 @@ static bool linesync_beam_multi_single(void) if (vp != -1) break; maybe_process_pull_audio(); + if (currprefs.m68k_speed < 0 && !was_syncline) { + is_syncline = -3; + return 0; + } target_spin(0); } vsync_clear(); @@ -9031,6 +9062,11 @@ static bool linesync_beam_multi_single(void) // We are still in vblank and second slice? Poll until vblank ends. if (display_slice_cnt == 1 && vp == -1) { maybe_process_pull_audio(); + if (currprefs.m68k_speed < 0 && !was_syncline) { + is_syncline = -3; + return 0; + } + target_spin(0); #if LLV_DEBUG write_log(_T("3:%d:%d:%d:%d."), vpos, vp, nextwaitvpos, vsyncnextscanline); @@ -9391,7 +9427,11 @@ static void hsync_handler_post (bool onvsync) #endif bool input_read_done = false; - if (isvsync_chipset() < 0) { + if (currprefs.cpu_thread) { + + maybe_process_pull_audio(); + + } else if (isvsync_chipset() < 0) { if (currprefs.gfx_display_sections <= 1) { if (vsync_vblank >= 85) @@ -9420,10 +9460,10 @@ static void hsync_handler_post (bool onvsync) frame_time_t rpt = read_processor_time (); while (vsync_isdone(NULL) <= 0 && (int)vsyncmintime - (int)(rpt + vsynctimebase / 10) > 0 && (int)vsyncmintime - (int)rpt < vsynctimebase) { maybe_process_pull_audio(); - if (!execute_other_cpu(rpt + vsynctimebase / 10)) { +// if (!execute_other_cpu(rpt + vsynctimebase / 10)) { if (cpu_sleep_millis(1) < 0) break; - } +// } rpt = read_processor_time (); } } else if (currprefs.m68k_speed_throttle) { @@ -9497,10 +9537,10 @@ static void hsync_handler_post (bool onvsync) // sleep if more than 2ms "free" time while (vsync_isdone(NULL) <= 0 && (int)vsyncmintime - (int)(rpt + vsynctimebase / 10) > 0 && (int)vsyncmintime - (int)rpt < vsynctimebase) { maybe_process_pull_audio(); - if (!execute_other_cpu(rpt + vsynctimebase / 10)) { +// if (!execute_other_cpu(rpt + vsynctimebase / 10)) { if (cpu_sleep_millis(1) < 0) break; - } +// } rpt = read_processor_time(); } } @@ -9646,6 +9686,7 @@ static void hsync_handler (void) bool vs = is_custom_vsync (); hsync_handler_pre (vs); if (vs) { + vsyncmintimepre = read_processor_time(); vsync_handler_pre (); if (savestate_check ()) { uae_reset (0, 0); diff --git a/events.cpp b/events.cpp index 5d06c84e..c98a9339 100644 --- a/events.cpp +++ b/events.cpp @@ -30,7 +30,8 @@ long cycles_to_hsync_event; unsigned long start_cycles; bool event_wait; -frame_time_t vsyncmintime, vsyncmaxtime, vsyncwaittime; +frame_time_t vsyncmintime, vsyncmintimepre; +frame_time_t vsyncmaxtime, vsyncwaittime; int vsynctimebase; int event2_count; @@ -127,6 +128,29 @@ static bool event_check_vsync(void) vsync_clear(); vsync_event_done(); + } else if (is_syncline == -3) { + if (!isvsync_chipset()) { + events_reset_syncline(); + return false; + } + // not vblank + audio_finish_pull(); + int vp = target_get_display_scanline(-1); + if (vp <= 0) { +#ifdef WITH_PPC + if (ppc_state) { + uae_ppc_execute_quick(); + } +#endif + if (currprefs.cachesize) + pissoff = pissoff_value; + else + pissoff = pissoff_nojit_value; + return true; + } + vsync_clear(); + vsync_event_done(); + } else if (is_syncline > 0) { if (!isvsync_chipset()) { @@ -150,6 +174,30 @@ static bool event_check_vsync(void) } vsync_event_done(); + } + else if (is_syncline <= -100) { + + if (!isvsync_chipset()) { + events_reset_syncline(); + return false; + } + audio_finish_pull(); + // wait for specific scanline + int vp = target_get_display_scanline(-1); + if (vp < 0 || vp >= (-(is_syncline + 100))) { +#ifdef WITH_PPC + if (ppc_state) { + uae_ppc_execute_check(); + } +#endif + if (currprefs.cachesize) + pissoff = pissoff_value; + else + pissoff = pissoff_nojit_value; + return true; + } + vsync_event_done(); + } else if (is_syncline == -10) { // wait is_syncline_end @@ -206,16 +254,22 @@ static bool event_check_vsync(void) void do_cycles_slow (unsigned long cycles_to_add) { #ifdef WITH_X86 +#if 0 if (x86_turbo_on) { execute_other_cpu_single(); } +#endif #endif - if ((pissoff -= cycles_to_add) >= 0) - return; + if (!currprefs.cpu_thread) { + if ((pissoff -= cycles_to_add) >= 0) + return; - cycles_to_add = -pissoff; - pissoff = 0; + cycles_to_add = -pissoff; + pissoff = 0; + } else { + pissoff = 0x40000000; + } while ((nextevent - currcycle) <= cycles_to_add) { diff --git a/include/events.h b/include/events.h index e933413f..ee580416 100644 --- a/include/events.h +++ b/include/events.h @@ -18,7 +18,8 @@ #include "machdep/rpt.h" -extern frame_time_t vsyncmintime, vsyncmaxtime, vsyncwaittime; +extern frame_time_t vsyncmintime, vsyncmintimepre; +extern frame_time_t vsyncmaxtime, vsyncwaittime; extern int vsynctimebase, syncbase; extern void reset_frame_rate_hack (void); extern unsigned long int vsync_cycles; diff --git a/od-win32/win32.cpp b/od-win32/win32.cpp index 3820456b..88f95083 100644 --- a/od-win32/win32.cpp +++ b/od-win32/win32.cpp @@ -280,7 +280,7 @@ int target_sleep_nanos(int nanos) return 0; } -static uae_u64 spincount; +uae_u64 spincount; void target_spin(int total) { @@ -302,7 +302,9 @@ void target_calibrate_spin(void) struct amigadisplay *ad = &adisplays[0]; struct apmode *ap = ad->picasso_on ? &currprefs.gfx_apmode[1] : &currprefs.gfx_apmode[0]; int vp; + uae_u64 sc; + sc = 0; spincount = 0; if (!ap->gfx_vsyncmode) return; @@ -311,7 +313,7 @@ void target_calibrate_spin(void) return; } write_log(_T("target_calibrate_spin() start\n")); - spincount = 0x800000000000; + sc = 0x800000000000; for (int i = 0; i < 50; i++) { for (;;) { vp = target_get_display_scanline(-1); @@ -337,19 +339,20 @@ void target_calibrate_spin(void) goto fail; if (vp2 == vp + 2) { uae_u64 sc = __rdtsc() - v1; - if (spincount > sc) - spincount = sc; + if (sc > sc) + sc = sc; } if (vp2 != vp + 1) break; } trynext:; } - if (spincount == 0x800000000000) { - write_log(_T("Spincount calculation error, spinloop not used.\n"), spincount); + if (sc == 0x800000000000) { + write_log(_T("Spincount calculation error, spinloop not used.\n"), sc); spincount = 0; } else { - write_log(_T("Spincount = %llu\n"), spincount); + spincount = sc; + write_log(_T("Spincount = %llu\n"), sc); } return; fail: diff --git a/od-win32/win32gfx.cpp b/od-win32/win32gfx.cpp index f1d005ac..ee8afd59 100644 --- a/od-win32/win32gfx.cpp +++ b/od-win32/win32gfx.cpp @@ -338,7 +338,7 @@ typedef NTSTATUS(CALLBACK* D3DKMTWAITFORVERTICALBLANKEVENT)(const D3DKMT_WAITFOR static D3DKMTWAITFORVERTICALBLANKEVENT pD3DKMTWaitForVerticalBlankEvent; #define STATUS_SUCCESS ((NTSTATUS)0) -int target_get_display_scanline(int displayindex) +static int target_get_display_scanline2(int displayindex) { if (pD3DKMTGetScanLine) { D3DKMT_GETSCANLINE sl = { 0 }; @@ -371,6 +371,24 @@ int target_get_display_scanline(int displayindex) return -13; } +extern uae_u64 spincount;; +int target_get_display_scanline(int displayindex) +{ + static uae_u64 lastrdtsc; + static int lastvpos; + if (spincount == 0 || currprefs.m68k_speed >= 0) { + lastrdtsc = 0; + lastvpos = target_get_display_scanline2(displayindex); + return lastvpos; + } + uae_u64 v = __rdtsc(); + if (lastrdtsc > v) + return lastvpos; + lastvpos = target_get_display_scanline2(displayindex); + lastrdtsc = __rdtsc() + spincount * 4; + return lastvpos; +} + typedef LONG(CALLBACK* QUERYDISPLAYCONFIG)(UINT32, UINT32*, DISPLAYCONFIG_PATH_INFO*, UINT32*, DISPLAYCONFIG_MODE_INFO*, DISPLAYCONFIG_TOPOLOGY_ID*); typedef LONG(CALLBACK* GETDISPLAYCONFIGBUFFERSIZES)(UINT32, UINT32*, UINT32*); typedef LONG(CALLBACK* DISPLAYCONFIGGETDEVICEINFO)(DISPLAYCONFIG_DEVICE_INFO_HEADER*); -- 2.47.3