diff --git a/src/common/settings.h b/src/common/settings.h index 9a7d3a30d3..0538c8deca 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -464,7 +464,10 @@ struct Values { FramePacingMode::Target_Auto, FramePacingMode::Target_240, "frame_pacing_mode", - Category::RendererAdvanced}; + Category::RendererAdvanced, + Specialization::Default, + true, + true}; SwitchableSetting astc_recompression{linkage, AstcRecompression::Uncompressed, diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp index 2a69d6d244..aafcfdf65b 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.cpp +++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp @@ -347,7 +347,7 @@ void Scheduler::EndRenderPass() Record([num_images = num_renderpass_images, images = renderpass_images, ranges = renderpass_image_ranges](vk::CommandBuffer cmdbuf) { - std::vector barriers(num_images); + std::array barriers; VkPipelineStageFlags src_stages = 0; for (size_t i = 0; i < num_images; ++i) { const VkImageSubresourceRange& range = ranges[i]; diff --git a/src/video_core/renderer_vulkan/vk_scheduler.h b/src/video_core/renderer_vulkan/vk_scheduler.h index fb0ac9b008..9f388fb1ac 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.h +++ b/src/video_core/renderer_vulkan/vk_scheduler.h @@ -115,28 +115,23 @@ public: /// Waits for the given GPU tick, optionally pacing frames. void Wait(u64 tick, double target_fps = 0.0) { if (Settings::values.use_speed_limit.GetValue() && target_fps > 0.0) { - auto frame_duration = std::chrono::duration_cast(std::chrono::duration(1.0 / target_fps)); - auto now = std::chrono::steady_clock::now(); - if (now < next_frame_time) { - std::this_thread::sleep_until(next_frame_time); - next_frame_time += frame_duration; - } else { - next_frame_time = now + frame_duration; + if (last_frame_time == std::chrono::steady_clock::time_point{}) { + last_frame_time = std::chrono::steady_clock::now(); } + auto frame_duration = std::chrono::duration(1.0 / target_fps); + auto elapsed = std::chrono::steady_clock::now() - last_frame_time; + auto sleep_time = frame_duration - elapsed; + auto sleep_time_ms = std::chrono::duration_cast(sleep_time).count(); + if (sleep_time_ms > 0) { + std::this_thread::sleep_for(std::chrono::milliseconds(sleep_time_ms)); + } + last_frame_time = std::chrono::steady_clock::now(); } - if (tick > master_semaphore->CurrentTick() && !chunk->Empty()) { - Flush(); - } - master_semaphore->Wait(tick); - } - - /// Resets the frame pacing state by setting the next frame time. - void ResetFramePacing(double target_fps = 0.0) { - if (target_fps > 0.0) { - auto frame_duration = std::chrono::duration_cast(std::chrono::duration(1.0 / target_fps)); - next_frame_time = std::chrono::steady_clock::now() + frame_duration; - } else { - next_frame_time = std::chrono::steady_clock::time_point{}; + if (tick > 0) { + if (tick >= master_semaphore->CurrentTick()) { + Flush(); + } + master_semaphore->Wait(tick); } } @@ -282,7 +277,7 @@ private: std::condition_variable_any event_cv; std::jthread worker_thread; - std::chrono::steady_clock::time_point next_frame_time{}; + std::chrono::steady_clock::time_point last_frame_time{}; }; } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp index 7e7e67639d..0370e02fa7 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.cpp +++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp @@ -146,25 +146,6 @@ void Swapchain::Create( { is_outdated = false; is_suboptimal = false; - - switch (Settings::values.frame_pacing_mode.GetValue()) { - case Settings::FramePacingMode::Target_Auto: - scheduler.ResetFramePacing(); - break; - case Settings::FramePacingMode::Target_30: - scheduler.ResetFramePacing(30.0); - break; - case Settings::FramePacingMode::Target_60: - scheduler.ResetFramePacing(60.0); - break; - case Settings::FramePacingMode::Target_120: - scheduler.ResetFramePacing(120.0); - break; - case Settings::FramePacingMode::Target_240: - scheduler.ResetFramePacing(240.0); - break; - } - width = width_; height = height_; #ifdef ANDROID @@ -213,24 +194,22 @@ bool Swapchain::AcquireNextImage() { break; } - if (resource_ticks[image_index] != 0 && !scheduler.IsFree(resource_ticks[image_index])) { - switch (Settings::values.frame_pacing_mode.GetValue()) { - case Settings::FramePacingMode::Target_Auto: - scheduler.Wait(resource_ticks[image_index]); - break; - case Settings::FramePacingMode::Target_30: - scheduler.Wait(resource_ticks[image_index], 30.0); - break; - case Settings::FramePacingMode::Target_60: - scheduler.Wait(resource_ticks[image_index], 60.0); - break; - case Settings::FramePacingMode::Target_120: - scheduler.Wait(resource_ticks[image_index], 120.0); - break; - case Settings::FramePacingMode::Target_240: - scheduler.Wait(resource_ticks[image_index], 240.0); - break; - } + switch (Settings::values.frame_pacing_mode.GetValue()) { + case Settings::FramePacingMode::Target_Auto: + scheduler.Wait(resource_ticks[image_index]); + break; + case Settings::FramePacingMode::Target_30: + scheduler.Wait(resource_ticks[image_index], 30.0); + break; + case Settings::FramePacingMode::Target_60: + scheduler.Wait(resource_ticks[image_index], 60.0); + break; + case Settings::FramePacingMode::Target_120: + scheduler.Wait(resource_ticks[image_index], 120.0); + break; + case Settings::FramePacingMode::Target_240: + scheduler.Wait(resource_ticks[image_index], 240.0); + break; } resource_ticks[image_index] = scheduler.CurrentTick();