mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-04-10 05:28:56 +02:00
[android] Refined cadence for low frame rate; chrono + duration = clamp/ ms response extended
This commit is contained in:
parent
5bce1993e1
commit
c42c67ab85
2 changed files with 36 additions and 24 deletions
|
|
@ -34,6 +34,7 @@ void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) {
|
|||
m_pending_frame_rate_hint_votes = 0;
|
||||
m_smoothed_present_rate = 0.0f;
|
||||
m_last_frame_display_time = {};
|
||||
m_pending_frame_rate_since = {};
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -81,7 +82,7 @@ void EmuWindow_Android::UpdateObservedFrameRate() {
|
|||
const float seconds = frame_time.count();
|
||||
if (seconds > 0.0f) {
|
||||
const float instantaneous_rate = 1.0f / seconds;
|
||||
if (std::isfinite(instantaneous_rate) && instantaneous_rate >= 10.0f &&
|
||||
if (std::isfinite(instantaneous_rate) && instantaneous_rate >= 1.0f &&
|
||||
instantaneous_rate <= 240.0f) {
|
||||
constexpr float SmoothingFactor = 0.15f;
|
||||
if (m_smoothed_present_rate <= 0.0f) {
|
||||
|
|
@ -97,23 +98,14 @@ void EmuWindow_Android::UpdateObservedFrameRate() {
|
|||
}
|
||||
|
||||
float EmuWindow_Android::QuantizeFrameRateHint(float frame_rate) {
|
||||
if (!std::isfinite(frame_rate) || frame_rate < 20.0f) {
|
||||
if (!std::isfinite(frame_rate) || frame_rate <= 0.0f) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
frame_rate = std::clamp(frame_rate, 20.0f, 240.0f);
|
||||
frame_rate = std::clamp(frame_rate, 1.0f, 240.0f);
|
||||
|
||||
constexpr std::array CandidateRates{24.0f, 30.0f, 36.0f, 40.0f, 45.0f, 48.0f,
|
||||
60.0f, 72.0f, 80.0f, 90.0f, 96.0f, 120.0f,
|
||||
144.0f, 165.0f, 180.0f, 200.0f, 240.0f};
|
||||
const auto best = std::min_element(CandidateRates.begin(), CandidateRates.end(),
|
||||
[frame_rate](float lhs, float rhs) {
|
||||
return std::fabs(frame_rate - lhs) <
|
||||
std::fabs(frame_rate - rhs);
|
||||
});
|
||||
const float best_rate = *best;
|
||||
const float tolerance = std::max(best_rate * 0.12f, 4.0f);
|
||||
return std::fabs(frame_rate - best_rate) <= tolerance ? best_rate : best_rate;
|
||||
constexpr float Step = 0.5f;
|
||||
return std::round(frame_rate / Step) * Step;
|
||||
}
|
||||
|
||||
float EmuWindow_Android::GetFrameTimeVerifiedHint() const {
|
||||
|
|
@ -129,10 +121,7 @@ float EmuWindow_Android::GetFrameTimeVerifiedHint() const {
|
|||
|
||||
const float verified_rate =
|
||||
std::clamp(60.0f / static_cast<float>(frame_time_scale), 0.0f, 240.0f);
|
||||
const float verified_hint = QuantizeFrameRateHint(verified_rate);
|
||||
|
||||
// Frame-time verification is most useful to separate stable 30/60 FPS content.
|
||||
return verified_hint <= 60.0f ? verified_hint : 0.0f;
|
||||
return QuantizeFrameRateHint(verified_rate);
|
||||
}
|
||||
|
||||
float EmuWindow_Android::GetFrameRateHint() const {
|
||||
|
|
@ -146,15 +135,21 @@ float EmuWindow_Android::GetFrameRateHint() const {
|
|||
}
|
||||
}
|
||||
|
||||
if (frame_time_verified_hint > 0.0f) {
|
||||
return frame_time_verified_hint;
|
||||
}
|
||||
|
||||
const float observed_hint = QuantizeFrameRateHint(observed_rate);
|
||||
if (observed_hint > 0.0f) {
|
||||
if (frame_time_verified_hint > 0.0f) {
|
||||
const float tolerance = std::max(observed_hint * 0.20f, 3.0f);
|
||||
if (std::fabs(observed_hint - frame_time_verified_hint) <= tolerance) {
|
||||
return QuantizeFrameRateHint((observed_hint + frame_time_verified_hint) * 0.5f);
|
||||
}
|
||||
}
|
||||
return observed_hint;
|
||||
}
|
||||
|
||||
if (frame_time_verified_hint > 0.0f) {
|
||||
return frame_time_verified_hint;
|
||||
}
|
||||
|
||||
constexpr float NominalFrameRate = 60.0f;
|
||||
if (!Settings::values.use_speed_limit.GetValue()) {
|
||||
return NominalFrameRate;
|
||||
|
|
@ -176,28 +171,43 @@ void EmuWindow_Android::UpdateFrameRateHint() {
|
|||
return;
|
||||
}
|
||||
|
||||
const auto now = Clock::now();
|
||||
const float frame_rate_hint = GetFrameRateHint();
|
||||
if (std::fabs(frame_rate_hint - m_last_frame_rate_hint) < 0.01f) {
|
||||
m_pending_frame_rate_hint = frame_rate_hint;
|
||||
m_pending_frame_rate_hint_votes = 0;
|
||||
m_pending_frame_rate_since = {};
|
||||
return;
|
||||
}
|
||||
|
||||
if (frame_rate_hint == 0.0f) {
|
||||
m_pending_frame_rate_hint = frame_rate_hint;
|
||||
m_pending_frame_rate_hint_votes = 0;
|
||||
m_pending_frame_rate_since = now;
|
||||
} else if (m_last_frame_rate_hint >= 0.0f) {
|
||||
if (std::fabs(frame_rate_hint - m_pending_frame_rate_hint) >= 0.01f) {
|
||||
m_pending_frame_rate_hint = frame_rate_hint;
|
||||
m_pending_frame_rate_hint_votes = 1;
|
||||
m_pending_frame_rate_since = now;
|
||||
return;
|
||||
}
|
||||
|
||||
++m_pending_frame_rate_hint_votes;
|
||||
constexpr std::uint32_t StableVoteThreshold = 12;
|
||||
if (m_pending_frame_rate_hint_votes < StableVoteThreshold) {
|
||||
if (m_pending_frame_rate_since.time_since_epoch().count() == 0) {
|
||||
m_pending_frame_rate_since = now;
|
||||
}
|
||||
|
||||
const auto stable_for = now - m_pending_frame_rate_since;
|
||||
const float reference_rate = std::max(frame_rate_hint, 1.0f);
|
||||
const auto stable_duration = std::chrono::duration_cast<Clock::duration>(
|
||||
std::chrono::duration<float>(std::clamp(3.0f / reference_rate, 0.15f, 0.40f)));
|
||||
constexpr std::uint32_t MinStableVotes = 3;
|
||||
|
||||
if (m_pending_frame_rate_hint_votes < MinStableVotes || stable_for < stable_duration) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
m_pending_frame_rate_since = now;
|
||||
}
|
||||
|
||||
using SetFrameRateWithChangeStrategyFn =
|
||||
|
|
@ -222,6 +232,7 @@ void EmuWindow_Android::UpdateFrameRateHint() {
|
|||
m_last_frame_rate_hint = frame_rate_hint;
|
||||
m_pending_frame_rate_hint = frame_rate_hint;
|
||||
m_pending_frame_rate_hint_votes = 0;
|
||||
m_pending_frame_rate_since = {};
|
||||
}
|
||||
|
||||
EmuWindow_Android::EmuWindow_Android(ANativeWindow* surface,
|
||||
|
|
|
|||
|
|
@ -73,5 +73,6 @@ private:
|
|||
float m_pending_frame_rate_hint = -1.0f;
|
||||
float m_smoothed_present_rate = 0.0f;
|
||||
Clock::time_point m_last_frame_display_time{};
|
||||
Clock::time_point m_pending_frame_rate_since{};
|
||||
std::uint32_t m_pending_frame_rate_hint_votes = 0;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue