libretro / vice-libretro

Versatile Commodore 8-bit Emulator
GNU General Public License v2.0
40 stars 70 forks source link

Autostart warp caps at 60 FPS #514

Closed automatedbugreportingfacility closed 7 months ago

automatedbugreportingfacility commented 7 months ago

When I set Core Options -> Media -> Autostart to Warp, the frame rate is limited to stable 60 FPS during the autostart. When I press the fast-forward button, the frame rate jumps to over 150 FPS, indicating there's room for the autostart warp to work (much) faster.

NB: I emulate a PAL C64C, i.e. if Core Options -> Media -> Autostart is set to ON, frame rate is at ~50.12 FPS during autoload. I have verified these values using the VIDEO section of Settings -> User Interface -> On-Screen Display -> On-Screen Notifications -> Notification Visibility -> Display Statistics.

RetroArch 1.17.0 (AArch64) + VICE x64sc (3.7 0bc7b58)

sonninnos commented 7 months ago

The warp mode sets both the core-side warping and frontend fast-forward on at the same time in order to not get juddery updating with very fast speeds, so any such limiting is entirely up to the frontend or video driver settings. And not happening here, since some emutypes easily go over 3K fps.

automatedbugreportingfacility commented 7 months ago

@sonninnos: do I understand correctly that I should file a bug in https://github.com/libretro/RetroArch? This is definitely not about the video driver -- pressing the fast-forward button causes the autostart speed to be much faster than the warp. If there was a driver issue, the speed would likely be limited for both.

Also, I'm not sure how judder is related here -- when a file is being autostarted from a disk, there's a static loading screen, i.e. there are no animations on the screen. Therefore, any judder would not be perceivable. There's the Settings -> Frame Throttle -> Fast-Forward Frameskip setting in RetroArch, which conserves battery at the expense of more juddery fast-forward animation. It defaults to ON, but I have it set to OFF to reduce the fast-forward judder. Still, that is unrelated to this issue (tested with both settings).

Currently, the autostart warp is limited to a mere 20% speed-up over a regular non-warped loading times here. The measured autostart times for a 127 block file (31.75 KB) are as follows:

Core Options -> Media -> Autostart ON: 1:21 Core Options -> Media -> Autostart Warp: 1:07 Loading time after manually pressing the fast-forward button: 0:25

For the NTSC, the autostart warp doesn't work at all since ~60 FPS is the regular frame rate.

sonninnos commented 7 months ago

Well something in your OS must be screwing with vsync then. The frontend ff frameskip option is designed for allowing fastforward even in forced vsync mode. Because otherwise every frame is sent to the gpu, which is a huge waste.

With "juddery updating" I mean trying to use the VKBD while warp is enabled used to be horrible since it updated everything at too long intervals.

The fast x64 core shows clear difference between frontend ff only versus the inner warp, especially when the Warp Boost hack is enabled. And I suggest using the Automatic Load Warp option instead of the Autostart Warp mode, which only warps on the first initial load.

Still both behave the same here, as I get the same maximum ff speed with and without manual pressing.

The core-side ff toggle isn't limited manually so it follows the frontend maximum ff speed.

automatedbugreportingfacility commented 7 months ago

@sonninnos: Thanks for your help. OS is Android 12. I don't think it's at fault here (see below), but in case you're willing to look into it, I'd be glad to work with you as needed to run any diagnostics/test/gather logs to help you pinpoint the issue.

And I suggest using the Automatic Load Warp option instead of the Autostart Warp mode, which only warps on the first initial load.

Thanks for the suggestion. On the C64, disk accesses can be made simultaneously to displaying text, graphics, sprites, and animations. The warp mode kicking in automatically during a trackmo or a game loader displaying a picture (which may cause the picture to go away too soon) would be a bad experience (IMHO -- opinions and use cases may vary). That's why I'd prefer to confine the automatic warp to the first initial load, nothing else needed for a genuine C64 experience, and the fast-forward button is there for the rare cases when the loading speed is unbearable.

However, I've just set Media -> Automatic Load Warp to ON to see if it'd make any difference for the autostart, and lo and behold: the autostart works at the full speed. Therefore, the bug can be found by comparing what happens in these two cases:

1) Media -> Automatic Load Warp == OFF && Media -> Autostart == Warp (limited to 120% / 60 FPS on my end) 2) Media -> Automatic Load Warp == ON && Media -> Autostart == ON (full speed on my end)

