Files
OpenVR-AdvancedSettings-frame/docs/steamframe/PROGRESS.md
T
Matthias JanetschekandClaude Opus 5.5 bde675f1b8 Steam Frame build, packaging and deployment scripts; render test
- build_scripts/steamframe/: Debian trixie (Qt 6.8) containers for the
  aarch64 cross build, native build and tests; toolchain; scripts to build,
  test (Vulkan validation layers), package (system Qt, ~3 MB) and deploy over
  SSH. Adapted from the vrdashboard template.
- test/render/: render test for the OpenGL and Vulkan backends, driven like
  OverlayController (option OVRAS_BUILD_TESTS).
- RPATH only $ORIGIN, without the build machine's link directories.
- Ignore dist/.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 13:50:57 +02:00

9.0 KiB
Raw Blame History

Steam Frame port: progress

Iteration 1

Step 1: build fixes, bytecode-only QML (2026-10-07)

Changes:

  • CMakeLists.txt:
    • Core5Compat removed (unused, not on the Frame).
    • GuiPrivate requested explicitly. This is temporary, until step 3 replaces QRhi.
    • QT_QMLCACHEGEN_ARGUMENTS --only-bytecode.
    • OpenVR library directory per architecture (linux64 / linuxarm64 / win64), for linking and for the copy next to the binary.
    • RPATH $ORIGIN.
    • libXtst linked.
  • overlaycontroller.cpp: d3d11.h and case QRhi::D3D11 only under _WIN32.
  • Logging: 8 active easylogging LOG(INFO) calls became qInfo() (overlaycontroller.cpp 6, ChaperoneTabController.cpp 1, MoveCenterTabController.cpp 1). Commented-out LOG lines are left unchanged.
  • Only changed lines are formatted (git clang-format).

Results (x86_64, Arch, Qt 6.11.1, GCC):

  • The build succeeds, with 1463 compiler warnings, as in qt6.
  • objdump -T: 7 Qt_6_PRIVATE_API symbols, all QRhi… (step 3). The QQmlPrivate::AOTCompiledContext symbols are gone (bytecode-only QML).
  • libopenvr_api.so is resolved from the binary's directory (ldd).
  • Not started: without a running SteamVR the start hangs in OpenVR init (expected; tested on the Frame in step 5).

Step 2: platform option, R7, tick (2026-10-07)

Changes:

  • Platform option:
    • CMake option OVRAS_STEAM_FRAME (default OFF) sets the compile definition OVRAS_STEAM_FRAME=1.
    • New src/utils/platform_capabilities.h evaluates it as the only place. It holds k_chaperoneCommitSupported, k_defaultVsyncDisabled and k_defaultCustomTickRateMs.
  • Tick (R6):
    • In "vsync disabled" mode, m_pumpEventsTimer runs directly at customTickRateMs (applyTickInterval(), Qt::PreciseTimer); the 1 ms counting is gone.
    • Changing the setting restarts the timer.
    • Setting defaults in settings_controller.h come from the constants: Frame true/11 ms, otherwise unchanged false/20 ms.
  • R7: with !k_chaperoneCommitSupported:
    • updateChaperoneResetData() and applyChaperoneResetData() skip CommitWorkingCopy/RevertWorkingCopy. Each logs once per function.
    • The init autosave profile is skipped.

Results:

  • Both variants (default and -DOVRAS_STEAM_FRAME=ON) build on x86_64. The definition is only set in the Frame variant (compile_commands.json).
  • Not tested at runtime yet (Frame, step 5).

Notes:

  • Another commit at start-up remains, but only on opt-in. SetWidget() applies a chaperone profile and commits when "auto-apply chaperone" (autoApplyChaperoneToggle, default false) is on. That's a chaperone-profile feature, so it belongs to R5 (iteration 2).
  • clang-format reflows comment blocks next to new comments. Separate new comments from existing commented-out code with a blank line, otherwise the diff grows.

Step 3: rendering through public API, --graphics-api, mouse y, shutdown order (2026-10-07)

Changes:

  • src/render/ (new): RenderBackend, OpenGLRenderBackend, VulkanRenderBackend from the template (4a5b090).
    • Changes to the template code: VRDASH_* → OVRAS_* names, origin note in the file header, references to OverlayController.
    • Formatted completely in OVRAS style.
    • One comment in VulkanRenderBackend.h was wrapped by hand, because the automatic wrapping had broken its column layout.
  • OverlayController:
    • QRhi block replaced by configureWindow → renderControl.initialize → attachWindow → createRenderTarget.
    • renderOverlay() wraps the frame in beginFrame/finishFrame. It submits vrTextureBounds + vrTexture while the context is current.
    • SetOverlayFromQRhiTexture, the QRhi members and QVulkanInstance are removed.
    • Render delay 5 → 16 ms (about 60 fps).
  • Shutdown: Shutdown() runs only once. It calls VR_Shutdown(), then frees the backend's render target (releaseRenderTarget, detachWindow).
  • Mouse y: always flipped; the Linux un-flip and its TODO are removed.
  • openvr_init::renderInterop(): Vulkan extensions and HMD GPU from SteamVR.
  • main.cpp: parses --graphics-api, then createRenderBackend → initialize → QQuickWindow::setGraphicsApi → OverlayController.
  • setup.*: --graphics-api opengl|vulkan (default opengl). Unknown or not built in → error, exit code GENERAL_FAILURE.
  • CMake:
    • GuiPrivate is gone.
    • The Vulkan backend is built when QT_FEATURE_vulkan is set (OVRAS_HAS_VULKAN).

