Browse code

Improve screen vector timing somewhat.

This patch tries to improve the accuracy of our
screen refresh timing. Notably, it tries to ensure
we don't introduce extra delay in our timing based
on how long the screen vector takes to evaluate.

We also try to ensure we only call SDL_Delay when
we have at least 1ms to wait.

d_m authored on 09/05/2023 20:07:17 • Devine Lu Linvega committed on 09/05/2023 20:12:23
Showing 1 changed files
... ...
@@ -456,28 +456,31 @@ handle_events(Uxn *u)
456 456
 static int
457 457
 run(Uxn *u)
458 458
 {
459
-	Uint64 now = SDL_GetPerformanceCounter(), frame_end, frame_interval = SDL_GetPerformanceFrequency() / 60;
459
+	Uint64 next_refresh = 0;
460
+	Uint64 now = SDL_GetPerformanceCounter();
461
+	Uint64 frame_interval = SDL_GetPerformanceFrequency() / 60;
460 462
 	for(;;) {
461 463
 		Uint16 screen_vector;
462 464
 		/* .System/halt */
463 465
 		if(u->dev[0x0f])
464 466
 			return system_error("Run", "Ended.");
465
-		frame_end = now + frame_interval;
467
+		now = SDL_GetPerformanceCounter();
466 468
 		exec_deadline = now + deadline_interval;
467 469
 		if(!handle_events(u))
468 470
 			return 0;
469 471
 		screen_vector = PEEK2(&u->dev[0x20]);
470
-		uxn_eval(u, screen_vector);
471
-		if(uxn_screen.x2)
472
-			redraw();
473
-		now = SDL_GetPerformanceCounter();
474
-		if(screen_vector) {
475
-			if(!BENCH && ((Sint64)(frame_end - now)) > 0) {
476
-				SDL_Delay((frame_end - now) / ms_interval);
477
-				now = frame_end;
478
-			}
479
-		} else
480
-			SDL_WaitEvent(NULL);
472
+		if(BENCH || now >= next_refresh) {
473
+			now = SDL_GetPerformanceCounter();
474
+			next_refresh = now + frame_interval;
475
+			uxn_eval(u, screen_vector);
476
+			if(uxn_screen.x2)
477
+				redraw();
478
+		}
479
+		if(BENCH);
480
+		else if(screen_vector || uxn_screen.x2) {
481
+			Uint64 delay_ms = (next_refresh - now) / ms_interval;
482
+			if(delay_ms > 0) SDL_Delay(delay_ms);
483
+		} else SDL_WaitEvent(NULL);
481 484
 	}
482 485
 }
483 486