@ -38,9 +38,7 @@
# include "video_core/vulkan_common/vulkan_memory_allocator.h"
# include "video_core/vulkan_common/vulkan_memory_allocator.h"
# include "video_core/vulkan_common/vulkan_surface.h"
# include "video_core/vulkan_common/vulkan_surface.h"
# include "video_core/vulkan_common/vulkan_wrapper.h"
# include "video_core/vulkan_common/vulkan_wrapper.h"
# ifdef __ANDROID__
# include <jni.h>
# endif
namespace Vulkan {
namespace Vulkan {
namespace {
namespace {
@ -189,39 +187,6 @@ RendererVulkan::~RendererVulkan() {
void ( device . GetLogical ( ) . WaitIdle ( ) ) ;
void ( device . GetLogical ( ) . WaitIdle ( ) ) ;
}
}
# ifdef __ANDROID__
class BooleanSetting {
public :
// static BooleanSetting FRAME_SKIPPING;
static BooleanSetting FRAME_INTERPOLATION ;
explicit BooleanSetting ( bool initial_value = false ) : value ( initial_value ) { }
[[nodiscard]] bool getBoolean ( ) const {
return value ;
}
void setBoolean ( bool new_value ) {
value = new_value ;
}
private :
bool value ;
} ;
// Initialize static members
// BooleanSetting BooleanSetting::FRAME_SKIPPING(false);
BooleanSetting BooleanSetting : : FRAME_INTERPOLATION ( false ) ;
// extern "C" JNIEXPORT jboolean JNICALL
// Java_org_yuzu_yuzu_1emu_features_settings_model_BooleanSetting_isFrameSkippingEnabled(JNIEnv* env, jobject /* this */) {
// return static_cast<jboolean>(BooleanSetting::FRAME_SKIPPING.getBoolean());
// }
extern " C " JNIEXPORT jboolean JNICALL
Java_org_yuzu_yuzu_1emu_features_settings_model_BooleanSetting_isFrameInterpolationEnabled ( JNIEnv * env , jobject /* this */ ) {
return static_cast < jboolean > ( BooleanSetting : : FRAME_INTERPOLATION . getBoolean ( ) ) ;
}
void RendererVulkan : : InterpolateFrames ( Frame * prev_frame , Frame * interpolated_frame ) {
void RendererVulkan : : InterpolateFrames ( Frame * prev_frame , Frame * interpolated_frame ) {
if ( ! prev_frame | | ! interpolated_frame | | ! prev_frame - > image | | ! interpolated_frame - > image ) {
if ( ! prev_frame | | ! interpolated_frame | | ! prev_frame - > image | | ! interpolated_frame - > image ) {
return ;
return ;
@ -292,30 +257,15 @@ class BooleanSetting {
TransitionImageLayout ( cmdbuf , * interpolated_frame - > image , VK_IMAGE_LAYOUT_GENERAL ) ;
TransitionImageLayout ( cmdbuf , * interpolated_frame - > image , VK_IMAGE_LAYOUT_GENERAL ) ;
} ) ;
} ) ;
}
}
# endif
void RendererVulkan : : Composite ( std : : span < const Tegra : : FramebufferConfig > framebuffers ) {
void RendererVulkan : : Composite ( std : : span < const Tegra : : FramebufferConfig > framebuffers ) {
# ifdef __ANDROID__
static int frame_counter = 0 ;
static int target_fps = 60 ; // Target FPS (30 or 60)
int frame_skip_threshold = 1 ;
bool frame_skipping = false ; //BooleanSetting::FRAME_SKIPPING.getBoolean();
bool frame_interpolation = BooleanSetting : : FRAME_INTERPOLATION . getBoolean ( ) ;
# endif
if ( framebuffers . empty ( ) ) {
if ( framebuffers . empty ( ) ) {
return ;
return ;
}
}
# ifdef __ANDROID__
if ( frame_skipping ) {
frame_skip_threshold = ( target_fps = = 30 ) ? 2 : 2 ;
}
bool frame_interpolation_enabled = Settings : : values . frame_interpolation . GetValue ( ) ;
frame_counter + + ;
if ( frame_counter % frame_skip_threshold ! = 0 ) {
if ( frame_interpolation & & previous_frame ) {
if ( frame_interpolation_enabled & & previous_frame ) {
Frame * interpolated_frame = present_manager . GetRenderFrame ( ) ;
Frame * interpolated_frame = present_manager . GetRenderFrame ( ) ;
InterpolateFrames ( previous_frame , interpolated_frame ) ;
InterpolateFrames ( previous_frame , interpolated_frame ) ;
blit_swapchain . DrawToFrame ( rasterizer , interpolated_frame , framebuffers ,
blit_swapchain . DrawToFrame ( rasterizer , interpolated_frame , framebuffers ,
@ -323,10 +273,11 @@ void RendererVulkan::Composite(std::span<const Tegra::FramebufferConfig> framebu
swapchain . GetImageViewFormat ( ) ) ;
swapchain . GetImageViewFormat ( ) ) ;
scheduler . Flush ( * interpolated_frame - > render_ready ) ;
scheduler . Flush ( * interpolated_frame - > render_ready ) ;
present_manager . Present ( interpolated_frame ) ;
present_manager . Present ( interpolated_frame ) ;
}
// Optionally, update previous_frame here if you want to chain interpolations
previous_frame = interpolated_frame ;
return ;
return ;
}
}
# endif
SCOPE_EXIT {
SCOPE_EXIT {
render_window . OnFrameDisplayed ( ) ;
render_window . OnFrameDisplayed ( ) ;
@ -346,6 +297,11 @@ void RendererVulkan::Composite(std::span<const Tegra::FramebufferConfig> framebu
scheduler . Flush ( * frame - > render_ready ) ;
scheduler . Flush ( * frame - > render_ready ) ;
present_manager . Present ( frame ) ;
present_manager . Present ( frame ) ;
// Store the current frame for interpolation on the next call
if ( frame_interpolation_enabled ) {
previous_frame = frame ;
}
gpu . RendererFrameEndNotify ( ) ;
gpu . RendererFrameEndNotify ( ) ;
rasterizer . TickFrame ( ) ;
rasterizer . TickFrame ( ) ;
}
}