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.
... | ... |
@@ -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 |
|