mirror of
https://github.com/mitch030504/Wiicompiled_VR_Frame.git
synced 2026-10-06 01:00:14 +02:00
[vr] refresh_rate (Hz, 0 = the headset's own) is requested through XR_FB_display_refresh_rate each time the session starts running and whenever the setting changes, matched against the runtime's own list within half a hertz. Setting it back to 0 restores the rate the session started at. A rate that is not offered, or one the runtime declines, is logged and changes nothing. The game renders 60 frames a second, so at 120 Hz every frame shows for exactly two refreshes, where 72 or 90 Hz hold some frames longer than others. The Steam Frame build defaults to 120; every other build keeps the headset's own rate unless the player picks one. The F10/headset panel and the Android launcher's Headset section offer the choice; the interpolation tooltip points at it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019HBRGKTE1GnN2ah8gcZKr3
57 lines
1.9 KiB
C++
57 lines
1.9 KiB
C++
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
#pragma once
|
|
|
|
#include <algorithm>
|
|
#include <cstdint>
|
|
|
|
namespace mkw::vr {
|
|
inline uint32_t NormalizeFrameInterpolationFps(uint32_t value) noexcept {
|
|
return value == 1 || value == 72 || value == 90 || value == 120 ? value : 0;
|
|
}
|
|
|
|
// The display refresh rate to ask the runtime for ([vr] refresh_rate): the one it lists within half
|
|
// a hertz of `requested` (runtimes report 119.9 or 120.00001 for 120), or 0 when none is close.
|
|
inline float MatchDisplayRefreshRate(const float* rates, uint32_t count, float requested) noexcept {
|
|
float best = 0.0f;
|
|
float best_distance = 0.5f;
|
|
for (uint32_t i = 0; i < count; ++i) {
|
|
const float distance = rates[i] > requested ? rates[i] - requested : requested - rates[i];
|
|
if (rates[i] > 0.0f && distance <= best_distance) {
|
|
best = rates[i];
|
|
best_distance = distance;
|
|
}
|
|
}
|
|
return best;
|
|
}
|
|
|
|
// A render-rate ceiling on the compositor's own display-time grid. Auto (1)
|
|
// renders every tick. Fixed targets cannot increase the physical refresh rate.
|
|
class FrameInterpolationPacing {
|
|
public:
|
|
bool ShouldRender(int64_t display_time, uint32_t target) noexcept {
|
|
if (target != target_ || display_time <= last_time_) {
|
|
next_time_ = 0;
|
|
target_ = target;
|
|
}
|
|
last_time_ = display_time;
|
|
if (target == 0 || target == 1) {
|
|
next_time_ = 0;
|
|
return true;
|
|
}
|
|
if (next_time_ != 0 && display_time + 1'000 < next_time_) return false;
|
|
const int64_t interval = 1'000'000'000 / target;
|
|
if (next_time_ == 0 || display_time - next_time_ > interval * 2) {
|
|
next_time_ = display_time + interval;
|
|
} else {
|
|
next_time_ += interval;
|
|
}
|
|
return true;
|
|
}
|
|
void Reset() noexcept { *this = {}; }
|
|
private:
|
|
int64_t next_time_ = 0;
|
|
int64_t last_time_ = 0;
|
|
uint32_t target_ = 0;
|
|
};
|
|
} // namespace mkw::vr
|