From: Toni Wilen Date: Wed, 18 Apr 2018 14:45:18 +0000 (+0300) Subject: New low latency vsync updates. X-Git-Tag: 4000~115 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=811e007c58ee5ee192a36de569462cd4405b3b58;p=francis%2Fwinuae.git New low latency vsync updates. --- diff --git a/custom.cpp b/custom.cpp index 8d2bcd35..b520ca69 100644 --- a/custom.cpp +++ b/custom.cpp @@ -143,7 +143,7 @@ static bool lof_lace; static bool bplcon0_interlace_seen; static int scandoubled_line; static bool vsync_rendered, frame_rendered, frame_shown; -static float vsynctimeperline; +static int vsynctimeperline; static int frameskiptime; static bool genlockhtoggle; static bool genlockvtoggle; @@ -4346,7 +4346,7 @@ void compute_framesync(void) compute_vsynctime (); - hblank_hz = (double)(currprefs.ntscmode ? CHIPSET_CLOCK_NTSC : CHIPSET_CLOCK_PAL) / (maxhpos + (islinetoggle() ? 0.5 : 0)); + hblank_hz = (currprefs.ntscmode ? CHIPSET_CLOCK_NTSC : CHIPSET_CLOCK_PAL) / (maxhpos + (islinetoggle() ? 0.5 : 0)); write_log (_T("%s mode%s%s V=%.4fHz H=%0.4fHz (%dx%d+%d) IDX=%d (%s) D=%d RTG=%d/%d\n"), isntsc ? _T("NTSC") : _T("PAL"), @@ -7476,7 +7476,7 @@ static bool framewait (void) vsynctimeperline = 1; if (0 || (log_vsync & 2)) { - write_log (_T("%06d %.2f/%06d %03d%%\n"), t, vsynctimeperline, vsynctimebase, t * 100 / vsynctimebase); + write_log (_T("%06d %06d/%06d %03d%%\n"), t, vsynctimeperline, vsynctimebase, t * 100 / vsynctimebase); } frame_shown = true; @@ -7538,7 +7538,7 @@ static bool framewait (void) vsyncmaxtime = curr_time + max; if (0) - write_log (_T("%06d:%06d/%06d\n"), adjust, vsynctimeperline, vstb); + write_log (_T("%06d:%06d/%06d %d %d\n"), adjust, vsynctimeperline, vstb, max, maxvpos_display); } else { @@ -8225,10 +8225,16 @@ STATIC_INLINE bool is_last_line (void) // low latency vsync +#define LLV_DEBUG 0 + static bool sync_timeout_check(frame_time_t max) { +#if LLV_DEBUG + return true; +#else frame_time_t rpt = read_processor_time(); return (int)rpt - (int)max <= 0; +#endif } extern int busywait; @@ -8240,7 +8246,7 @@ static void scanlinesleep(int currline, int nextline) return; int diff = vsync_hblank / (nextline - currline); int us = 1000000 / diff; - if (us < 2100) { // less than 2ms + if (us < 1300) { // spin if less than 1.3ms target_spin(nextline - currline - 1); return; } @@ -8249,6 +8255,12 @@ static void scanlinesleep(int currline, int nextline) cpu_sleep_millis(1); } +static void linesync_first_last_line(int *first, int *last) +{ + *first = minfirstline; + *last = maxvpos_display; +} + static bool linesync_beam_single(void) { frame_time_t maxtime = read_processor_time() + 2 * vsynctimebase; @@ -8300,14 +8312,17 @@ static bool linesync_beam_multi_dual(void) bool was_syncline = is_syncline != 0; is_syncline = 0; - if (vpos == 0 && !was_syncline) { + if (vpos == 0) { + int firstline, lastline; + linesync_first_last_line(&firstline, &lastline); + display_slices = currprefs.gfx_display_sections; if (display_slices <= 0) display_slices = 1; display_slice_cnt = 0; vsyncnextscanline = vsync_activeheight / display_slices + 1; - display_slice_lines = (maxvpos_display - minfirstline) / display_slices + 1; - nextwaitvpos = minfirstline + display_slice_lines; + display_slice_lines = (lastline - firstline) / display_slices + 1; + nextwaitvpos = firstline + display_slice_lines; if (display_slices <= 1) nextwaitvpos = maxvpos_display + 1; if (display_slices <= 2 && vsyncnextscanline > vsync_activeheight * 2 / 3) @@ -8317,6 +8332,9 @@ static bool linesync_beam_multi_dual(void) frame_shown = true; } + if (!display_slices) + return false; + if (vpos >= nextwaitvpos || is_last_line()) { if (display_slice_cnt == 0) { @@ -8405,16 +8423,19 @@ static bool linesync_beam_multi(void) is_syncline = 0; if (vpos == 0 && !was_syncline) { + int firstline, lastline; + linesync_first_last_line(&firstline, &lastline); + display_slices = currprefs.gfx_display_sections; if (!display_slices) display_slices = 1; display_slice_cnt = 0; vsyncnextscanline = vsync_activeheight / display_slices + 1; vsyncnextscanline_add = vsync_activeheight / display_slices; - display_slice_lines = (maxvpos_display - minfirstline) / display_slices + 1; - nextwaitvpos = minfirstline + display_slice_lines + display_slice_lines / 2; + display_slice_lines = (lastline - firstline) / display_slices + 1; + nextwaitvpos = firstline + display_slice_lines + display_slice_lines / 2; if (display_slices <= 1) - nextwaitvpos = maxvpos_display + 1; + nextwaitvpos = lastline + 1; if (display_slices <= 2 && vsyncnextscanline > vsync_activeheight * 2 / 3) vsyncnextscanline = vsync_activeheight * 2 / 3; @@ -8423,6 +8444,9 @@ static bool linesync_beam_multi(void) frame_shown = true; } + if (!display_slices) + return false; + if (is_last_line()) { if (!was_syncline && !display_rendered) { @@ -8450,11 +8474,17 @@ static bool linesync_beam_multi(void) return 0; } scanlinesleep(vp, vsyncnextscanline); +#if LLV_DEBUG + write_log(_T("1:%d:%d:%d:%d."), vpos, vp, nextwaitvpos, vsyncnextscanline); +#endif } do_display_slice(); input_read_done = true; display_slice_cnt = -1; display_rendered = false; +#if LLV_DEBUG + write_log("\n"); +#endif } else if (vpos >= nextwaitvpos) { @@ -8496,6 +8526,9 @@ static bool linesync_beam_multi(void) return 0; } target_spin(0); +#if LLV_DEBUG + write_log(_T("2:%d:%d:%d:%d."), vpos, vp, nextwaitvpos, vsyncnextscanline); +#endif } do_display_slice(); display_rendered = false; @@ -8518,6 +8551,9 @@ static bool linesync_beam_multi(void) if (vp == -1) { maybe_process_pull_audio(); target_spin(0); +#if LLV_DEBUG + write_log(_T("3:%d:%d:%d:%d."), vpos, vp, nextwaitvpos, vsyncnextscanline); +#endif continue; } if (vp < 0 || vp >= vsyncnextscanline) @@ -8528,6 +8564,9 @@ static bool linesync_beam_multi(void) return 0; } scanlinesleep(vp, vsyncnextscanline); +#if LLV_DEBUG + write_log(_T("4:%d:%d:%d:%d."), vpos, vp, nextwaitvpos, vsyncnextscanline); +#endif } do_display_slice(); input_read_done = true; @@ -8538,7 +8577,11 @@ static bool linesync_beam_multi(void) } nextwaitvpos += display_slice_lines; display_slice_cnt++; +#if LLV_DEBUG + write_log("\n"); +#endif } + return input_read_done; } diff --git a/include/uae.h b/include/uae.h index c149d86c..476ee9d6 100644 --- a/include/uae.h +++ b/include/uae.h @@ -36,6 +36,7 @@ extern void target_run (void); extern void target_quit (void); extern void target_restart (void); extern void target_getdate(int *y, int *m, int *d); +extern void target_cpu_speed(void); extern bool get_plugin_path (TCHAR *out, int size, const TCHAR *path); extern void stripslashes (TCHAR *p); extern void fixtrailing (TCHAR *p); diff --git a/newcpu.cpp b/newcpu.cpp index 6b1f909e..ddbf4323 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -1923,6 +1923,7 @@ static void build_cpufunctbl (void) write_log(_T("\n")); set_cpu_caches (true); + target_cpu_speed(); } #define CYCLES_DIV 8192 @@ -6441,6 +6442,7 @@ void m68k_go (int may_quit) currprefs.m68k_speed = changed_prefs.m68k_speed; currprefs.m68k_speed_throttle = changed_prefs.m68k_speed_throttle; update_68k_cycles(); + target_cpu_speed(); } cpu_prefs_changed_flag = 0; } diff --git a/od-win32/direct3d.cpp b/od-win32/direct3d.cpp index 091e1e12..70848837 100644 --- a/od-win32/direct3d.cpp +++ b/od-win32/direct3d.cpp @@ -3764,6 +3764,25 @@ static uae_u8 *xD3D_setcursorsurface(int monid, int *pitch) } } +bool xD3D_getscanline(int *scanline, bool *invblank) +{ + struct d3dstruct *d3d = &d3ddata[0]; + HRESULT hr; + D3DRASTER_STATUS rt; + + if (!isd3d(d3d)) + return false; + if (d3d->d3dswapchain) + hr = d3d->d3dswapchain->GetRasterStatus(&rt); + else + hr = d3d->d3ddev->GetRasterStatus(0, &rt); + if (FAILED(hr)) + return false; + *scanline = rt.ScanLine; + *invblank = rt.InVBlank != FALSE; + return true; +} + void d3d9_select(void) { D3D_free = xD3D_free; @@ -3792,6 +3811,7 @@ void d3d9_select(void) D3D_run = NULL; D3D_debug = xD3D_debug; D3D_led = NULL; + D3D_getscanline = xD3D_getscanline; } #endif diff --git a/od-win32/direct3d.h b/od-win32/direct3d.h index 8c5894e5..b71f5437 100644 --- a/od-win32/direct3d.h +++ b/od-win32/direct3d.h @@ -25,6 +25,7 @@ extern bool(*D3D_getscalerect)(int, float *mx, float *my, float *sx, float *sy); extern void(*D3D_run)(int); extern int(*D3D_debug)(int, int); extern void(*D3D_led)(int, int, int); +extern bool(*D3D_getscanline)(int*, bool*); extern LPDIRECT3DSURFACE9 D3D_capture(int, int*,int*,int*); extern bool D3D11_capture(int, void**,int*, int*,int*); diff --git a/od-win32/direct3d11.cpp b/od-win32/direct3d11.cpp index f25bb13a..231a13ae 100644 --- a/od-win32/direct3d11.cpp +++ b/od-win32/direct3d11.cpp @@ -64,6 +64,7 @@ bool(*D3D_getscalerect)(int, float *mx, float *my, float *sx, float *sy); void(*D3D_run)(int); int(*D3D_debug)(int, int); void(*D3D_led)(int, int, int); +bool(*D3D_getscanline)(int*, bool*); static HMODULE hd3d11, hdxgi, hd3dcompiler, dwmapi; @@ -4865,6 +4866,7 @@ void d3d11_select(void) D3D_run = xD3D11_run; D3D_debug = xD3D11_debug; D3D_led = xD3D11_led; + D3D_getscanline = NULL; } void d3d_select(struct uae_prefs *p) diff --git a/od-win32/win32gfx.cpp b/od-win32/win32gfx.cpp index de8f8c7b..0733b49e 100644 --- a/od-win32/win32gfx.cpp +++ b/od-win32/win32gfx.cpp @@ -335,25 +335,35 @@ static D3DKMTWAITFORVERTICALBLANKEVENT pD3DKMTWaitForVerticalBlankEvent; int target_get_display_scanline(int displayindex) { - if (!pD3DKMTGetScanLine) - return -10; - D3DKMT_GETSCANLINE sl = { 0 }; - struct MultiDisplay *md = displayindex < 0 ? getdisplay(&currprefs) : &Displays[displayindex]; - if (!md->HasAdapterData) - return -11; - sl.VidPnSourceId = md->VidPnSourceId; - sl.hAdapter = md->AdapterHandle; - NTSTATUS status = pD3DKMTGetScanLine(&sl); - if (status == STATUS_SUCCESS) { - if (sl.InVerticalBlank) - return -1; - return sl.ScanLine; - } else { - if ((int)status > 0) - return -(int)status; - return status; + if (pD3DKMTGetScanLine) { + D3DKMT_GETSCANLINE sl = { 0 }; + struct MultiDisplay *md = displayindex < 0 ? getdisplay(&currprefs) : &Displays[displayindex]; + if (!md->HasAdapterData) + return -11; + sl.VidPnSourceId = md->VidPnSourceId; + sl.hAdapter = md->AdapterHandle; + NTSTATUS status = pD3DKMTGetScanLine(&sl); + if (status == STATUS_SUCCESS) { + if (sl.InVerticalBlank) + return -1; + return sl.ScanLine; + } else { + if ((int)status > 0) + return -(int)status; + return status; + } + return -12; + } else if (D3D_getscanline) { + int scanline; + bool invblank; + if (D3D_getscanline(&scanline, &invblank)) { + if (invblank) + return -1; + return scanline; + } + return -14; } - return -12; + return -13; } typedef LONG(CALLBACK* QUERYDISPLAYCONFIG)(UINT32, UINT32*, DISPLAYCONFIG_PATH_INFO*, UINT32*, DISPLAYCONFIG_MODE_INFO*, DISPLAYCONFIG_TOPOLOGY_ID*); @@ -449,6 +459,44 @@ static unsigned int __stdcall waitvblankthread(void *dummy) return 0; } +static void display_vblank_thread_kill(void) +{ + if (waitvblankthread_mode == 2) { + waitvblankthread_mode = 0; + while (waitvblankthread_mode != -1) { + Sleep(10); + } + waitvblankthread_mode = 0; + CloseHandle(waitvblankevent); + waitvblankevent = NULL; + } + wait_vblank_display = NULL; +} + +static void display_vblank_thread(struct AmigaMonitor *mon) +{ + struct amigadisplay *ad = &adisplays[mon->monitor_id]; + struct apmode *ap = ad->picasso_on ? &currprefs.gfx_apmode[1] : &currprefs.gfx_apmode[0]; + + if (currprefs.m68k_speed >= 0) { + display_vblank_thread_kill(); + return; + } + // It seems some Windows 7 drivers hang if D3DKMTWaitForVerticalBlankEvent() + // and D3DKMTGetScanLine() is used simultaneously. + if (os_win8 && ap->gfx_vsyncmode && pD3DKMTWaitForVerticalBlankEvent && wait_vblank_display->HasAdapterData) { + waitvblankevent = CreateEvent(NULL, FALSE, FALSE, NULL); + waitvblankthread_mode = 1; + unsigned int th; + _beginthreadex(NULL, 0, waitvblankthread, 0, 0, &th); + } +} + +void target_cpu_speed(void) +{ + display_vblank_thread(&AMonitors[0]); +} + extern void target_calibrate_spin(void); static void display_param_init(struct AmigaMonitor *mon) { @@ -471,29 +519,9 @@ static void display_param_init(struct AmigaMonitor *mon) if (!wait_vblank_display || !wait_vblank_display->HasAdapterData) { write_log(_T("Selected display mode does not have adapter data!\n")); } - - if (ap->gfx_vsyncmode && pD3DKMTWaitForVerticalBlankEvent && wait_vblank_display->HasAdapterData) { - waitvblankevent = CreateEvent(NULL, FALSE, FALSE, NULL); - waitvblankthread_mode = 1; - unsigned int th; - _beginthreadex(NULL, 0, waitvblankthread, 0, 0, &th); - } Sleep(10); target_calibrate_spin(); -} - -static void display_param_free(void) -{ - if (waitvblankthread_mode == 2) { - waitvblankthread_mode = 0; - while (waitvblankthread_mode != -1) { - Sleep(10); - } - waitvblankthread_mode = 0; - CloseHandle(waitvblankevent); - waitvblankevent = NULL; - } - wait_vblank_display = NULL; + display_vblank_thread(mon); } const TCHAR *target_get_display_name (int num, bool friendlyname) @@ -1815,7 +1843,7 @@ static void close_hwnds(struct AmigaMonitor *mon) { mon->screen_is_initialized = 0; if (!mon->monitor_id) { - display_param_free(); + display_vblank_thread_kill(); #ifdef AVIOUTPUT AVIOutput_Restart(); #endif