]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Lagless VSYNC updates.
authorToni Wilen <twilen@winuae.net>
Sat, 21 Apr 2018 10:34:40 +0000 (13:34 +0300)
committerToni Wilen <twilen@winuae.net>
Sat, 21 Apr 2018 10:34:40 +0000 (13:34 +0300)
custom.cpp
events.cpp
include/events.h
include/uae.h
od-win32/direct3d11.cpp
od-win32/win32.cpp
od-win32/win32gfx.cpp

index b520ca694944007014d107c0bb6c451a783b0937..00ccc660460704177dd53829fa07632128b3497e 100644 (file)
@@ -7487,11 +7487,9 @@ static bool framewait (void)
                if (!vblank_hz_state)
                        return status != 0;
 
-               if (vs < 0) {
-                       frame_shown = true;
-                       status = 1;
-                       return status != 0;
-               }
+               frame_shown = true;
+               status = 1;
+               return status != 0;
        }
 
        status = 1;
@@ -8252,7 +8250,10 @@ static void scanlinesleep(int currline, int nextline)
        }
        if (busywait)
                return;
-       cpu_sleep_millis(1);
+       if (currprefs.m68k_speed < 0)
+               sleep_millis_main(1);
+       else
+               target_sleep_nanos(500);
 }
 
 static void linesync_first_last_line(int *first, int *last)
@@ -8343,20 +8344,18 @@ static bool linesync_beam_multi_dual(void)
                                do_render_slice(1, display_slice_cnt);
                                display_rendered = true;
                        }
-                       if (!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;
-                                               break;
-                                       }
-                                       maybe_process_pull_audio();
-                                       target_spin(0);
+                       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;
+                                       break;
                                }
-                               do_display_slice();
-                               display_rendered = false;
-                               input_read_done = true;
+                               maybe_process_pull_audio();
+                               target_spin(0);
                        }
+                       do_display_slice();
+                       display_rendered = false;
+                       input_read_done = true;
 
                } else {
 
@@ -8408,7 +8407,7 @@ static bool linesync_beam_multi_dual(void)
        return input_read_done;
 }
 
-static bool linesync_beam_multi(void)
+static bool linesync_beam_multi_single(void)
 {
        static int vsyncnextscanline;
        static int vsyncnextscanline_add;
@@ -8464,6 +8463,7 @@ static bool linesync_beam_multi(void)
                        }
                        vsync_clear();
                }