FWIW, 'Drive Sound Emulation', 'Datasette Sound', and 'Audio Leak Emulation' are all set to OFF on my end.

More fun stuff noticed: when Media -> Autostart is set to ON (i.e. no bugged Autostart Warp), if I set Media -> Automatic Load Warp to ON, start autoloading some content, then set Automatic Load Warp to OFF while the load is still pending, then weirdly the speed drops to 120% (i.e. 60 FPS) for the remaining duration of the load, and not 100% (50.12 FPS) as expected.

sonninnos commented 7 months ago

Ok, I think I got it now. For some random reason after changing options and restarting the current frontend ff mode detector RETRO_ENVIRONMENT_GET_FASTFORWARDING says that it is already active even after disabling it on the previous run, and therefore the code decides to ignore the desired mode change. When only using the reset hotkey it worked fine, therefore it is easy to miss.

It got solved by simply not caring about the current ff state, but I have a feeling I added the check there so that things won't get stuck when also manually pressing ff, but I'll do some more testing to see if it only makes things worse after all.

Edit: Indeed the state is wrong when those frontend calls happen during the same retro_run() frame, so no wonder the state has not updated properly..

sonninnos commented 7 months ago

Ok, I pushed a tiny reordering of things which seems to work fine here, so please have a try when possible.

automatedbugreportingfacility commented 7 months ago

@sonninnos: I've just tried 91d0d4d, and unfortunately there's no difference.

sonninnos commented 7 months ago

Then you need to be even more clear about the steps needed to reproduce it, since I can't do it no matter what.

automatedbugreportingfacility commented 7 months ago

@sonninnos: Okay, so in order to provide more reproducible steps, I nuked /storage/emulated/0/RetroArch, cleared the app data and cache. And it led to some discoveries.

First of all, after starting anew, I noticed that the Autostart Warp works at the full speed. I thought it'd be simply a case of determining which specific option from the previous configuration is the culprit, but I quickly realized that things are more complicated than that...

A major hurdle is that the Autostart Warp speed is extremely brittle -- even if it works at the expected full speed, simply opening the menu during the autload and going back to content causes the frame rate to drop to 60 FPS (i.e. the refresh rate of the UI)!

Also, a completely random setting makes a factor: opening a .D64 using "Load Content" will warp at the full speed if Core Options -> System -> Model is one of the "Automatic" ones?! It makes zero sense to me, almost looks like a red herring.

I believe there's a major bug somewhere causing the frame rate of the emulated content to be force-synced to the refresh rate of the user interface. Maybe even more problems in tandem causing this tangled mess. I also noticed what you noticed -- that using the "restart" option (or force-resetting for a C64 model change) always makes it run correctly at the full speed. The problem occurs when:

1) Core Options -> System -> Model is set to "C64C PAL" (or "C64 PAL", whatever, just not "Automatic"). 2) The .d64 is autostarted from Main Menu -> Load Content, not from any kind of reset/restart.

The file I use for testing is Destination_II.D64 from https://csdb.dk/release/?id=662 (Destination_II.zip), but I think any .d64 will do.

The exact steps after starting with a clean RetroArch 1.17.0 (AArch64) on Android 12 (using a phone with a static refresh rate of 60Hz): 1) Allow RetroArch file access when prompted. 2) Main Menu -> Load Core -> Download a Core -> Commodore - C64 (VICE x64sc, accurate) 3) Settings -> User Interface -> On-Screen Display -> On-Screen Notifications -> Notification Visibility -> Display Framerate: set to enabled 4) Main Menu -> Load Content: navigate to and select Destination_II.D64. It should start autoloading at a normal speed: 50.12 FPS. 5) Exit content to Quick Menu -> Core Options -> Media -> Autostart: set to Warp. "Automatic Load Warp" should default to OFF. 6) Go back to Core Options -> System -> Model: select "C64C PAL". 7) Go back to Main Menu -> Load Content: navigate to and select Destination_II.D64. Autoloads at 60 FPS here.

Please let me know if these steps work for you. I can also provide a video capture or try logging stuff if necessary.

sonninnos commented 7 months ago

