From: Toni Wilen Date: Sat, 14 Apr 2018 16:04:02 +0000 (+0300) Subject: Low latency vsync updates. X-Git-Tag: 4000~121 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=9efe7369e99023a13a85c770702bde26d78feb2d;p=francis%2Fwinuae.git Low latency vsync updates. --- diff --git a/custom.cpp b/custom.cpp index 5a304202..8d2bcd35 100644 --- a/custom.cpp +++ b/custom.cpp @@ -8225,6 +8225,13 @@ STATIC_INLINE bool is_last_line (void) // low latency vsync +static bool sync_timeout_check(frame_time_t max) +{ + frame_time_t rpt = read_processor_time(); + return (int)rpt - (int)max <= 0; +} + +extern int busywait; static void scanlinesleep(int currline, int nextline) { if (currline < 0) @@ -8237,16 +8244,20 @@ static void scanlinesleep(int currline, int nextline) target_spin(nextline - currline - 1); return; } + if (busywait) + return; cpu_sleep_millis(1); } static bool linesync_beam_single(void) { + frame_time_t maxtime = read_processor_time() + 2 * vsynctimebase; + is_syncline = 0; maybe_process_pull_audio(); if (is_last_line()) { do_render_slice(-1, 0); - while (!currprefs.turbo_emulation) { + while (!currprefs.turbo_emulation && sync_timeout_check(maxtime)) { maybe_process_pull_audio(); target_spin(0); int vp = target_get_display_scanline(-1); @@ -8254,14 +8265,14 @@ static bool linesync_beam_single(void) break; } vsync_clear(); - while (!currprefs.turbo_emulation) { + while (!currprefs.turbo_emulation && sync_timeout_check(maxtime)) { maybe_process_pull_audio(); int vp = target_get_display_scanline(-1); if (vp >= vsync_activeheight - 1 || vp < 0) break; scanlinesleep(vp, vsync_activeheight - 1); } - while (!currprefs.turbo_emulation) { + while (!currprefs.turbo_emulation && sync_timeout_check(maxtime)) { maybe_process_pull_audio(); target_spin(0); int vp = target_get_display_scanline(-1); @@ -8284,6 +8295,7 @@ static bool linesync_beam_multi_dual(void) static int display_slice_lines; static int display_slices; static bool display_rendered; + frame_time_t maxtime = read_processor_time() + 2 * vsynctimebase; bool input_read_done = false; bool was_syncline = is_syncline != 0; @@ -8314,7 +8326,7 @@ static bool linesync_beam_multi_dual(void) display_rendered = true; } if (!currprefs.turbo_emulation) { - while (!currprefs.turbo_emulation) { + while (!currprefs.turbo_emulation && sync_timeout_check(maxtime)) { frame_time_t rpt = read_processor_time(); if ((int)rpt - (int)vsyncmintime >= 0 || (int)rpt - (int)vsyncmintime < -vsynctimebase * 2) { vsyncmintime = rpt + vsynctimebase; @@ -8335,7 +8347,7 @@ static bool linesync_beam_multi_dual(void) do_render_slice(0, display_slice_cnt); display_rendered = true; } - for (;;) { + while(sync_timeout_check(maxtime)) { int vp = target_get_display_scanline(-1); if (vp == -1) { maybe_process_pull_audio(); @@ -8378,7 +8390,6 @@ static bool linesync_beam_multi_dual(void) return input_read_done; } - static bool linesync_beam_multi(void) { static int vsyncnextscanline; @@ -8388,6 +8399,7 @@ static bool linesync_beam_multi(void) static int display_slice_lines; static int display_slices; static bool display_rendered; + frame_time_t maxtime = read_processor_time() + 2 * vsynctimebase; bool input_read_done = false; bool was_syncline = is_syncline != 0; @@ -8417,7 +8429,18 @@ static bool linesync_beam_multi(void) do_render_slice(0, display_slice_cnt); display_rendered = true; } - while (!currprefs.turbo_emulation) { + // if 2 slices: make sure we are out of vblank. + if (display_slices <= 2) { + while (!currprefs.turbo_emulation && sync_timeout_check(maxtime)) { + int vp = target_get_display_scanline(-1); + if (vp != -1) + break; + maybe_process_pull_audio(); + target_spin(0); + } + vsync_clear(); + } + while (!currprefs.turbo_emulation && sync_timeout_check(maxtime)) { int vp = target_get_display_scanline(-1); if (vp < 0 || vp >= vsyncnextscanline) break; @@ -8443,7 +8466,7 @@ static bool linesync_beam_multi(void) do_render_slice(1, display_slice_cnt); display_rendered = true; - for (;;) { + for(;;) { frame_time_t rpt = read_processor_time(); if ((int)rpt - (int)vsyncmintime >= 0 || (int)rpt - (int)vsyncmintime < -2 * vsynctimebase) break; @@ -8451,15 +8474,6 @@ static bool linesync_beam_multi(void) target_spin(0); } vsyncmintime = read_processor_time() + vsynctimebase; - - while (!currprefs.turbo_emulation) { - maybe_process_pull_audio(); - int vp = target_get_display_scanline(-1); - if (vp < 0) - break; - scanlinesleep(vp, vsync_activeheight - 1); - } - do_display_slice(); display_rendered = false; input_read_done = true; @@ -8472,7 +8486,7 @@ static bool linesync_beam_multi(void) display_rendered = true; } - for (;;) { + while (sync_timeout_check(maxtime)) { int vp = target_get_display_scanline(-1); maybe_process_pull_audio(); if (vp < 0 || vp < vsync_activeheight / 2 || vp >= vsync_activeheight - 1) @@ -8499,7 +8513,7 @@ static bool linesync_beam_multi(void) do_render_slice(0, display_slice_cnt); display_rendered = true; } - for(;;) { + while (sync_timeout_check(maxtime)) { int vp = target_get_display_scanline(-1); if (vp == -1) { maybe_process_pull_audio(); @@ -8534,7 +8548,7 @@ void vsync_event_done(void) if (currprefs.gfx_display_sections <= 1) { linesync_beam_single(); } else { - if (vsync_hblank >= 85 && currprefs.gfx_variable_sync) + if (vsync_hblank >= 85 && !currprefs.gfx_variable_sync) linesync_beam_multi_dual(); else linesync_beam_multi(); diff --git a/od-win32/dxwrap.h b/od-win32/dxwrap.h index fb3cd4f6..87277764 100644 --- a/od-win32/dxwrap.h +++ b/od-win32/dxwrap.h @@ -82,6 +82,7 @@ struct MultiDisplay { LUID AdapterLuid; UINT VidPnSourceId; UINT AdapterHandle; + bool HasAdapterData; }; extern struct MultiDisplay Displays[MAX_DISPLAYS + 1]; diff --git a/od-win32/win32.cpp b/od-win32/win32.cpp index ad1cfab5..9a838637 100644 --- a/od-win32/win32.cpp +++ b/od-win32/win32.cpp @@ -125,6 +125,7 @@ int uaelib_debug; int pissoff_value = 15000 * CYCLE_UNIT; unsigned int fpucontrol; int extraframewait, extraframewait2; +int busywait; extern FILE *debugfile; extern int console_logging; @@ -250,21 +251,35 @@ void target_calibrate_spin(void) spincount = 0; if (!ap->gfx_vsyncmode) return; + if (busywait) { + write_log(_T("target_calibrate_spin() skipped\n")); + return; + } + write_log(_T("target_calibrate_spin() start\n")); spincount = 0x800000000000; for (int i = 0; i < 50; i++) { for (;;) { vp = target_get_display_scanline(-1); + if (vp <= -10) + goto fail; if (vp >= 1 && vp < vsync_activeheight - 10) break; } + int vp3 = target_get_display_scanline(-1); for (;;) { int vp2 = target_get_display_scanline(-1); + if (vp2 <= -10) + goto fail; if (vp2 == vp + 1) break; + if (vp2 != vp) + goto trynext; } uae_u64 v1 = __rdtsc(); for (;;) { int vp2 = target_get_display_scanline(-1); + if (vp2 <= -10) + goto fail; if (vp2 == vp + 2) { uae_u64 sc = __rdtsc() - v1; if (spincount > sc) @@ -273,6 +288,7 @@ void target_calibrate_spin(void) if (vp2 != vp + 1) break; } +trynext:; } if (spincount == 0x800000000000) { write_log(_T("Spincount calculation error, spinloop not used.\n"), spincount); @@ -280,6 +296,10 @@ void target_calibrate_spin(void) } else { write_log(_T("Spincount = %llu\n"), spincount); } + return; +fail: + write_log(_T("Scanline read failed: %d!\n"), vp); + spincount = 0; } int timeend (void) @@ -442,7 +462,7 @@ int sleep_millis_amiga(int ms) return ret; } -bool quit_ok() +bool quit_ok(void) { if (isfullscreen() > 0) return true; @@ -3860,19 +3880,22 @@ void target_fixup_options (struct uae_prefs *p) } struct MultiDisplay *md = getdisplay (p); - for (int i = 0; i < MAX_AMIGADISPLAYS; i++) { - if (p->gfx_monitor[i].gfx_size_fs.special == WH_NATIVE) { + for (int j = 0; j < MAX_AMIGADISPLAYS; j++) { + if (p->gfx_monitor[j].gfx_size_fs.special == WH_NATIVE) { int i; for (i = 0; md->DisplayModes[i].depth >= 0; i++) { if (md->DisplayModes[i].res.width == md->rect.right - md->rect.left && md->DisplayModes[i].res.height == md->rect.bottom - md->rect.top) { - p->gfx_monitor[i].gfx_size_fs.width = md->DisplayModes[i].res.width; - p->gfx_monitor[i].gfx_size_fs.height = md->DisplayModes[i].res.height; + p->gfx_monitor[j].gfx_size_fs.width = md->DisplayModes[i].res.width; + p->gfx_monitor[j].gfx_size_fs.height = md->DisplayModes[i].res.height; + write_log(_T("Native resolution: %dx%d\n"), p->gfx_monitor[j].gfx_size_fs.width, p->gfx_monitor[j].gfx_size_fs.height); break; } } - if (md->DisplayModes[i].depth < 0) - p->gfx_monitor[i].gfx_size_fs.special = 0; + if (md->DisplayModes[i].depth < 0) { + p->gfx_monitor[j].gfx_size_fs.special = 0; + write_log(_T("Native resolution not found.\n")); + } } } /* switch from 32 to 16 or vice versa if mode does not exist */ @@ -6205,6 +6228,10 @@ static int parseargs(const TCHAR *argx, const TCHAR *np, const TCHAR *np2) floppy_writemode = -1; return 1; } + if (!_tcscmp(arg, _T("busywait"))) { + busywait = 1; + return 1; + } if (!np) return 0; diff --git a/od-win32/win32gfx.cpp b/od-win32/win32gfx.cpp index a0c6922e..de8f8c7b 100644 --- a/od-win32/win32gfx.cpp +++ b/od-win32/win32gfx.cpp @@ -170,15 +170,17 @@ static uae_u8 *scrlinebuf; static struct MultiDisplay *getdisplay2(struct uae_prefs *p, int index) { struct AmigaMonitor *mon = &AMonitors[0]; - int max; + static int max; int display = index < 0 ? p->gfx_apmode[mon->screen_is_picasso ? APMODE_RTG : APMODE_NATIVE].gfx_display - 1 : index; - max = 0; - while (Displays[max].monitorname) - max++; - if (max == 0) { - gui_message (_T("no display adapters! Exiting")); - exit (0); + if (!max || (max > 0 && Displays[max].monitorname != NULL)) { + max = 0; + while (Displays[max].monitorname) + max++; + if (max == 0) { + gui_message(_T("no display adapters! Exiting")); + exit(0); + } } if (index >= 0 && display >= max) return NULL; @@ -190,7 +192,7 @@ static struct MultiDisplay *getdisplay2(struct uae_prefs *p, int index) } struct MultiDisplay *getdisplay (struct uae_prefs *p) { - return getdisplay2 (p, -1); + return getdisplay2(p, -1); } void desktop_coords(int monid, int *dw, int *dh, int *ax, int *ay, int *aw, int *ah) @@ -334,17 +336,24 @@ static D3DKMTWAITFORVERTICALBLANKEVENT pD3DKMTWaitForVerticalBlankEvent; int target_get_display_scanline(int displayindex) { if (!pD3DKMTGetScanLine) - return -2; + 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; - if (pD3DKMTGetScanLine(&sl) == STATUS_SUCCESS) { + 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 -2; + return -12; } typedef LONG(CALLBACK* QUERYDISPLAYCONFIG)(UINT32, UINT32*, DISPLAYCONFIG_PATH_INFO*, UINT32*, DISPLAYCONFIG_MODE_INFO*, DISPLAYCONFIG_TOPOLOGY_ID*); @@ -446,8 +455,6 @@ static void display_param_init(struct AmigaMonitor *mon) struct amigadisplay *ad = &adisplays[mon->monitor_id]; struct apmode *ap = ad->picasso_on ? &currprefs.gfx_apmode[1] : &currprefs.gfx_apmode[0]; - wait_vblank_display = getdisplay(&currprefs); - vsync_activeheight = mon->currentmode.current_height; vsync_totalheight = vsync_activeheight * 1125 / 1080; vsync_vblank = 0; @@ -460,7 +467,12 @@ static void display_param_init(struct AmigaMonitor *mon) vsync_activeheight = mon->currentmode.current_height; } - if (ap->gfx_vsyncmode && pD3DKMTWaitForVerticalBlankEvent) { + wait_vblank_display = getdisplay(&currprefs); + 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; @@ -1026,10 +1038,12 @@ static bool enumeratedisplays2 (bool selectall) if (hdc != NULL) { D3DKMT_OPENADAPTERFROMHDC OpenAdapterData = { 0 }; OpenAdapterData.hDc = hdc; - if (pD3DKMTOpenAdapterFromHdc(&OpenAdapterData) == STATUS_SUCCESS) { + NTSTATUS status = pD3DKMTOpenAdapterFromHdc(&OpenAdapterData); + if (status == STATUS_SUCCESS) { md->AdapterLuid = OpenAdapterData.AdapterLuid; md->VidPnSourceId = OpenAdapterData.VidPnSourceId; md->AdapterHandle = OpenAdapterData.hAdapter; + md->HasAdapterData = true; } DeleteDC(hdc); } @@ -2891,7 +2905,8 @@ bool vsync_switchmode(int monid, int hz) void vsync_clear(void) { vsync_active = false; - ResetEvent(waitvblankevent); + if (waitvblankevent) + ResetEvent(waitvblankevent); } int vsync_isdone(frame_time_t *dt)