+
                while (!currprefs.turbo_emulation && sync_timeout_check(maxtime)) {
                        int vp = target_get_display_scanline(-1);
                        if (vp < 0 || vp >= vsyncnextscanline)
@@ -8488,25 +8488,38 @@ static bool linesync_beam_multi(void)
 
        } else if (vpos >= nextwaitvpos) {
 
+               // topmost/first slice?
                if (display_slice_cnt == 0) {
-                       // topmost slice
 
                        if (currprefs.gfx_variable_sync) {
 
-                               do_render_slice(1, display_slice_cnt);
-                               display_rendered = true;
+                               if (!currprefs.turbo_emulation) {
+                                       if (!was_syncline) {
+                                               do_render_slice(1, display_slice_cnt);
+                                               display_rendered = true;
+                                       }
 
-                               for(;;) {
-                                       frame_time_t rpt = read_processor_time();
-                                       if ((int)rpt - (int)vsyncmintime >= 0 || (int)rpt - (int)vsyncmintime < -2 * vsynctimebase)
-                                               break;
-                                       maybe_process_pull_audio();
-                                       target_spin(0);
+                                       frame_time_t rpt;
+                                       for(;;) {
+                                               rpt = read_processor_time();
+                                               if ((int)rpt - (int)vsyncmintime >= 0 || (int)rpt - (int)vsyncmintime < -2 * vsynctimebase)
+                                                       break;
+                                               maybe_process_pull_audio();
+                                               if (currprefs.m68k_speed < 0 && !was_syncline) {
+                                                       is_syncline = -1;
+                                                       return 0;
+                                               }
+                                               target_spin(0);
+                                       }
+                                       do_display_slice();
+                                       if ((int)rpt - (int)vsyncmintime < vsynctimebase && (int)rpt - (int)vsyncmintime > -vsynctimebase) {
+                                               vsyncmintime += vsynctimebase;
+                                       } else {
+                                               vsyncmintime = rpt + vsynctimebase;
+                                       }
+                                       display_rendered = false;
+                                       input_read_done = true;
                                }
-                               vsyncmintime = read_processor_time() + vsynctimebase;
-                               do_display_slice();
-                               display_rendered = false;
-                               input_read_done = true;
 
                        } else {
 
@@ -8516,13 +8529,16 @@ static bool linesync_beam_multi(void)
                                                display_rendered = true;
                                        }
 
+                                       // flip slightly early because flip regularly gets delayed if done during vblank
+                                       int lastflipline = vsync_activeheight - vsyncnextscanline_add / 3;
                                        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)
+                                               if (vp < vsync_activeheight / 2 || vp >= lastflipline)
                                                        break;
                                                if (currprefs.m68k_speed < 0 && !was_syncline) {
-                                                       is_syncline = -1;
+                                                       is_syncline_end = lastflipline;
+                                                       is_syncline = -2;
                                                        return 0;
                                                }
                                                target_spin(0);
@@ -8533,6 +8549,21 @@ static bool linesync_beam_multi(void)
                                        do_display_slice();
                                        display_rendered = false;
                                        input_read_done = true;
+
+#if 1
+                                       // if flipped before vblank, wait for vblank
+                                       while (sync_timeout_check(maxtime)) {
+                                               int vp = target_get_display_scanline(-1);
+                                               if (vp < vsync_activeheight / 2)
+                                                       break;
+                                               if (currprefs.m68k_speed < 0 && !was_syncline) {
+                                                       is_syncline = -1;
+                                                       return 0;
+                                               }
+                                               maybe_process_pull_audio();
+                                               target_spin(0);
+                                       }
+#endif
                                }
 
                        }
@@ -8548,7 +8579,8 @@ static bool linesync_beam_multi(void)
                                }
                                while (sync_timeout_check(maxtime)) {
                                        int vp = target_get_display_scanline(-1);
-                                       if (vp == -1) {
+                                       // We are still in vblank and second slice? Poll until vblank ends.
+                                       if (display_slice_cnt == 1 && vp == -1) {
                                                maybe_process_pull_audio();
                                                target_spin(0);
 #if LLV_DEBUG
@@ -8591,10 +8623,10 @@ 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_vblank >= 85 && !currprefs.gfx_variable_sync)
                        linesync_beam_multi_dual();
                else
-                       linesync_beam_multi();
+                       linesync_beam_multi_single();
        }
 }
 