I don't get any of that speed drop when only toggling the menu while warping, not with desktop nor with phone, but I was able to do it while autostart warping is still active by hitting restart from the menu without changing any settings, or using the reset hotkey. Automatic warping survives it since it is doing realtime magic instead of the initial autostart mechanism, and autostart warp starts working again after hitting reset again.

It is all because of the exact moment the core is forcing a reload of the emulator state because certain settings don't come into effect otherwise. Changing the model from auto to non-auto is one of those settings. So pretty sure it has nothing to do with the mode, but just the change. Automatic does nothing else except search certain tags from the filename and path, and only does something when there is some.

So while I was able to stop the internal autostart warp not turning off properly after loading after doing a restart at a bad time, it did not totally fix the frontend problem of it believing it is already fastforwarding when it is not, and therefore it does not enable itself, and therefore only the internal warp is active, which will be limited by the refresh rate, as in the rate retro_run() is called.

I went back to one of my previous attempts and moved the ff forcing away from VICE internal warp toggle function to retro_run(), and it seems to be doing the trick. It is pushed now, so please try again when possible.

automatedbugreportingfacility commented 7 months ago

@sonninnos: 3fd23e1 fixes the autostart warp problem, thanks a lot for all your patient investigation and fixes!

This problem remains and probably has a different root cause:

A major hurdle is that the Autostart Warp speed is extremely brittle -- even if it works at the expected full speed, simply opening the menu during the autload and going back to content causes the frame rate to drop to 60 FPS (i.e. the refresh rate of the UI)!

Plus doing a restart from the menu while the full-speed warped autoload is pending will cap it to 60 FPS after the restart. Contrary to the fixed issue, pressing the fast-forward button while the warp is stuck at 60 FPS has no effect. Very likely what you're describing as the frontend problem with maintaining the fast-forward state.

While these things are clearly broken under the hood, I can easily work around that by trying to avoid using the menu during a warped load, so this is not a biggie. It'd probably be more annoying if I used Automatic Load Warp as there'd be a lot more cases where accessing the menu would interrupt a load. If you would like to investigate further to work around that, however, I'd gladly provide adb logcat or whatever's necessary for diagnosis as it reproduces in a stable manner here.

One last thing:

it did not totally fix the frontend problem of it believing it is already fastforwarding when it is not

Would it make sense to file a bug at https://github.com/libretro/RetroArch? I can copy the relevant bits there.

sonninnos commented 7 months ago

Good, so perhaps there is still some sort of limiting happening then, but not anymore due to the core. Try changing frontend drivers and settings or something. And don't disable the frontend fastforward frameskip option, since being capped at the refresh rate is exactly the symptom of having it disabled while vsync is enforced globally.

Frontend FF will disable vsync if it is enabled and allowed to be switched off by the driver, and frontend menu will forcefully switch to swap interval 1 if vsync is enabled. So perhaps some of that switching is causing the permanent damage somehow. But still not happening with my Android 12 phone.

One last thing:

it did not totally fix the frontend problem of it believing it is already fastforwarding when it is not

No point blaming the frontend with this old information, since that was describing the old problem, which is now sorted with the reason stated above. The core reading the frontend state again at the same frame is not a frontend problem.

The menu state alone causing any permanent speed differences is for sure a separate frontend issue. The core has no idea about the frontend pausing the core, and can't do anything about it. So also try what happens when the menu pause toggle option is disabled. The core speed should be still capped while the menu is active of course.

automatedbugreportingfacility commented 7 months ago

Try changing frontend drivers

Tried glui, ozone, rgui, xmb -- all exhibit the same behavior.

And don't disable the frontend fastforward frameskip option, since being capped at the refresh rate is exactly the symptom of having it disabled while vsync is enforced globally.

Okay, I'll keep it on always.

So also try what happens when the menu pause toggle option is disabled. The core speed should be still capped while the menu is active of course.

Correct, the speed drops to 60 FPS the moment the menu is opened.

The only settings that make any difference:

automatedbugreportingfacility commented 7 months ago

Okay, I think I've finally found the solution, and a simple one at that -- RetroArch Nightly works as desired from the get-go, so the issue may have been fixed (at least in the default configuration) between the release of 1.17.0 and today. Thanks again for your help.

sonninnos commented 7 months ago

Tried glui, ozone, rgui, xmb -- all exhibit the same behavior.

Those are menu drivers, not video drivers, and thus aren't supposed to change anything in this scope.