From f9f3fd0f3e25568397a7c334e1fe64713d4aeaf9 Mon Sep 17 00:00:00 2001 From: Pavel Barabanov Date: Thu, 10 Apr 2025 22:24:15 +0300 Subject: [PATCH] Android: add FRAME_SKIPPING and FRAME_INTERPOLATION --- .../features/settings/model/BooleanSetting.kt | 5 ++--- .../features/settings/model/view/SettingsItem.kt | 16 ++++++++++++++++ .../settings/ui/SettingsFragmentPresenter.kt | 2 ++ .../yuzu/yuzu_emu/fragments/EmulationFragment.kt | 3 +++ src/android/app/src/main/res/values/strings.xml | 4 ++++ src/common/settings.h | 4 ++++ .../renderer_vulkan/renderer_vulkan.cpp | 13 ++++++++++--- 7 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt index a412a80a2e..6b50180963 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt @@ -89,11 +89,10 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting { GPU_LOG_MEMORY_TRACKING("gpu_log_memory_tracking"), GPU_LOG_DRIVER_DEBUG("gpu_log_driver_debug"), + ENABLE_FRAME_INTERPOLATION("enable_frame_interpolation"), + ENABLE_FRAME_SKIPPING("enable_frame_skipping"), ENABLE_QUICK_SETTINGS("enable_quick_settings"); -// external fun isFrameSkippingEnabled(): Boolean - external fun isFrameInterpolationEnabled(): Boolean - override fun getBoolean(needsGlobal: Boolean): Boolean = NativeConfig.getBoolean(key, needsGlobal) diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt index f95c53720f..f8ce7d3eea 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt @@ -238,6 +238,22 @@ abstract class SettingsItem( override fun reset() = BooleanSetting.USE_DOCKED_MODE.reset() } + put( + SwitchSetting( + BooleanSetting.ENABLE_FRAME_INTERPOLATION, + titleId = R.string.enable_frame_interpolation, + descriptionId = R.string.enable_frame_interpolation_description + ) + ) + + put( + SwitchSetting( + BooleanSetting.ENABLE_FRAME_SKIPPING, + titleId = R.string.enable_frame_skipping, + descriptionId = R.string.enable_frame_skipping_description + ) + ) + put( SwitchSetting( dockedModeSetting, diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt index 161579927c..a0ed7a1056 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt @@ -271,6 +271,8 @@ class SettingsFragmentPresenter( sl.apply { // add(IntSetting.RENDERER_NVDEC_EMULATION.key) + add(BooleanSetting.ENABLE_FRAME_INTERPOLATION.key) + add(BooleanSetting.ENABLE_FRAME_SKIPPING.key) add(IntSetting.RENDERER_RESOLUTION.key) add(IntSetting.RENDERER_VSYNC.key) add(IntSetting.RENDERER_SCALING_FILTER.key) diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt index 0069e169b3..61b43a85a8 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt @@ -1509,6 +1509,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { if (BooleanSetting.SHOW_FPS.getBoolean(needsGlobal)) { var fpsText = String.format("FPS: %.1f", actualFps) + if (BooleanSetting.ENABLE_FRAME_INTERPOLATION.getBoolean(needsGlobal)) { + fpsText += String.format(" (Generated: %.1f)", actualFps * 2) + } sb.append(fpsText) } diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 77be250537..fd8d00706e 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -465,6 +465,10 @@ Network + Enable Frame Skipping + Toggle frame skipping to improve performance by reducing the number of rendered frames. + Enable Frame Interpolation + Toggle frame interpolation to improve visual smoothness by generating intermediate frames. Resolution (Handheld/Docked) VSync mode Window adapting filter diff --git a/src/common/settings.h b/src/common/settings.h index 3e14a40a09..6f93ead1bc 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -337,6 +337,10 @@ struct Values { #endif "backend", Category::Renderer}; SwitchableSetting vulkan_device{linkage, 0, "vulkan_device", Category::Renderer, Specialization::RuntimeList}; + SwitchableSetting enable_frame_interpolation{linkage, true, "enable_frame_interpolation", + Category::Renderer}; + SwitchableSetting enable_frame_skipping{linkage, true, "enable_frame_skipping", + Category::Renderer}; // Graphics Settings ResolutionScalingInfo resolution_info{}; diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 010cfd225d..0161c53a44 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -38,9 +38,6 @@ #include "video_core/vulkan_common/vulkan_memory_allocator.h" #include "video_core/vulkan_common/vulkan_surface.h" #include "video_core/vulkan_common/vulkan_wrapper.h" -#ifdef __ANDROID__ -#include -#endif namespace Vulkan { namespace { @@ -175,6 +172,16 @@ RendererVulkan::~RendererVulkan() { } void RendererVulkan::Composite(std::span framebuffers) { +#ifdef __ANDROID__ + static u64 frame_counter = 0; + if (Settings::values.enable_frame_skipping.GetValue()) { + ++frame_counter; + if ((frame_counter % 2) != 0) { + return; + } + } +#endif + SCOPE_EXIT { render_window.OnFrameDisplayed(); };