@@ -8749,10 +8781,10 @@ static void hsync_handler_post (bool onvsync)
                if (currprefs.gfx_display_sections <= 1) {
                        input_read_done = linesync_beam_single();
                } else {
-                       if (vsync_hblank >= 85 && currprefs.gfx_variable_sync)
+                       if (vsync_vblank >= 85 && !currprefs.gfx_variable_sync)
                                input_read_done = linesync_beam_multi_dual();
                        else
-                               input_read_done = linesync_beam_multi();
+                               input_read_done = linesync_beam_multi_single();
                }
 
        } else if (!currprefs.cpu_thread && !cpu_sleepmode && currprefs.m68k_speed < 0 && !currprefs.cpu_memory_cycle_exact) {
@@ -10249,7 +10281,7 @@ uae_u8 *restore_custom_extra (uae_u8 *src)
        //currprefs.a4091rom.enabled = changed_prefs.a4091rom.enabled = RBB;
        RBB;
        RBB;
-       currprefs.cs_cdtvscsi = changed_prefs.cs_cdtvscsi = RBB;
+       RBB;
 
        currprefs.cs_pcmcia = changed_prefs.cs_pcmcia = RBB;
        currprefs.cs_ciaatod = changed_prefs.cs_ciaatod = RB;
@@ -10309,7 +10341,7 @@ uae_u8 *save_custom_extra (int *len, uae_u8 *dstptr)
 
        SB (is_board_enabled(&currprefs, ROMTYPE_A2091, 0) ? 1 : 0);
        SB (is_board_enabled(&currprefs, ROMTYPE_A4091, 0) ? 1 : 0);
-       SB (currprefs.cs_cdtvscsi ? 1 : 0);
+       SB (0);
 
        SB (currprefs.cs_pcmcia ? 1 : 0);
        SB (currprefs.cs_ciaatod);
index 0c70d0a1b24e24d20cc03420536499893862a19f..3819b216f6de4629cb00bbf3f86e8db5f228b479 100644 (file)
@@ -70,9 +70,37 @@ void do_cycles_slow (unsigned long cycles_to_add)
 
                /* Keep only CPU emulation running while waiting for sync point. */
                if (is_syncline == -1) {
-                       audio_finish_pull();
+
                        // wait for vblank
+                       audio_finish_pull();
+                       int done = vsync_isdone(NULL);
+                       if (!done) {
+#ifdef WITH_PPC
+                               if (ppc_state) {
+                                       if (is_syncline == 1) {
+                                               uae_ppc_execute_check();
+                                       } else {
+                                               uae_ppc_execute_quick();
+                                       }
+                               }
+#endif
+                               if (currprefs.cachesize)
+                                       pissoff = pissoff_value;
+                               else
+                                       pissoff = pissoff_nojit_value;
+                               return;
+                       }
+                       vsync_clear();
+                       vsync_event_done();
+
+               } else if (is_syncline == -2) {
+
+                       // wait for vblank or early vblank
+                       audio_finish_pull();
                        int done = vsync_isdone(NULL);
+                       int vp = target_get_display_scanline(-1);
+                       if (vp < 0 || vp >= is_syncline_end)
+                               done = true;
                        if (!done) {
 #ifdef WITH_PPC
                                if (ppc_state) {
index fb094a9d9a8a342bd7fbe43e256e2f9e72fe3cb9..42ed45631d340fbd079474b8f68185d1834e004c 100644 (file)
@@ -32,7 +32,6 @@ extern void do_cycles_ce (unsigned long cycles);
 extern void do_cycles_ce020 (unsigned long cycles);
 extern void events_schedule (void);
 extern void do_cycles_slow (unsigned long cycles_to_add);
-extern void do_cycles_fast (unsigned long cycles_to_add);
 
 extern int is_cycle_ce (void);
 
index 476ee9d6ad538c43b0f820082e45cda5589f6e44..7d1867ce7939be240e77839cdfe6cbe0aba583aa 100644 (file)
@@ -37,6 +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 bool get_plugin_path (TCHAR *out, int size, const TCHAR *path);
 extern void stripslashes (TCHAR *p);
 extern void fixtrailing (TCHAR *p);
index 51edfb92951bbbea6ab1a738e339af8e8dd54e4a..a1f8f69779717b5619e3e44861e14bfc80b09297 100644 (file)
@@ -3115,8 +3115,9 @@ static void do_present(struct d3d11struct *d3d, int black)
 
        int vsync = isvsync();
        UINT syncinterval = d3d->vblankintervals;
-       if (d3d->m_tearingSupport && (d3d->swapChainDesc.Flags & DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING)) {
-               if (1 || apm->gfx_vsyncmode || d3d - d3d11data > 0 || currprefs.turbo_emulation) {
+       // only if no vsync or low latency vsync
+       if (d3d->m_tearingSupport && (d3d->swapChainDesc.Flags & DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING) && (!vsync || apm->gfx_vsyncmode)) {
+               if (apm->gfx_vsyncmode || d3d - d3d11data > 0 || currprefs.turbo_emulation) {
                        presentFlags |= DXGI_PRESENT_ALLOW_TEARING;
                        syncinterval = 0;
                }
@@ -3127,6 +3128,10 @@ static void do_present(struct d3d11struct *d3d, int black)
                        syncinterval = 0;
        }
        if (currprefs.turbo_emulation) {
+               static int skip;
+               if (--skip > 0)
+                       return;
+               skip = 10;
                if (os_win8)
                        presentFlags |= DXGI_PRESENT_DO_NOT_WAIT;
                syncinterval = 0;
@@ -3134,8 +3139,6 @@ static void do_present(struct d3d11struct *d3d, int black)
        d3d->syncinterval = syncinterval;
 
        hr = d3d->m_swapChain->Present(syncinterval, presentFlags);
-       if (FAILED(hr))
-               write_log(_T("%08x\n"), hr);
        if (currprefs.turbo_emulation && hr == DXGI_ERROR_WAS_STILL_DRAWING)
                hr = S_OK;
        if (FAILED(hr) && hr != DXGI_STATUS_OCCLUDED) {
index c33f05f8174309ff52e8c78baed0244721aac9ab..35cb99a2010d7a4dc7bc55b0c861087523598cff 100644 (file)
@@ -216,6 +216,11 @@ static int guijoybutton[MAX_JPORTS];
 static int guijoyaxis[MAX_JPORTS][4];
 static bool guijoychange;
 
+typedef NTSTATUS(CALLBACK* NTDELAYEXECUTION)(BOOL, PLARGE_INTEGER);
+typedef NTSTATUS(CALLBACK* ZWSETTIMERRESOLUTION)(ULONG, BOOLEAN, PULONG);
+static NTDELAYEXECUTION pNtDelayExecution;
+static ZWSETTIMERRESOLUTION pZwSetTimerResolution;
+
 #if TOUCH_SUPPORT
 typedef BOOL (CALLBACK* REGISTERTOUCHWINDOW)(HWND, ULONG);
 typedef BOOL (CALLBACK* GETTOUCHINPUTINFO)(HTOUCHINPUT, UINT, PTOUCHINPUT, int);
@@ -225,6 +230,50 @@ static GETTOUCHINPUTINFO pGetTouchInputInfo;
 static CLOSETOUCHINPUTHANDLE pCloseTouchInputHandle;
 #endif
 
+static ULONG ActualTimerResolution;
+
+void target_sleep_nanos(int nanos)
+{
+       static bool init;
+       if (!init) {
+               pNtDelayExecution = (NTDELAYEXECUTION)GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "NtDelayExecution");
+               pZwSetTimerResolution = (ZWSETTIMERRESOLUTION)GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "ZwSetTimerResolution");
+               if (pZwSetTimerResolution) {
+                       // 0.5ms
+                       NTSTATUS status = pZwSetTimerResolution((500 * 1000) / 100, TRUE, &ActualTimerResolution);
+                       if (!status) {
+                               LARGE_INTEGER interval;
+                               interval.QuadPart = -(int)ActualTimerResolution;
+                               status = pNtDelayExecution(false, &interval);
+                               if (!status) {
+                                       write_log(_T("Using NtDelayExecution. ActualTimerResolution=%u\n"), ActualTimerResolution);
+                               } else {
+                                       write_log(_T("NtDelayExecution returned %08x\n"), status);
+                                       pNtDelayExecution = NULL;
+                                       pZwSetTimerResolution = NULL;
+                               }
+                       } else {
+                               write_log(_T("NtDelayExecution not available\n"));
+                               pNtDelayExecution = NULL;
+                               pZwSetTimerResolution = NULL;
+                       }
+               }
+               init = true;
+       }
+       if (pNtDelayExecution) {
+               LARGE_INTEGER interval;
+               int start = read_processor_time();
+               nanos *= 10;
+               if (nanos < ActualTimerResolution)
+                       nanos = ActualTimerResolution;
+               interval.QuadPart = -nanos;
+               pNtDelayExecution(false, &interval);
+               idletime += read_processor_time() - start;
+       } else {
+               sleep_millis_main(1);
+       }
+}
+
 static uae_u64 spincount;
 
 void target_spin(int total)
index 2db058d1d610d48fd4716247833d5d0bb4f1fa8a..a72181dd745a33fc56bd5c1c048efc82f20cc7e3 100644 (file)
@@ -485,7 +485,9 @@ static void display_vblank_thread(struct AmigaMonitor *mon)
                display_vblank_thread_kill();
                return;
        }
-       // It seems some Windows 7 drivers hang if D3DKMTWaitForVerticalBlankEvent()
+       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->HasAdapterData) {
                waitvblankevent = CreateEvent(NULL, FALSE, FALSE, NULL);