Rakashazi / emu-ex-plus-alpha

Multi-platform computer & game console emulation system including supporting code (EmuFramework) and core engine (Imagine)
GNU General Public License v3.0
600 stars 145 forks source link

[Feature request]: Black frame insertion option for 120Hz-capable displays #1056

Closed M-a-r-k closed 3 months ago

M-a-r-k commented 1 year ago

Describe the feature

For devices with 120Hz-capable screen, a black frame insertion option would be good to reduce motion blur. Overall/average brightness would be reduced and maybe some users would be aware of 60Hz flicker, but that's no worse than an original CRT display.

(For very high refresh rate displays, non-1:1 black frame insertion could be an option. E.g. display 180Hz, show each emulated frame twice followed by a black frame. The brightness reduction would not be as severe, but motion blur would not be reduced as much.)

Add screenshots

No response

Rakashazi commented 1 year ago

I recently picked up a 120Hz device and plan to do some testing to see how feasible software BFI is next time I update the display code.

M-a-r-k commented 1 year ago

If anyone wants to see what black frame insertion looks like on their Android device, RetroArch supports it but they don't expose the option in the menus. You need to edit retroarch.cfg, change video_black_frame_insertion = "0" to video_black_frame_insertion = "1".

Apparently some LCD screens don't like BFI very much. Most/all OLED screens are probably fine (my phone's is), and it only makes sense to use that option for 120Hz-capable screens anyway.

Rakashazi commented 1 year ago

I added an initial implementation of black frame insertion in the last commit. Currently I've only tested it on my Pixel 7 Pro but it should work on other 120Hz devices. Note that the app only has half the time to render frames (8ms vs 16ms) in this mode so an Android 13+ device supporting PerformanceHintManager is recommended. Let me know how it runs on your end.

M-a-r-k commented 1 year ago

I tried the latest GBC.emu from github. Chose that because it shouldn't be too heavy on CPU requirement (vs GBA.emu say).

I can't seem to get a combination of video settings that don't result in flickering.

Could how this feature functions be re-worked to not require rendering each non-black frame in half the time? It sounds like the current situation is similar to setting frame delay in RetroArch to 8ms. (Which might reduce latency if your system is fast enough, but would result in flickering if it isn't.)

For what it's worth I can enable BFI on RetroArch and play GBA games with a stable display.

Redmi Note 10 Pro on Android 13. I tried enabling the phone's performance mode and setting performance mode in GBC.emu to Sustained, still flickers. However, I did notice that continually touching the screen did in some cases cause the flicker to almost stop. Maybe doing that prevents the OS clocking down the CPU?

Rakashazi commented 1 year ago

Right, in 120hz mode the app wakes up at 8ms intervals so you get lower latency when you switch into high refresh modes by default, but it should be possible to process the blank frame + actual frame at the same so the actual frame has the full 16ms to finish. I'll look into adding an option for this in a future update.

About the flickering, the app doesn't render any frames ahead so most likely the alternating simple/complex computations of each frame are causing the the CPU speed to decrease or the threads are being moved to the low power cores and they cannot ramp up fast enough at the next vsync. The fact that touching the screen improves performance is also an indicator of this since many devices are configured to boost UI responsiveness by increasing CPU frequency when touched.

The PerformanceHintManager API is supposed to address this but while the API is present on Android 13, devices aren't required to do anything with it so it's possibly a no-op on the Redmi currently. Luckily I recently added a system option called "Configure CPU Affinity" that may help. Try setting the mode to manual, then only toggle on the CPUs with the highest MHz values and check if there's any change.

Additionally try these video options: Image Buffers -> 2 Present Mode -> Queued

M-a-r-k commented 3 months ago

I just checked version 1.5.77 (Snes9x-EX+ and MD.emu). BFI seems to be nearly rock-solid now. I adjusted various video options and didn't see flickering.

Rakashazi commented 3 months ago

Awesome, thanks for letting me know. There were various micro optimizations related to rendering in 1.5.77 so those helped out BFI as well.