Okay, so I’ve run a camera test on the “Frame Delay” setting. With Nestopia, I could run Mega Man 2 with a frame delay setting of 12 ms on my Core i7-6700K. If everything works as expected, input lag should reduce by 12/16.67 = 0.72 frames. And the test results are as expected (within tolerances):
Without frame delay:
Average: 4.3
Min: 3.25
Max: 5.25
With frame delay set to 12:
Average: 3.4
Min: 2.5
Max: 4.5
This obviously feels great when playing. To understand exactly how good this is and to understand how much room there actually is for improvement, let’s make a simple calculation. We’ll start with the average result (in milliseconds) and remove all the known quantities:
3.4 * 16.666… = 56.67 ms
-4 ms (average time until USB poll)
-8.33 ms (average time until emulator runs)
-4.67 ms (time until emulator finishes first loop and receives vsync. This would be 16.67 ms if the Frame Delay setting was 0, but setting it to 12 has removed 12 ms.)
-16.67 ms (time until emulator finishes second loop and receives vsync)
-11 ms (time for scanning display from top left until reaching the Mega Man character)
Time left unaccounted for: 12 ms
Although the USB polling time could be decreased slightly by increasing the polling rate, there really isn’t that much to do about the other known quantities listed above. The remaining time could come from other small delays within the system (perhaps specifically the GPU driver/hardware). We also haven’t accounted for any delay within the HP Z24i display I’m using. Even if it’s fast, we can probably expect a couple of milliseconds between receiving a signal at the display’s input and getting detectable change of the corresponding pixels.
What about an actual NES on a CRT?
If we go by the hypothesis that the actual NES hardware also has 2 frames of delay in certain cases (such as during Mega Man 2 gameplay) and that it reads input at the beginning of VBLANK, we arrive at:
-8.33 ms (average time until input is actually read)
-16.67 ms (time until NES has finished one frame)
-12 ms (time for running through vblank again and scan out the lines until reaching the Mega Man character at the bottom of the screen)
Expected average input lag for Mega Man 2 on real NES and CRT:[B] 2.2 frames
[/B]If the above calculations hold true, our emulated case using an LCD monitor is only 1.2 frames behind the real NES on a CRT. 1.2 frames translates to 20 ms. That’s actually very, very good.
[QUOTE=Sam33;41747]That’s great work in finding the causes of latency in emulation. Also, I compared mednafen’s version of bsnes source code to the recent Brunnis fix to bsnes-mercury-libretro. Here is the Brunnis fix first to src/system/system.cpp:
And that from mednafen:
It appears that mednafen also used overscan to determine “scheduler.exit”, but the two cpu.vcounter values should instead be decremented by 1. This would mirror the Brunnis fix (save for the condition that exit_line_counter is greater than 100). It may be worthwhile to confirm that the current mednafen changes are not adequate to fully decrease input latency and the effect of exit_line_counter on the snes demos (or a similar use of exit_line_counter to test for increased compatibility).[/QUOTE]
Thanks Sam33! I’ll see if I can have a look at that during the day.