Results (x86_64, Qt 6.11.1):

  • The build succeeds. The Vulkan backend is built in.
  • objdump -T: only QVulkanDeviceFunctions::* / QVulkanFunctions::* remain as Qt_6_PRIVATE_API. Acceptance criterion R1 (symbols) is met.
  • Warnings 1463 → 1630. The new code itself has none; the additional ones come from openvr.h in the three new translation units.
  • Not tested yet:
    • running both backends, Vulkan validation, the snapshot test (step 5, with the containers)
    • mouse direction (Frame)

Risk:

  • MyTextField opens the SteamVR keyboard on activeFocus. The template had to send the offscreen window an explicit FocusIn, otherwise activeFocusItem stayed null. The qt6 branch doesn't send it. If text fields don't respond on the Frame, that is the cause (R4).

Step 4: manifest and installation (2026-10-07)

Changes:

  • manifest.vrmanifest: binary_path_linux and binary_path_linux_arm → AdvancedSettings_app.
  • manifest::handleManifests:
    • VR_Init(Utility); on VRInitError_Init_NotAvailableToUtilityApps, VR_Init(Background).
    • Other errors: message and exit code OPENVR_INIT_ERROR, instead of initializeOpenVR's retry loop.
  • main.cpp: --graphics-api is checked before connecting to OpenVR. A wrong value used to fail only after initializeOpenVR's retry loop.

Results (x86_64, without SteamVR):

  • --force-install-manifest exits right away with OPENVR_INIT_ERROR (−2).
  • --graphics-api foo exits right away with GENERAL_FAILURE (−1).
  • The build tree contains the binary, libopenvr_api.so, both manifests, default_action_manifests/ and res/.
  • Not tested yet: Background on the Frame (step 5).

Step 5: Frame build, package, tests (2026-10-07)

Changes:

  • build_scripts/steamframe/ (new, see DESIGN.md section 9): containers, toolchain, build, test, package and deploy scripts.
  • test/render/ (new): render test for both backends (OVRAS_BUILD_TESTS=ON).
  • CMakeLists.txt:
    • option OVRAS_BUILD_TESTS
    • RPATH only $ORIGIN (BUILD_WITH_INSTALL_RPATH). Before, the cross binary also had the host's absolute link directory in its RUNPATH.
  • .gitignore: dist/.

Results:

  • Render tests:
    • locally (Arch, Qt 6.11, Intel Iris Xe): OpenGL and Vulkan, 4/4 passed each
    • in the container (Debian trixie, Qt 6.8, same GPU via /dev/dri): 2/2 passed, no Vulkan validation messages
    • Proof that the layer was active: VK_LOADER_DEBUG=layer shows "Inserted device layer VK_LAYER_KHRONOS_validation".
  • Cross build (aarch64, Qt 6.8 Debian): succeeds once the container has libxt-dev (input_sender_X11.cpp includes X11/Intrinsic.h).
    • Qt_6_PRIVATE_API without QVulkan*: 0 → R1 symbols met.
    • Qt version tag: Qt_6.8 (fits the Frame's 6.8.0).
    • GLIBC ≤ 2.38 (the Frame has 2.39); GLIBCXX ≤ 3.4.32 (not checked against the Frame).
    • NEEDED: Qt6 Core/Gui/Qml/Quick/Widgets/Network/DBus/Multimedia/WebSockets, libX11, libXtst, libpulse, libopenvr_api, libstdc++/libc.
  • Package dist/AdvancedSettings-5.7.4-linux-arm64.tar.gz: 3.0 MB (9.1 MB unpacked). The version 5.7.4 comes from qt6's project() (master is at 5.8.17).

Open (needs the Frame):

  • Are the QML modules OVRAS imports present in the Frame's system Qt? QtQuick.Controls (Material), Layouts, Dialogs, Multimedia.
  • Do libXt/libXtst exist on SteamOS? Is libstdc++ new enough?

Test checklist on the Frame (step 5)

Deploy: build_scripts/steamframe/deploy-to-frame.sh <user>@<frame> (SteamVR running).

# Check Criterion Result
T1 install.sh: registration works (log: "Manifest reinstalled", via Background) R2 open
T2 Tab appears in the dashboard, UI correct (OpenGL) R2, R3 open
T3 ./run.sh vulkan: UI correct R3 open
T4 Laser right way up, click, scrolling on several pages (both APIs) R4 open
T5 Text field (e.g. new profile name): SteamVR keyboard opens, input arrives R4 open
T6 An OVRAS action arrives (e.g. push-to-talk, log/notification) R4 open
T7 Play area before/after start unchanged; log: "CommitWorkingCopy skipped" R7 open
T8 Quit app (OVRAS "Exit" and Quit in the SteamVR dashboard): no crash (both APIs) R2 open
T9 Auto-start after a SteamVR restart / reboot R2 open
T10 pidstat -p $(pgrep -f AdvancedSettings_app) 10 6: dashboard closed / OVRAS visible / other tab visible R6 open
T11 uninstall.sh unregisters it R2 open