From 36b9ea4371f3c503a7b8033b7a3e97103f010ad0 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sun, 22 Apr 2018 12:10:57 +0300 Subject: [PATCH] Lagless vsync updates, including autoscale compatibility. --- custom.cpp | 26 ++++++++++++-------------- drawing.cpp | 33 +++++++++++++++++++++++++-------- include/uae.h | 2 +- od-win32/direct3d.cpp | 13 +++++++++---- od-win32/direct3d11.cpp | 15 +++++++++------ od-win32/win32.cpp | 7 ++++++- od-win32/win32_scaler.cpp | 22 ++++++++++++++++------ od-win32/win32gfx.cpp | 10 ++++++++-- 8 files changed, 86 insertions(+), 42 deletions(-) diff --git a/custom.cpp b/custom.cpp index 00ccc660..86b50e91 100644 --- a/custom.cpp +++ b/custom.cpp @@ -8111,9 +8111,9 @@ static bool is_custom_vsync (void) return false; } -static bool do_render_slice(int mode, int slicecnt) +static bool do_render_slice(int mode, int slicecnt, int lastline) { - draw_lines(vpos, slicecnt); + draw_lines(lastline, slicecnt); render_screen(0, mode, true); return true; } @@ -8244,7 +8244,7 @@ static void scanlinesleep(int currline, int nextline) return; int diff = vsync_hblank / (nextline - currline); int us = 1000000 / diff; - if (us < 1300) { // spin if less than 1.3ms + if (us < target_sleep_nanos(-1)) { // spin if less than minimum sleep time target_spin(nextline - currline - 1); return; } @@ -8267,9 +8267,8 @@ 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); + do_render_slice(-1, 0, vpos - 1); while (!currprefs.turbo_emulation && sync_timeout_check(maxtime)) { maybe_process_pull_audio(); target_spin(0); @@ -8299,16 +8298,15 @@ static bool linesync_beam_single(void) return false; } - static bool linesync_beam_multi_dual(void) { + frame_time_t maxtime = read_processor_time() + 2 * vsynctimebase; static int vsyncnextscanline; static int nextwaitvpos; static int display_slice_cnt; 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; @@ -8341,7 +8339,7 @@ static bool linesync_beam_multi_dual(void) if (display_slice_cnt == 0) { if (!was_syncline) { - do_render_slice(1, display_slice_cnt); + do_render_slice(is_last_line() ? 1 : 2, display_slice_cnt, vpos - 1); display_rendered = true; } while (!currprefs.turbo_emulation && sync_timeout_check(maxtime)) { @@ -8361,7 +8359,7 @@ static bool linesync_beam_multi_dual(void) if (!currprefs.turbo_emulation) { if (!was_syncline && !display_rendered) { - do_render_slice(0, display_slice_cnt); + do_render_slice(0, display_slice_cnt, vpos - 1); display_rendered = true; } while(sync_timeout_check(maxtime)) { @@ -8409,6 +8407,7 @@ static bool linesync_beam_multi_dual(void) static bool linesync_beam_multi_single(void) { + frame_time_t maxtime = read_processor_time() + 2 * vsynctimebase; static int vsyncnextscanline; static int vsyncnextscanline_add; static int nextwaitvpos; @@ -8416,7 +8415,6 @@ static bool linesync_beam_multi_single(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; @@ -8449,7 +8447,7 @@ static bool linesync_beam_multi_single(void) if (is_last_line()) { if (!was_syncline && !display_rendered) { - do_render_slice(0, display_slice_cnt); + do_render_slice(1, display_slice_cnt, vpos - 1); display_rendered = true; } // if 2 slices: make sure we are out of vblank. @@ -8495,7 +8493,7 @@ static bool linesync_beam_multi_single(void) if (!currprefs.turbo_emulation) { if (!was_syncline) { - do_render_slice(1, display_slice_cnt); + do_render_slice(2, display_slice_cnt, vpos - 1); display_rendered = true; } @@ -8525,7 +8523,7 @@ static bool linesync_beam_multi_single(void) if (!currprefs.turbo_emulation) { if (!was_syncline) { - do_render_slice(1, display_slice_cnt); + do_render_slice(2, display_slice_cnt, vpos - 1); display_rendered = true; } @@ -8574,7 +8572,7 @@ static bool linesync_beam_multi_single(void) int vp2 = target_get_display_scanline(-1); if (!currprefs.turbo_emulation && (currprefs.m68k_speed < 0 || vp2 < vsyncnextscanline - vsyncnextscanline_add / 10)) { if (!was_syncline && !display_rendered) { - do_render_slice(0, display_slice_cnt); + do_render_slice(0, display_slice_cnt, vpos - 1); display_rendered = true; } while (sync_timeout_check(maxtime)) { diff --git a/drawing.cpp b/drawing.cpp index 3fba5c67..99781f7f 100644 --- a/drawing.cpp +++ b/drawing.cpp @@ -3700,6 +3700,8 @@ static void draw_frame_extras(struct vidbuffer *vb, int y_start, int y_end) refresh_indicator_update(vb); } +extern bool beamracer_debug; + void draw_lines(int end, int section) { int monid = 0; @@ -3708,6 +3710,11 @@ void draw_lines(int end, int section) int y_start = -1; int y_end = -1; + static bool section_toggle; + + if (section == 0) + section_toggle = !section_toggle; + end -= minfirstline; if (end < 0) return; @@ -3719,6 +3726,8 @@ void draw_lines(int end, int section) return; } + int section_color_cnt = 4; + vidinfo->outbuffer = vb; if (!lockscr(vb, false, vb->last_drawn_line ? false : true)) return; @@ -3740,12 +3749,20 @@ void draw_lines(int end, int section) hposblank = 0; pfield_draw_line(vb, line, whereline, wherenext); -#if 0 - static const int section_colors[] = { 0x777, 0xf00, 0x0f0, 0x00f }; - int color = section_colors[section & 3]; - xlinebuffer = row_map[whereline]; - for (int x = 0; x < 4; x++) { - putpixel(xlinebuffer, NULL, vidinfo->drawbuffer.pixbytes, x, xcolors[color], 1); +#if 1 + if (beamracer_debug) { + if (vb->last_drawn_line == end - 4) { + section_color_cnt = 4; + } + if (section_color_cnt > 0) { + section_color_cnt--; + static const int section_colors[] = { 0x777, 0xf00, 0x0f0, 0x00f }; + int color = section_toggle ? section_colors[section & 3] : 0; + xlinebuffer = row_map[whereline]; + for (int x = 0; x < 4; x++) { + putpixel(xlinebuffer, NULL, vidinfo->drawbuffer.pixbytes, x, xcolors[color], 1); + } + } } #endif @@ -3883,7 +3900,7 @@ static void finish_drawing_frame(bool drawlines) } if (multimon && locked) { unlockscr(out, -1, -1); - render_screen(out->monitor_id, 0, true); + render_screen(out->monitor_id, 1, true); show_screen(out->monitor_id, 0); } } @@ -4232,7 +4249,7 @@ void freevidbuffer(int monid, struct vidbuffer *buf) memset (buf, 0, sizeof (struct vidbuffer)); } -void reset_drawing (void) +void reset_drawing(void) { int monid = 0; struct amigadisplay *ad = &adisplays[monid]; diff --git a/include/uae.h b/include/uae.h index 7d1867ce..6ea146c4 100644 --- a/include/uae.h +++ b/include/uae.h @@ -37,7 +37,7 @@ 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 void target_sleep_nanos(int); +extern int target_sleep_nanos(int); 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/od-win32/direct3d.cpp b/od-win32/direct3d.cpp index 50f8dc07..c7030c56 100644 --- a/od-win32/direct3d.cpp +++ b/od-win32/direct3d.cpp @@ -1842,7 +1842,7 @@ static bool xD3D_getscalerect(int monid, float *mx, float *my, float *sx, float return true; } -static void setupscenecoords (struct d3dstruct *d3d) +static void setupscenecoords (struct d3dstruct *d3d, bool normalrender) { int monid = d3d - d3ddata; struct vidbuf_description *vidinfo = &adisplays[monid].gfxvidinfo; @@ -1851,6 +1851,9 @@ static void setupscenecoords (struct d3dstruct *d3d) float dw, dh; static RECT sr2[MAX_AMIGAMONITORS], dr2[MAX_AMIGAMONITORS], zr2[MAX_AMIGAMONITORS]; + if (!normalrender) + return; + //write_log (_T("%dx%d %dx%d %dx%d\n"), tin_w, tin_h, tin_w, tin_h, window_w, window_h); getfilterrect2 (monid, &dr, &sr, &zr, d3d->window_w, d3d->window_h, d3d->tin_w / d3d->dmult, d3d->tin_h / d3d->dmult, d3d->dmult, d3d->tin_w, d3d->tin_h); @@ -3106,7 +3109,9 @@ static void D3D_render2(struct d3dstruct *d3d, int mode) if (!isd3d (d3d) || !d3d->texture) return; - if (mode > 0) + bool normalrender = mode < 0 || (mode & 1); + + if (mode > 0 && (mode & 2)) d3d->slicecnt = 0; else if (mode < 0) d3d->slicecnt = d3d->slicecnt == 2 ? 0 : d3d->slicecnt; @@ -3161,7 +3166,7 @@ static void D3D_render2(struct d3dstruct *d3d, int mode) masktexture = s->masktexture; } - setupscenecoords (d3d); + setupscenecoords(d3d, normalrender); hr = d3d->d3ddev->SetTransform (D3DTS_PROJECTION, &d3d->m_matProj); hr = d3d->d3ddev->SetTransform (D3DTS_VIEW, &d3d->m_matView); hr = d3d->d3ddev->SetTransform (D3DTS_WORLD, &d3d->m_matWorld); @@ -3260,7 +3265,7 @@ static void D3D_render2(struct d3dstruct *d3d, int mode) } else { // non-shader version - setupscenecoords (d3d); + setupscenecoords (d3d, normalrender); hr = d3d->d3ddev->SetTransform (D3DTS_PROJECTION, &d3d->m_matProj); hr = d3d->d3ddev->SetTransform (D3DTS_VIEW, &d3d->m_matView); hr = d3d->d3ddev->SetTransform (D3DTS_WORLD, &d3d->m_matWorld); diff --git a/od-win32/direct3d11.cpp b/od-win32/direct3d11.cpp index a1f8f697..da943f35 100644 --- a/od-win32/direct3d11.cpp +++ b/od-win32/direct3d11.cpp @@ -1460,10 +1460,13 @@ static bool UpdateBuffers(struct d3d11struct *d3d) return true; } -static void setupscenecoords(struct d3d11struct *d3d) +static void setupscenecoords(struct d3d11struct *d3d, bool normalrender) { RECT sr, dr, zr; + if (!normalrender) + return; + getfilterrect2(d3d - d3d11data, &dr, &sr, &zr, d3d->m_screenWidth, d3d->m_screenHeight, d3d->m_bitmapWidth / d3d->dmult, d3d->m_bitmapHeight / d3d->dmult, d3d->dmult, d3d->m_bitmapWidth, d3d->m_bitmapHeight); if (!memcmp(&sr, &d3d->sr2, sizeof RECT) && !memcmp(&dr, &d3d->dr2, sizeof RECT) && !memcmp(&zr, &d3d->zr2, sizeof RECT)) { @@ -4151,11 +4154,11 @@ static void CameraClass_Render(struct d3d11struct *d3d) xD3DXMatrixLookAtLH(&d3d->m_viewMatrix, &position, &lookAt, &up); } -static bool GraphicsClass_Render(struct d3d11struct *d3d, float rotation) +static bool GraphicsClass_Render(struct d3d11struct *d3d, float rotation, bool normalrender) { bool result; - setupscenecoords(d3d); + setupscenecoords(d3d, normalrender); // Generate the view matrix based on the camera's position. CameraClass_Render(d3d); @@ -4309,7 +4312,7 @@ static bool xD3D11_renderframe(int monid, int mode, bool immediate) d3d->frames_since_init++; - if (mode > 0) + if (mode > 0 && (mode & 2)) d3d->slicecnt = 0; else if (mode < 0) d3d->slicecnt = d3d->slicecnt == 2 ? 0 : d3d->slicecnt; @@ -4331,7 +4334,7 @@ static bool xD3D11_renderframe(int monid, int mode, bool immediate) if (d3d->delayedfs || !d3d->texture2d || !d3d->d3dinit_done) return false; - GraphicsClass_Render(d3d, 0); + GraphicsClass_Render(d3d, 0, mode < 0 || (mode & 1)); if (d3d->filenotificationhandle != NULL) { bool notify = false; @@ -4508,7 +4511,7 @@ static bool xD3D11_alloctexture(int monid, int w, int h) d3d->delayedrestore = true; } - setupscenecoords(d3d); + setupscenecoords(d3d, true); changed_prefs.leds_on_screen |= STATUSLINE_TARGET; currprefs.leds_on_screen |= STATUSLINE_TARGET; diff --git a/od-win32/win32.cpp b/od-win32/win32.cpp index 35cb99a2..ed774d03 100644 --- a/od-win32/win32.cpp +++ b/od-win32/win32.cpp @@ -232,7 +232,7 @@ static CLOSETOUCHINPUTHANDLE pCloseTouchInputHandle; static ULONG ActualTimerResolution; -void target_sleep_nanos(int nanos) +int target_sleep_nanos(int nanos) { static bool init; if (!init) { @@ -261,6 +261,8 @@ void target_sleep_nanos(int nanos) init = true; } if (pNtDelayExecution) { + if (nanos < 0) + return 800; LARGE_INTEGER interval; int start = read_processor_time(); nanos *= 10; @@ -270,8 +272,11 @@ void target_sleep_nanos(int nanos) pNtDelayExecution(false, &interval); idletime += read_processor_time() - start; } else { + if (nanos < 0) + return 1300; sleep_millis_main(1); } + return 0; } static uae_u64 spincount; diff --git a/od-win32/win32_scaler.cpp b/od-win32/win32_scaler.cpp index b83c2fc7..d57d806c 100644 --- a/od-win32/win32_scaler.cpp +++ b/od-win32/win32_scaler.cpp @@ -1126,13 +1126,23 @@ void S2X_render(int monid, int y_start, int y_end) } else { /* null */ if (amiga_depth == dst_depth) { - uae_u8 *d = dptr, *s = sptr; - int y; int w = aw * dst_depth / 8; - for (y = 0; y < ah && d + w <= enddptr; y++) { - memcpy (d, s, w); - s += vb->rowbytes; - d += pitch; + if (y_start < 0) { + uae_u8 *d = dptr; + uae_u8 *s = sptr; + for (int y = 0; y < ah && d + w <= enddptr; y++) { + memcpy(d, s, w); + s += vb->rowbytes; + d += pitch; + } + } else { + uae_u8 *d = dptr + y_start * pitch; + uae_u8 *s = sptr + y_start * vb->rowbytes; + for (int y = y_start; y < ah && y < y_end && d + w <= enddptr; y++) { + memcpy(d, s, w); + s += vb->rowbytes; + d += pitch; + } } } ok = 1; diff --git a/od-win32/win32gfx.cpp b/od-win32/win32gfx.cpp index a72181dd..839bd534 100644 --- a/od-win32/win32gfx.cpp +++ b/od-win32/win32gfx.cpp @@ -102,6 +102,7 @@ int vsync_modechangetimeout = 10; int vsync_activeheight, vsync_totalheight; float vsync_vblank, vsync_hblank; +bool beamracer_debug; int reopen(struct AmigaMonitor *, int, bool); @@ -4094,6 +4095,10 @@ retry: if (isfullscreen () != 0) setmouseactive(mon->monitor_id, -1); + if (D3D_debug) { + D3D_debug(0, beamracer_debug); + } + return 1; oops: @@ -4198,10 +4203,11 @@ void updatewinfsmode(int monid, struct uae_prefs *p) bool toggle_3d_debug(void) { if (isvsync_chipset() < 0) { + beamracer_debug = !beamracer_debug; if (D3D_debug) { - int d = D3D_debug(0, 0); - D3D_debug(0, d ? 0 : 1); + D3D_debug(0, beamracer_debug); } + reset_drawing(); return true; } return false; -- 2.47.3