Give the Steam Frame build its own passthrough default

SteamVR has no XR_FB_passthrough, so the Steam Frame build neither asks
for it nor offers the setting: [vr] passthrough defaults to false there,
and the F10/headset panel and the launcher hide the switch. The Frame
keeps the Android defaults that suit it (render scale 0.8, foveation
medium, the GX thread, object culling, performance level boost) and
starts at 120 Hz (previous commit).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019HBRGKTE1GnN2ah8gcZKr3
This commit is contained in:
Claude committed 2026-10-04 08:34:04 +00:00
1 parent 8b98330485
commit e626e0eceb
5 files changed
+41 -12

No files matched your search

@@ -286,11 +286,14 @@ class SettingsPage(
format = { "%.1f m".format(it) },
write = { c, value -> c.setFloat("vr", "hud_width_meters", value) },
)
toggle(
R.string.vr_passthrough, R.string.vr_passthrough_helper,
read = { it.bool("vr", "passthrough") ?: true },
write = { c, value -> c.setBool("vr", "passthrough", value) },
)
// Horizon OS's XR_FB_passthrough; SteamVR on the Steam Frame has no such layer.
if (!BuildConfig.STEAM_FRAME) {
toggle(
R.string.vr_passthrough, R.string.vr_passthrough_helper,
read = { it.bool("vr", "passthrough") ?: true },
write = { c, value -> c.setBool("vr", "passthrough", value) },
)
}
}
}
+15 -6
View File
@@ -189,8 +189,9 @@ inline constexpr uint32_t kPostProcessingBloomPath = 0x10u;
inline constexpr uint32_t kDisabledPostProcessingPathsDefault = kPostProcessingBloomPath;
// Headset eye size as a fraction of what the OpenXR runtime recommends. A
// standalone headset renders on a mobile GPU, so the Quest starts below it;
// the launcher's first Config.toml (GameStorage.kt) writes the same value.
// standalone headset renders on a mobile GPU, so the Quest and the Steam Frame
// start below it; the launcher's first Config.toml (GameStorage.kt) writes the
// same value.
#if defined(__ANDROID__)
inline constexpr float kVrRenderScaleDefault = 0.8f;
#define MKW_VR_RENDER_SCALE_DEFAULT_TEXT "0.8"
@@ -306,7 +307,8 @@ inline bool IsSupportedVrRefreshRate(uint32_t value) {
// 4x4 pixel blocks, the higher the level the closer to the centre. Whether the
// GPU device gets fragment density maps at all is decided at launch, so going
// from "off" to a level takes a restart; between levels and back to "off" it is
// live. The Quest starts at "medium"; elsewhere it does nothing.
// live. The standalone headsets (Quest, Steam Frame) start at "medium";
// elsewhere it does nothing.
#if defined(__ANDROID__)
inline constexpr const char* kVrFoveationDefault = "medium";
#else
@@ -1719,9 +1721,16 @@ inline bool SetVrRaceView(VrRaceView view) {
// The room, through the headset's cameras, around the menu screen and every
// other virtual screen, a Flat Screen race included, and around the immersive
// window (never a fully immersive race). Only the Quest offers it; the
// launcher's Settings page shows the same default.
inline bool VrPassthrough(bool fallback = true) {
// window (never a fully immersive race). Only the Quest offers it
// (XR_FB_passthrough, which SteamVR does not have); the launcher's Settings
// page shows the same default.
#if defined(MKW_HEADSET_STEAM_FRAME)
inline constexpr bool kVrPassthroughDefault = false;
#else
inline constexpr bool kVrPassthroughDefault = true;
#endif
inline bool VrPassthrough(bool fallback = kVrPassthroughDefault) {
return Get().vrPassthrough.value_or(fallback);
}
+4
View File
@@ -147,7 +147,9 @@ int g_vrRaceView = static_cast<int>(RuntimeConfigFile::GetVrRaceView());
bool g_vrFlatScreen = g_vrRaceView == static_cast<int>(RuntimeConfigFile::VrRaceView::FlatScreen);
constexpr std::array<const char*, 3> kVrRaceViewLabels{"Immersive", "Immersive window", "Flat screen"};
#if defined(__ANDROID__)
#if !defined(MKW_HEADSET_STEAM_FRAME)
bool g_vrPassthrough = RuntimeConfigFile::VrPassthrough();
#endif
bool g_vrHandTracking = RuntimeConfigFile::VrHandTracking();
// Menu labels for the foveation levels, index-matched to RuntimeConfigFile::kVrFoveationLevels and to
// aurora_set_stereo_foveation.
@@ -1489,6 +1491,7 @@ void DrawVrSettings() {
}
}
#if defined(__ANDROID__)
#if !defined(MKW_HEADSET_STEAM_FRAME)
if (ImGui::Checkbox("Passthrough around the menu screen", &g_vrPassthrough)) {
mkw::vr::OpenXRSetPassthrough(g_vrPassthrough);
RuntimeConfigFile::SetVrPassthrough(g_vrPassthrough);
@@ -1500,6 +1503,7 @@ void DrawVrSettings() {
"fully virtual; the immersive window and the Flat Screen race have the room "
"around them too. Applies immediately.");
}
#endif
// Shows the live level Aurora holds.
g_vrFoveation = static_cast<int>(aurora_get_stereo_foveation());
if (ImGui::Combo("Foveated rendering", &g_vrFoveation, kVrFoveationLabels.data(),
+5 -1
View File
@@ -423,7 +423,11 @@ public:
"XR_KHR_convert_timespec_time",
"XR_KHR_android_thread_settings",
"XR_FB_display_refresh_rate", "XR_EXT_performance_settings",
"XR_FB_passthrough", "XR_VALVE_frame_controller_interaction"};
"XR_VALVE_frame_controller_interaction"};
#if !defined(MKW_HEADSET_STEAM_FRAME)
// Horizon OS's room view; the Steam Frame build neither asks for it nor offers the setting.
config.optional_extensions.push_back("XR_FB_passthrough");
#endif
AddHandMeshExtensions(config);
config.instance_create_next = OpenXRAndroidInstanceCreateNext();
#endif
+9
View File
@@ -68,6 +68,15 @@ int main() {
Require(std::string_view(MKW_VR_REFRESH_RATE_DEFAULT_TEXT) == "0");
#endif
// [vr] passthrough: Horizon OS's room view, which the Steam Frame build does not offer.
Require(Parse("[vr]\npassthrough = false\n").vrPassthrough == false);
Require(!Parse("[vr]\n").vrPassthrough.has_value());
#if defined(MKW_HEADSET_STEAM_FRAME)
Require(!RuntimeConfigFile::kVrPassthroughDefault);
#else
Require(RuntimeConfigFile::kVrPassthroughDefault);
#endif
// [vr] hand_tracking: the cockpit hands follow the headset's hand tracking.
Require(Parse("[vr]\nhand_tracking = true\n").vrHandTracking == true);
Require(Parse("[vr]\nhand_tracking = false\n").vrHandTracking == false);