Here we go again

This commit is contained in:
MaranBr 2026-02-11 14:43:34 -04:00 committed by crueter
parent 114cd4e703
commit 452a422f36
6 changed files with 47 additions and 32 deletions

View File

@ -437,7 +437,7 @@ struct Values {
SwitchableSetting<FramePacingMode, true> frame_pacing_mode{linkage,
FramePacingMode::Target_Auto,
FramePacingMode::Target_Auto,
FramePacingMode::Target_120,
FramePacingMode::Target_240,
"frame_pacing_mode",
Category::RendererAdvanced};

View File

@ -129,7 +129,7 @@ ENUM(TimeZone, Auto, Default, Cet, Cst6Cdt, Cuba, Eet, Egypt, Eire, Est, Est5Edt
ENUM(AnisotropyMode, Automatic, Default, X2, X4, X8, X16, X32, X64, None);
ENUM(AstcDecodeMode, Cpu, Gpu, CpuAsynchronous);
ENUM(AstcRecompression, Uncompressed, Bc1, Bc3);
ENUM(FramePacingMode, Target_Auto, Target_30, Target_60, Target_120);
ENUM(FramePacingMode, Target_Auto, Target_30, Target_60, Target_120, Target_240);
ENUM(VSyncMode, Immediate, Mailbox, Fifo, FifoRelaxed);
ENUM(VramUsageMode, Conservative, Aggressive);
ENUM(RendererBackend, OpenGL_GLSL, Vulkan, Null, OpenGL_GLASM, OpenGL_SPIRV);

View File

@ -505,6 +505,7 @@ std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QObject* parent)
PAIR(FramePacingMode, Target_30, tr("30 FPS")),
PAIR(FramePacingMode, Target_60, tr("60 FPS")),
PAIR(FramePacingMode, Target_120, tr("120 FPS")),
PAIR(FramePacingMode, Target_240, tr("240 FPS")),
}});
translations->insert({Settings::EnumMetadata<Settings::VramUsageMode>::Index(),
{

View File

@ -347,7 +347,7 @@ void Scheduler::EndRenderPass()
Record([num_images = num_renderpass_images,
images = renderpass_images,
ranges = renderpass_image_ranges](vk::CommandBuffer cmdbuf) {
std::array<VkImageMemoryBarrier, 9> barriers;
std::vector<VkImageMemoryBarrier> barriers(num_images);
VkPipelineStageFlags src_stages = 0;
for (size_t i = 0; i < num_images; ++i) {
const VkImageSubresourceRange& range = ranges[i];

View File

@ -111,37 +111,34 @@ public:
return master_semaphore->IsFree(tick);
}
/// Waits for the given tick to trigger on the GPU.
void Wait(u64 tick) {
if (tick >= master_semaphore->CurrentTick()) {
// Make sure we are not waiting for the current tick without signalling
/// 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::steady_clock::duration>(std::chrono::duration<double>(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 (tick > master_semaphore->CurrentTick() && !chunk->Empty()) {
Flush();
}
master_semaphore->Wait(tick);
}
/// Waits until the next game frame based on the current game FPS.
void WaitFPS(u64 tick, double target_fps) {
if (master_semaphore->CurrentTick() >= tick) {
return;
}
const auto frame_duration = std::chrono::duration_cast<std::chrono::steady_clock::duration>(std::chrono::duration<double>(1.0 / target_fps));
const auto now = std::chrono::steady_clock::now();
if (next_frame_time == std::chrono::steady_clock::time_point{}) {
next_frame_time = now;
}
next_frame_time += frame_duration;
if (next_frame_time > now) {
std::this_thread::sleep_until(next_frame_time);
/// Resets the frame pacing state by updating the next frame time to agora
void ResetFramePacing(double target_fps = 0.0) {
if (target_fps > 0.0) {
auto frame_duration = std::chrono::duration_cast<std::chrono::steady_clock::duration>(std::chrono::duration<double>(1.0 / target_fps));
next_frame_time = std::chrono::steady_clock::now() + frame_duration;
} else {
next_frame_time = now;
next_frame_time = std::chrono::steady_clock::time_point{};
}
}
void ResetFramePacing() {
next_frame_time = std::chrono::steady_clock::now();
}
/// Returns the master timeline semaphore.
[[nodiscard]] MasterSemaphore& GetMasterSemaphore() const noexcept {
return *master_semaphore;

View File

@ -147,7 +147,23 @@ void Swapchain::Create(
is_outdated = false;
is_suboptimal = false;
scheduler.ResetFramePacing();
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_;
@ -197,21 +213,22 @@ bool Swapchain::AcquireNextImage() {
break;
}
if (!Settings::values.use_speed_limit.GetValue()) {
scheduler.Wait(resource_ticks[image_index]);
} else {
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.WaitFPS(resource_ticks[image_index], 30.0);
scheduler.Wait(resource_ticks[image_index], 30.0);
break;
case Settings::FramePacingMode::Target_60:
scheduler.WaitFPS(resource_ticks[image_index], 60.0);
scheduler.Wait(resource_ticks[image_index], 60.0);
break;
case Settings::FramePacingMode::Target_120:
scheduler.WaitFPS(resource_ticks[image_index], 120.0);
scheduler.Wait(resource_ticks[image_index], 120.0);
break;
case Settings::FramePacingMode::Target_240:
scheduler.Wait(resource_ticks[image_index], 240.0);
break;
}
}