策略抽离

This commit is contained in:
2026-08-02 14:20:27 +08:00
parent 6d000f43b4
commit 2df8959ed6
87 changed files with 2454 additions and 1390 deletions
-194
View File
@@ -1,37 +1,8 @@
#include "Frame_Scheduler.h"
#include <algorithm>
#include <cmath>
#include <utility>
namespace renderive {
namespace {
constexpr double Ratio_Threshold = 1.03;
constexpr int Switch_Samples = 3;
}
void Smoothed_Interval::update(double sample_ms) {
if (sample_ms <= 0.0 || !std::isfinite(sample_ms))
return;
if (!sample_count) {
srtt_ms = sample_ms;
jitter_ms = sample_ms * 0.5;
sample_count = 1;
return;
}
double error = std::abs(sample_ms - srtt_ms);
jitter_ms += 0.25 * (error - jitter_ms);
srtt_ms += 0.125 * (sample_ms - srtt_ms);
++sample_count;
}
double Smoothed_Interval::safe_ms(double jitter_factor) const {
return sample_count ? srtt_ms + jitter_factor * jitter_ms : 0.0;
}
bool Smoothed_Interval::valid() const {
return sample_count > 0;
}
void Frame_Lifecycle_Record::record_renderable_render(const std::string& object_name, const std::string& parent_object_name, int tree_depth, Renderable_Cache_Mode cache_mode, std::uint64_t render_time_ns) {
Renderable_Frame_Stat& stat = renderable_stat(object_name, parent_object_name, tree_depth);
stat.cache_enabled = cache_mode == Renderable_Cache_Mode::Local_Pixel;
@@ -110,169 +81,4 @@ Renderable_Cache_Frame_Stats& Frame_Lifecycle_Record::cache_stat(const std::stri
return renderable_cache_stats.back();
}
void Frame_Feedback_Controller::reset() {
std::uint64_t user_period = state_value.user_period_ns;
*this = Frame_Feedback_Controller();
state_value.user_period_ns = user_period;
refresh_control_snapshot();
}
void Frame_Feedback_Controller::set_max_render_fps(double fps) {
state_value.user_period_ns = fps > 0.0 ? ms_to_ns(1000.0 / fps) : 0;
refresh_control_snapshot();
}
void Frame_Feedback_Controller::on_input_changed(std::uint64_t, std::uint64_t input_version) {
if (input_version)
latest_input_version = input_version;
else
++latest_input_version;
}
void Frame_Feedback_Controller::on_render_started(Frame_Lifecycle_Record& frame, std::uint64_t now_ns) {
last_render_begin_ns = now_ns;
frame.render_begin_ns = now_ns;
frame.wait_21_ns = now_ns > frame.render_role_enter_ns ? now_ns - frame.render_role_enter_ns : 0;
refresh_control_snapshot();
write_state(frame);
}
void Frame_Feedback_Controller::on_render_completed(Frame_Lifecycle_Record& frame) {
std::uint64_t render_duration_ns = frame.render_end_ns > frame.render_begin_ns ? frame.render_end_ns - frame.render_begin_ns : 0;
last_render_begin_ns = frame.render_begin_ns;
render_period.update(static_cast<double>(render_duration_ns + frame.wait_21_ns) / 1000000.0);
refresh_control_snapshot();
write_state(frame);
}
void Frame_Feedback_Controller::on_frame_presented(Frame_Lifecycle_Record& frame) {
std::uint64_t paint_duration_ns = frame.paint_end_ns > frame.paint_begin_ns ? frame.paint_end_ns - frame.paint_begin_ns : 0;
paint_period.update(static_cast<double>(paint_duration_ns + frame.wait_23_ns) / 1000000.0);
frame.outcome = Frame_Outcome::Presented;
refresh_control_snapshot();
write_state(frame);
}
void Frame_Feedback_Controller::on_frame_superseded(Frame_Lifecycle_Record& frame) {
frame.outcome = Frame_Outcome::Superseded;
refresh_control_snapshot();
write_state(frame);
}
void Frame_Feedback_Controller::on_frame_dropped(Frame_Lifecycle_Record& frame, Frame_Outcome outcome) {
frame.outcome = outcome;
refresh_control_snapshot();
write_state(frame);
}
bool Frame_Feedback_Controller::rate_limit_ready(std::uint64_t now_ns) const {
return now_ns >= next_render_time;
}
std::uint64_t Frame_Feedback_Controller::next_render_time_ns() const {
return next_render_time;
}
const Refresh_Control_Snapshot& Frame_Feedback_Controller::state() const {
return state_value;
}
void Frame_Feedback_Controller::write_state(Frame_Lifecycle_Record& frame) const {
frame.refresh = state_value;
}
void Frame_Feedback_Controller::refresh_control_snapshot() {
std::uint64_t render_period_ns = render_period.valid() ? ms_to_ns(render_period.safe_ms(0.5)) : 0;
std::uint64_t paint_period_ns = paint_period.valid() ? ms_to_ns(paint_period.safe_ms(0.5)) : 0;
std::uint64_t user_period_ns = state_value.user_period_ns;
Refresh_Limit_Source candidate = classify_limit_source(render_period_ns, paint_period_ns, user_period_ns);
std::uint64_t candidate_period = 0;
switch (candidate) {
case Refresh_Limit_Source::Render:
candidate_period = render_period_ns;
break;
case Refresh_Limit_Source::Paint:
candidate_period = paint_period_ns;
break;
case Refresh_Limit_Source::User:
candidate_period = user_period_ns;
break;
case Refresh_Limit_Source::Unknown:
break;
}
update_limit_source(candidate, candidate_period);
std::uint64_t target_period = std::max({render_period_ns, paint_period_ns, user_period_ns});
state_value.render_period_ns = render_period_ns;
state_value.paint_period_ns = paint_period_ns;
state_value.target_period_ns = target_period;
if (state_value.source == Refresh_Limit_Source::Unknown)
state_value.source = candidate;
if (state_value.source == Refresh_Limit_Source::User && last_render_begin_ns)
next_render_time = last_render_begin_ns + user_period_ns;
else
next_render_time = 0;
}
Refresh_Limit_Source Frame_Feedback_Controller::classify_limit_source(std::uint64_t render_period_ns, std::uint64_t paint_period_ns, std::uint64_t user_period_ns) const {
if (!render_period_ns && !paint_period_ns)
return user_period_ns ? Refresh_Limit_Source::User : Refresh_Limit_Source::Unknown;
std::uint64_t max_period = std::max({render_period_ns, paint_period_ns, user_period_ns});
if (max_period == user_period_ns && user_period_ns)
return Refresh_Limit_Source::User;
if (max_period == paint_period_ns && paint_period_ns)
return Refresh_Limit_Source::Paint;
if (max_period == render_period_ns && render_period_ns)
return Refresh_Limit_Source::Render;
return Refresh_Limit_Source::Unknown;
}
void Frame_Feedback_Controller::update_limit_source(Refresh_Limit_Source candidate, std::uint64_t candidate_period_ns) {
if (candidate == Refresh_Limit_Source::Unknown)
return;
if (state_value.source == Refresh_Limit_Source::Unknown) {
state_value.source = candidate;
candidate_source = candidate;
candidate_count = 0;
return;
}
std::uint64_t current_period = 0;
switch (state_value.source) {
case Refresh_Limit_Source::Render:
current_period = state_value.render_period_ns;
break;
case Refresh_Limit_Source::Paint:
current_period = state_value.paint_period_ns;
break;
case Refresh_Limit_Source::User:
current_period = state_value.user_period_ns;
break;
case Refresh_Limit_Source::Unknown:
break;
}
if (candidate == state_value.source || (current_period && static_cast<double>(candidate_period_ns) <= static_cast<double>(current_period) * Ratio_Threshold)) {
candidate_source = candidate;
candidate_count = 0;
return;
}
if (candidate != candidate_source) {
candidate_source = candidate;
candidate_count = 1;
return;
}
if (++candidate_count >= Switch_Samples) {
state_value.source = candidate;
candidate_count = 0;
}
}
double Frame_Feedback_Controller::duration_ms(std::uint64_t begin_ns, std::uint64_t end_ns) {
return end_ns > begin_ns ? static_cast<double>(end_ns - begin_ns) / 1000000.0 : 0.0;
}
std::uint64_t Frame_Feedback_Controller::ms_to_ns(double ms) {
if (ms <= 0.0 || !std::isfinite(ms))
return 0;
return static_cast<std::uint64_t>(ms * 1000000.0);
}
} // namespace renderive