From ae69f1e6d8839edbda662a982211f5cf50083c7e Mon Sep 17 00:00:00 2001 From: Gamer64 <76565986+Gamer64ytb@users.noreply.github.com> Date: Thu, 28 Aug 2025 03:48:30 +0200 Subject: [PATCH] [renderer_vulkan]: Make a working toggle --- src/common/settings.h | 4 - .../renderer_vulkan/renderer_vulkan.cpp | 169 +++++++----------- 2 files changed, 64 insertions(+), 109 deletions(-) diff --git a/src/common/settings.h b/src/common/settings.h index 27196fbd69..a7b803f3a6 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -334,12 +334,8 @@ struct Values { SwitchableSetting vulkan_device{linkage, 0, "vulkan_device", Category::Renderer, Specialization::RuntimeList}; SwitchableSetting enable_raii{linkage, false, "enable_raii", Category::Renderer}; -#ifdef __ANDROID__ SwitchableSetting frame_interpolation{linkage, true, "frame_interpolation", Category::Renderer, Specialization::RuntimeList}; - SwitchableSetting frame_skipping{linkage, false, "frame_skipping", Category::Renderer, - Specialization::RuntimeList}; -#endif SwitchableSetting use_disk_shader_cache{linkage, true, "use_disk_shader_cache", Category::Renderer}; SwitchableSetting optimize_spirv_output{linkage, diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index a91fba6725..2189c4bc08 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -38,9 +38,7 @@ #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 { @@ -189,133 +187,95 @@ RendererVulkan::~RendererVulkan() { 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) {} +void RendererVulkan::InterpolateFrames(Frame* prev_frame, Frame* interpolated_frame) { + if (!prev_frame || !interpolated_frame || !prev_frame->image || !interpolated_frame->image) { + return; + } - [[nodiscard]] bool getBoolean() const { - return value; - } - - void setBoolean(bool new_value) { - value = new_value; - } - - private: - bool value; + const auto& framebuffer_layout = render_window.GetFramebufferLayout(); + // Fixed aggressive downscale (50%) + VkExtent2D dst_extent{ + .width = framebuffer_layout.width / 2, + .height = framebuffer_layout.height / 2 }; - // 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(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(BooleanSetting::FRAME_INTERPOLATION.getBoolean()); + // Check if we need to recreate the destination frame + bool needs_recreation = false; // Only recreate when necessary + if (!interpolated_frame->image_view) { + needs_recreation = true; // Need to create initially + } else { + // Check if dimensions have changed + if (interpolated_frame->framebuffer) { + needs_recreation = (framebuffer_layout.width / 2 != dst_extent.width) || + (framebuffer_layout.height / 2 != dst_extent.height); + } else { + needs_recreation = true; + } } - void RendererVulkan::InterpolateFrames(Frame* prev_frame, Frame* interpolated_frame) { - if (!prev_frame || !interpolated_frame || !prev_frame->image || !interpolated_frame->image) { - return; - } + if (needs_recreation) { + interpolated_frame->image = CreateWrappedImage(memory_allocator, dst_extent, swapchain.GetImageViewFormat()); + interpolated_frame->image_view = CreateWrappedImageView(device, interpolated_frame->image, swapchain.GetImageViewFormat()); + interpolated_frame->framebuffer = blit_swapchain.CreateFramebuffer( + Layout::FramebufferLayout{dst_extent.width, dst_extent.height}, + *interpolated_frame->image_view, + swapchain.GetImageViewFormat()); + } - const auto& framebuffer_layout = render_window.GetFramebufferLayout(); - // Fixed aggressive downscale (50%) - VkExtent2D dst_extent{ - .width = framebuffer_layout.width / 2, - .height = framebuffer_layout.height / 2 + scheduler.RequestOutsideRenderPassOperationContext(); + scheduler.Record([&](vk::CommandBuffer cmdbuf) { + // Transition images to transfer layouts + TransitionImageLayout(cmdbuf, *prev_frame->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + TransitionImageLayout(cmdbuf, *interpolated_frame->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + + // Perform the downscale blit + VkImageBlit blit_region{}; + blit_region.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; + blit_region.srcOffsets[0] = {0, 0, 0}; + blit_region.srcOffsets[1] = { + static_cast(framebuffer_layout.width), + static_cast(framebuffer_layout.height), + 1 + }; + blit_region.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; + blit_region.dstOffsets[0] = {0, 0, 0}; + blit_region.dstOffsets[1] = { + static_cast(dst_extent.width), + static_cast(dst_extent.height), + 1 }; - // Check if we need to recreate the destination frame - bool needs_recreation = false; // Only recreate when necessary - if (!interpolated_frame->image_view) { - needs_recreation = true; // Need to create initially - } else { - // Check if dimensions have changed - if (interpolated_frame->framebuffer) { - needs_recreation = (framebuffer_layout.width / 2 != dst_extent.width) || - (framebuffer_layout.height / 2 != dst_extent.height); - } else { - needs_recreation = true; - } - } + // Using the wrapper's BlitImage with proper parameters + cmdbuf.BlitImage( + *prev_frame->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + *interpolated_frame->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + blit_region, VK_FILTER_NEAREST + ); - if (needs_recreation) { - interpolated_frame->image = CreateWrappedImage(memory_allocator, dst_extent, swapchain.GetImageViewFormat()); - interpolated_frame->image_view = CreateWrappedImageView(device, interpolated_frame->image, swapchain.GetImageViewFormat()); - interpolated_frame->framebuffer = blit_swapchain.CreateFramebuffer( - Layout::FramebufferLayout{dst_extent.width, dst_extent.height}, - *interpolated_frame->image_view, - swapchain.GetImageViewFormat()); - } - - scheduler.RequestOutsideRenderPassOperationContext(); - scheduler.Record([&](vk::CommandBuffer cmdbuf) { - // Transition images to transfer layouts - TransitionImageLayout(cmdbuf, *prev_frame->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - TransitionImageLayout(cmdbuf, *interpolated_frame->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - - // Perform the downscale blit - VkImageBlit blit_region{}; - blit_region.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; - blit_region.srcOffsets[0] = {0, 0, 0}; - blit_region.srcOffsets[1] = { - static_cast(framebuffer_layout.width), - static_cast(framebuffer_layout.height), - 1 - }; - blit_region.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; - blit_region.dstOffsets[0] = {0, 0, 0}; - blit_region.dstOffsets[1] = { - static_cast(dst_extent.width), - static_cast(dst_extent.height), - 1 - }; - - // Using the wrapper's BlitImage with proper parameters - cmdbuf.BlitImage( - *prev_frame->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - *interpolated_frame->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - blit_region, VK_FILTER_NEAREST - ); - - // Transition back to general layout - TransitionImageLayout(cmdbuf, *prev_frame->image, VK_IMAGE_LAYOUT_GENERAL); - TransitionImageLayout(cmdbuf, *interpolated_frame->image, VK_IMAGE_LAYOUT_GENERAL); - }); - } -#endif + // Transition back to general layout + TransitionImageLayout(cmdbuf, *prev_frame->image, VK_IMAGE_LAYOUT_GENERAL); + TransitionImageLayout(cmdbuf, *interpolated_frame->image, VK_IMAGE_LAYOUT_GENERAL); + }); +} void RendererVulkan::Composite(std::span 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 + bool frame_skipping = true; if (framebuffers.empty()) { return; } - #ifdef __ANDROID__ if (frame_skipping) { frame_skip_threshold = (target_fps == 30) ? 2 : 2; } frame_counter++; if (frame_counter % frame_skip_threshold != 0) { - if (frame_interpolation && previous_frame) { + if (Settings::values.frame_interpolation.GetValue() && previous_frame) { Frame* interpolated_frame = present_manager.GetRenderFrame(); InterpolateFrames(previous_frame, interpolated_frame); blit_swapchain.DrawToFrame(rasterizer, interpolated_frame, framebuffers, @@ -326,7 +286,6 @@ void RendererVulkan::Composite(std::span framebu } return; } - #endif SCOPE_EXIT { render_window.OnFrameDisplayed();