]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Lagless vsync improvements.
authorToni Wilen <twilen@winuae.net>
Sat, 16 Nov 2019 17:47:41 +0000 (19:47 +0200)
committerToni Wilen <twilen@winuae.net>
Sat, 16 Nov 2019 17:47:41 +0000 (19:47 +0200)
custom.cpp
od-win32/win32.cpp
od-win32/win32gfx.cpp

index 4bebbf804bd9da0f5258ac84f876393a2ff10e6b..1fd090557179d5c485a51668cf4fd7cd934ed8eb 100644 (file)
@@ -8951,6 +8951,7 @@ static bool linesync_beam_single_single(void)
                if (vsyncnextstep != 1) {
                        vsyncnextstep = 1;
                        do_render_slice(-1, 0, vpos);
+                       // wait until out of vblank
                        while (!currprefs.turbo_emulation && sync_timeout_check(maxtime)) {
                                maybe_process_pull_audio();
                                vp = target_get_display_scanline(-1);
@@ -8966,24 +8967,42 @@ static bool linesync_beam_single_single(void)
                if (vsyncnextstep != 2) {
                        vsyncnextstep = 2;
                        vsync_clear();
+                       // wait until second half of display
                        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)
+                               if (vp >= vsync_activeheight / 2)
                                        break;
                                if (currprefs.m68k_speed < 0 && !was_syncline) {
                                        is_syncline = -2;
                                        is_syncline_end = vsync_activeheight - 1;
                                        return 0;
                                }
-                               scanlinesleep(vp, vsync_activeheight - 1);
+                               scanlinesleep(vp, vsync_activeheight / 2);
                        }
                }
                if (vsyncnextstep != 3) {
                        vsyncnextstep = 3;
+                       // wait until end of display (or start of next field)
+                       while (!currprefs.turbo_emulation && sync_timeout_check(maxtime)) {
+                               maybe_process_pull_audio();
+                               vp = target_get_display_scanline(-1);
+                               if (vp >= vsync_activeheight - 1 || vp < vsync_activeheight / 2)
+                                       break;
+                               if (currprefs.m68k_speed < 0 && !was_syncline) {
+                                       is_syncline = -2;
+                                       is_syncline_end = vsync_activeheight - 1;
+                                       return 0;
+                               }
+                               scanlinesleep(vp, vsync_activeheight - 1);
+                       }
+               }
+               if (vsyncnextstep != 4) {
+                       vsyncnextstep = 4;
                        do_display_slice();
                        frame_rendered = true;
                        frame_shown = true;
+                       // wait until first half of display
                        while (!currprefs.turbo_emulation && sync_timeout_check(maxtime)) {
                                maybe_process_pull_audio();
                                vp = target_get_display_scanline(-1);
@@ -9013,7 +9032,7 @@ static bool linesync_beam_multi_dual(void)
                linesync_first_last_line(&firstline, &lastline);
 
                display_slices = currprefs.gfx_display_sections;
-               if (!display_slices)
+               if (display_slices <= 0)
                        display_slices = 1;
                display_slice_cnt = 0;
                vsyncnextscanline = vsync_activeheight / display_slices + 1;
@@ -9218,7 +9237,7 @@ static bool linesync_beam_multi_single(void)
                                }
 
                                // flip slightly early because flip regularly gets delayed if done during vblank
-                               int lastflipline = vsync_activeheight - vsyncnextscanline_add / 3;
+                               int lastflipline = vsync_activeheight - vsyncnextscanline_add / 5;
                                while (sync_timeout_check(maxtime)) {
                                        int vp = target_get_display_scanline(-1);
                                        maybe_process_pull_audio();
index 9c5d966f1e26bd66ec0a6ec0b1b310ed6f5dd64d..31a6f9f147b51cc4d32437bb71934ccbe9119b8b 100644 (file)
@@ -319,10 +319,11 @@ int target_sleep_nanos(int nanos)
 }
 
 uae_u64 spincount;
+extern bool calculated_scanline;
 
 void target_spin(int total)
 {
-       if (!spincount)
+       if (!spincount || calculated_scanline)
                return;
        if (total > 10)
                total = 10;
@@ -346,7 +347,7 @@ void target_calibrate_spin(void)
        spincount = 0;
        if (!ap->gfx_vsyncmode)
                return;
-       if (busywait) {
+       if (busywait || calculated_scanline) {
                write_log(_T("target_calibrate_spin() skipped\n"));
                return;
        }
index 78057372154b6879a532b1cbf5453808020a1f20..4984b7aa3006a08702f41b44d879b3a695bc8086 100644 (file)
@@ -330,6 +330,13 @@ int target_get_display(const TCHAR *name)
        return -1;
 }
 
+static volatile int waitvblankthread_mode;
+HANDLE waitvblankevent;
+static frame_time_t wait_vblank_timestamp;
+static MultiDisplay *wait_vblank_display;
+static volatile bool vsync_active;
+static bool scanlinecalibrating;
+
 typedef NTSTATUS(CALLBACK* D3DKMTOPENADAPTERFROMHDC)(D3DKMT_OPENADAPTERFROMHDC*);
 static D3DKMTOPENADAPTERFROMHDC pD3DKMTOpenAdapterFromHdc;
 typedef NTSTATUS(CALLBACK* D3DKMTGETSCANLINE)(D3DKMT_GETSCANLINE*);
@@ -371,22 +378,35 @@ static int target_get_display_scanline2(int displayindex)
        return -13;
 }
 
-extern uae_u64 spincount;;
+extern uae_u64 spincount;
+bool calculated_scanline = 1;
+
 int target_get_display_scanline(int displayindex)
 {
-       static uae_u64 lastrdtsc;
-       static int lastvpos;
-       if (spincount == 0 || currprefs.m68k_speed >= 0) {
-               lastrdtsc = 0;
+       if (!scanlinecalibrating && calculated_scanline) {
+               static int lastline;
+               float diff = read_processor_time() - wait_vblank_timestamp;
+               if (diff < 0)
+                       return -1;
+               int sl = (int)(diff * (vsync_activeheight + (vsync_totalheight - vsync_activeheight) / 10) * vsync_vblank / syncbase);
+               if (sl < 0)
+                       sl = -1;
+               return sl;
+       } else {
+               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;
        }
-       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*);
@@ -459,16 +479,10 @@ static bool get_display_vblank_params(int displayindex, int *activeheightp, int
        return ret;
 }
 
-static volatile int waitvblankthread_mode;
-HANDLE waitvblankevent;
-static frame_time_t wait_vblank_timestamp;
-static MultiDisplay *wait_vblank_display;
-static volatile bool vsync_active;
-
 static unsigned int __stdcall waitvblankthread(void *dummy)
 {
        waitvblankthread_mode = 2;
-       SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
+       SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
        while (waitvblankthread_mode) {
                D3DKMT_WAITFORVERTICALBLANKEVENT e = { 0 };
                e.hAdapter = wait_vblank_display->AdapterHandle;
@@ -500,19 +514,17 @@ 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;
-       }
        if (waitvblankthread_mode > 0)
                return;
        // It seems some Windows 7 drivers stall if D3DKMTWaitForVerticalBlankEvent()
        // and D3DKMTGetScanLine() is used simultaneously.
-       if (os_win8 && ap->gfx_vsyncmode && pD3DKMTWaitForVerticalBlankEvent && wait_vblank_display && wait_vblank_display->HasAdapterData) {
+       if ((calculated_scanline || os_win8) && ap->gfx_vsyncmode && pD3DKMTWaitForVerticalBlankEvent && wait_vblank_display && wait_vblank_display->HasAdapterData) {
                waitvblankevent = CreateEvent(NULL, FALSE, FALSE, NULL);
                waitvblankthread_mode = 1;
                unsigned int th;
                _beginthreadex(NULL, 0, waitvblankthread, 0, 0, &th);
+       } else {
+               calculated_scanline = 0;
        }
 }
 
@@ -546,7 +558,9 @@ static void display_param_init(struct AmigaMonitor *mon)
                write_log(_T("Selected display mode does not have adapter data!\n"));
        }
        Sleep(10);
+       scanlinecalibrating = true;
        target_calibrate_spin();
+       scanlinecalibrating = false;
        display_vblank_thread(mon);
 }