Browse Source

Fine-tuning of frame pacing logic

pull/3628/head
MaranBr 1 week ago
committed by crueter
parent
commit
0cc9cd8ce7
  1. 47
      src/video_core/renderer_vulkan/vk_scheduler.h

47
src/video_core/renderer_vulkan/vk_scheduler.h

@ -16,8 +16,8 @@
#include "common/alignment.h" #include "common/alignment.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "common/settings.h"
#include "common/polyfill_thread.h" #include "common/polyfill_thread.h"
#include "common/settings.h"
#include "video_core/renderer_vulkan/vk_master_semaphore.h" #include "video_core/renderer_vulkan/vk_master_semaphore.h"
#include "video_core/vulkan_common/vulkan_wrapper.h" #include "video_core/vulkan_common/vulkan_wrapper.h"
@ -114,29 +114,40 @@ public:
/// Waits for the given GPU tick, optionally pacing frames. /// Waits for the given GPU tick, optionally pacing frames.
void Wait(u64 tick, double target_fps = 0.0) { void Wait(u64 tick, double target_fps = 0.0) {
if (tick > 0) {
if (tick >= master_semaphore->CurrentTick()) {
Flush();
}
master_semaphore->Wait(tick);
}
if (Settings::values.use_speed_limit.GetValue() && target_fps > 0.0) { if (Settings::values.use_speed_limit.GetValue() && target_fps > 0.0) {
const auto now = std::chrono::steady_clock::now();
if (start_time == std::chrono::steady_clock::time_point{} || current_target_fps != target_fps) {
start_time = now;
auto now = std::chrono::steady_clock::now();
if (last_target_fps != target_fps) {
max_frame_count = static_cast<int>(0.1 * target_fps);
frame_interval = std::chrono::duration_cast<std::chrono::steady_clock::duration>(std::chrono::duration<double>(1.0 / target_fps));
last_target_fps = target_fps;
frame_counter = 0; frame_counter = 0;
current_target_fps = target_fps;
start_time = now;
} }
frame_counter++; frame_counter++;
std::chrono::duration<double> frame_interval(1.0 / current_target_fps);
auto target_time = start_time + frame_interval * frame_counter; auto target_time = start_time + frame_interval * frame_counter;
if (target_time > now) {
std::this_thread::sleep_until(target_time);
} else {
start_time = now;
if (target_time >= now) {
auto sleep_time = target_time - now;
if (sleep_time > std::chrono::milliseconds(15)) {
std::this_thread::sleep_for(sleep_time - std::chrono::milliseconds(1));
}
while (std::chrono::steady_clock::now() < target_time) {
#ifdef _WIN32
_mm_pause();
#else
std::this_thread::yield();
#endif
}
} else if (frame_counter > max_frame_count) {
frame_counter = 0; frame_counter = 0;
start_time = now;
} }
} }
if (tick > 0) {
if (tick >= master_semaphore->CurrentTick()) {
Flush();
}
master_semaphore->Wait(tick);
}
} }
/// Returns the master timeline semaphore. /// Returns the master timeline semaphore.
@ -281,9 +292,11 @@ private:
std::condition_variable_any event_cv; std::condition_variable_any event_cv;
std::jthread worker_thread; std::jthread worker_thread;
std::chrono::steady_clock::time_point frame_interval{};
std::chrono::steady_clock::time_point start_time{}; std::chrono::steady_clock::time_point start_time{};
double last_target_fps{};
u64 max_frame_count{};
u64 frame_counter{}; u64 frame_counter{};
double current_target_fps{};
}; };
} // namespace Vulkan } // namespace Vulkan
Loading…
Cancel
Save