mirror of
https://github.com/mitch030504/Wiicompiled_VR_Frame.git
synced 2026-10-06 06:00:25 +02:00
Ask the headset for a configured refresh rate, 120 Hz on the Steam Frame
[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
This commit is contained in:
8 files changed
+215
-1
No files matched your search
@@ -63,6 +63,7 @@ struct RuntimeUserConfig {
|
||||
std::optional<std::string> vrMirrorView;
|
||||
std::optional<std::string> vrControllerMode;
|
||||
std::optional<uint32_t> vrFrameInterpolationFps;
|
||||
std::optional<uint32_t> vrRefreshRate;
|
||||
std::optional<bool> vrFirstPerson;
|
||||
std::optional<bool> vrFirstPersonToggleClick;
|
||||
std::optional<float> vrFirstPersonUnitsPerMeter;
|
||||
@@ -281,6 +282,25 @@ inline bool IsSupportedVrPerformanceLevel(std::string_view value) {
|
||||
return value == "default" || value == "power_savings" || value == "sustained_low" ||
|
||||
value == "sustained_high" || value == "boost";
|
||||
}
|
||||
// The display refresh rate asked of the OpenXR runtime (XR_FB_display_refresh_rate), in Hz, each
|
||||
// time the session starts and whenever the setting changes; 0 leaves the headset's own rate. 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 starts at 120; elsewhere the
|
||||
// headset's own setting stays in charge. A runtime without the extension, or one that declines the
|
||||
// rate, keeps its own.
|
||||
#if defined(MKW_HEADSET_STEAM_FRAME)
|
||||
inline constexpr uint32_t kVrRefreshRateDefault = 120;
|
||||
#define MKW_VR_REFRESH_RATE_DEFAULT_TEXT "120"
|
||||
#else
|
||||
inline constexpr uint32_t kVrRefreshRateDefault = 0;
|
||||
#define MKW_VR_REFRESH_RATE_DEFAULT_TEXT "0"
|
||||
#endif
|
||||
inline constexpr uint32_t kVrRefreshRateMin = 60;
|
||||
inline constexpr uint32_t kVrRefreshRateMax = 240;
|
||||
|
||||
inline bool IsSupportedVrRefreshRate(uint32_t value) {
|
||||
return value == 0 || (value >= kVrRefreshRateMin && value <= kVrRefreshRateMax);
|
||||
}
|
||||
// Fixed foveated rendering of the immersive eyes on the Quest, in the order of
|
||||
// aurora_set_stereo_foveation's levels: the periphery is shaded in 2x2, then
|
||||
// 4x4 pixel blocks, the higher the level the closer to the centre. Whether the
|
||||
@@ -545,6 +565,11 @@ inline void EnsureConfigFile() {
|
||||
"controller_mode = \"wii_remote\"\n"
|
||||
"# VR interpolation: 0 = Off, 1 = Auto, or 72/90/120 FPS. Live.\n"
|
||||
"frame_interpolation_fps = 0\n"
|
||||
"# Display refresh rate asked of the headset, in Hz (72, 90, 120,\n"
|
||||
"# 144, ...), or 0 to leave the headset's own setting. The game runs\n"
|
||||
"# at 60, so 120 shows every frame twice. Only runtimes that let apps\n"
|
||||
"# choose (XR_FB_display_refresh_rate) take it. Live.\n"
|
||||
"refresh_rate = " MKW_VR_REFRESH_RATE_DEFAULT_TEXT "\n"
|
||||
"render_scale = " MKW_VR_RENDER_SCALE_DEFAULT_TEXT "\n"
|
||||
"world_units_per_meter = 500.0\n"
|
||||
"hud_distance_meters = 2.0\n"
|
||||
@@ -872,6 +897,9 @@ inline RuntimeUserConfig ParseConfigDocument(const toml::value& document) {
|
||||
value && IsSupportedVrControllerMode(*value)) {
|
||||
config.vrControllerMode = *value;
|
||||
}
|
||||
if (auto value = FindConfigUint(document, "vr", "refresh_rate"); value && IsSupportedVrRefreshRate(*value)) {
|
||||
config.vrRefreshRate = *value;
|
||||
}
|
||||
config.vrFrameInterpolationFps = FindConfigValue<uint32_t>(document, "vr", "frame_interpolation_fps");
|
||||
if (!config.vrFrameInterpolationFps) {
|
||||
// Migrate the initial experimental checkbox to Auto.
|
||||
@@ -1241,6 +1269,14 @@ inline bool SetVrFrameInterpolationFps(uint32_t value) {
|
||||
return WriteSetting("vr", "frame_interpolation_fps", std::to_string(value));
|
||||
}
|
||||
|
||||
inline bool SetVrRefreshRate(uint32_t value) {
|
||||
if (!IsSupportedVrRefreshRate(value)) {
|
||||
return false;
|
||||
}
|
||||
Mutable().vrRefreshRate = value;
|
||||
return WriteSetting("vr", "refresh_rate", std::to_string(value));
|
||||
}
|
||||
|
||||
inline bool SetVrFirstPersonRotation(std::string value) {
|
||||
if (!IsSupportedVrFirstPersonRotation(value)) {
|
||||
return false;
|
||||
@@ -1743,6 +1779,11 @@ inline uint32_t VrFrameInterpolationFps() {
|
||||
return mkw::vr::NormalizeFrameInterpolationFps(Get().vrFrameInterpolationFps.value_or(0));
|
||||
}
|
||||
|
||||
inline uint32_t VrRefreshRate(uint32_t fallback = kVrRefreshRateDefault) {
|
||||
const uint32_t value = Get().vrRefreshRate.value_or(fallback);
|
||||
return IsSupportedVrRefreshRate(value) ? value : 0;
|
||||
}
|
||||
|
||||
inline bool DiagnosticsOpenXRLogging(bool fallback = false) {
|
||||
return Get().diagnosticsOpenXRLogging.value_or(fallback);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,21 @@ 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 {
|
||||
|
||||
Reference in new issue
Block a user