v5.0.0 - Move to Direct Presentation with Native 3D Output Modes#26
Merged
Conversation
Add Anaglyph Red Cyan Compromise mode; Add VirtualDesktop mode to replace vd_fsbs_hack;
…op peek, hide dead OSD controls - Presenters: overlay is click-through by default (X11 empty XShape input region + input=False; Wayland empty wl_surface input region + kb NONE) so mouse+keyboard reach the flat game. SetInputCapture(true) on OSD-open takes pointer+keyboard so GUI clicks/typing don't leak to the game (OSD still reads evdev). SetAlwaysOnTop(false) lowers the overlay (X11 XLowerWindow + drop _NET_WM_STATE_ABOVE; Wayland layer BACKGROUND) to peek at the game. - VkRenderer edge-tracks menu-visible + man_on_top on the present thread and drives the two presenter calls; on-top defaults true on Linux so the OSD 'Always on Top' checkbox is meaningful (uncheck = peek). - Gamepad GUI nav confirmed already wired (buttons/dpad/sticks/triggers -> ImGui nav, NavEnableGamepad + HasGamepad). - OSD: hide Linux-inert controls (Auto Focus, Hide/Lock Cursor, LeiaSR head- tracking section) and filter LeiaSR/NvidiaDX9 out of the output-mode dropdown while preserving enum mapping. Link libXext for XShape. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…onnect) Corrects the earlier always-on-top-by-default. VkRenderer's focus block now replicates WindowPresenter::FocusThreadLoop: overlay starts lowered; when an app connects to SteamVR it auto-raises (once per app PID, latching is_on_top+man_on_top so Ctrl+F8 can still drop it); man_on_top overrides; OSD open forces on-top+capture. Linux Activate no longer defaults on-top true. Dropped the unconditional BringToTop at present-thread start. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Byte-preserving UNORM-everywhere was still dark: the SteamVR Linux compositor hands direct-mode eye images as LINEAR data, so presenting them raw through a UNORM swapchain makes KWin interpret linear values as sRGB and darken them. Prefer an _SRGB swapchain so the final present store sRGB-encodes exactly once (imports/out_sbs stay UNORM/raw). Needs on-hardware visual confirmation. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Converted all 108 vrto3d_profiles/*_config.json from legacy VK_*/XINPUT_* to the portable Key_*/Pad_* vocabulary via tools/migrate_profiles.cpp (reuses the loader's vrto3d::keys::MigrateName, handles + combos), matching the migrated default_config. No behavioral change — the loader already accepted both spellings; this makes the shipped canonical format consistent and avoids a silent rewrite on each user's first save. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
#1: Wayland/X11 presenters had identical AcquireNext/Present/RenderPass/ Extent/Format delegations + ctx_/swapchain_ members. Hoisted into SwapchainPresenterBase; each presenter now implements only its native windowing surface. WibbleWobblePresenter stays a direct IVkPresenter (no swapchain). #3: The want-on-top state machine existed in both WindowPresenter:: FocusThreadLoop (Windows) and VkRenderer's Linux focus block and had to be hand-synced. Extracted to focus_policy.h ComputeWantOnTop() (pure, per-caller FocusLatchState); both call it. Behavior identical. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Refactor #2: hoist the repeated 'create image -> get mem reqs -> find memory type -> allocate -> bind -> make view' sequence into vk_context: Image2D + AllocateBindImageView (with alloc_pnext / extra_type_bits for dmabuf import/export chains) + CreateImage2D for the plain device-local case. vk_renderer's out_sbs target and the wibblewobble render target now use CreateImage2D; the dmabuf import/export paths keep their bespoke memory-type logic and call AllocateBindImageView directly. Also bumps the VRto3DLib submodule to pick up the ApplyUserSettingsHotkeys dedup (refactor #4). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Steam Deck usability (no keyboard): - Add an always-polled Start+DPad-Up gamepad chord mirroring Ctrl+F8 (toggle always-on-top). This is the direct fix for a lowered/buried overlay 'disappearing' with no keyboard way back — it counterparts the existing Start+DPad-Down menu-open chord and is polled regardless of disable_hotkeys so recovery always works. - Harden the X11 re-raise: SetAlwaysOnTop(true) now also sends a _NET_ACTIVE_WINDOW request with source=pager, which KWin honors even from a non-focusable background window (a plain XRaiseWindow can be swallowed by focus-stealing prevention, leaving the overlay stuck behind the Plasma desktop). input=False keeps it from grabbing keys. - Add a 'Reset Defaults' button in System > Misc that restores VRto3D's built-in factory stereo/shader/tracking tunables while preserving the display/output hardware fields. Distinct from 'Reload Default Cfg', which re-reads the user's possibly-customized default_config.json. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The runtime keybind loader already migrates legacy VK_*/XINPUT_* names to the portable vocabulary transparently and canonicalizes them in place on the next profile save (VRto3DLib key_names MigrateName + ParseBindName). That makes this dev-only bulk converter — used once to migrate the 108 shipped profiles (commit 0d1395b) — redundant. Dropping it keeps the migration story to a single self-healing path. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…-top) Investigating 'overlay stays on top after the game exits' when SteamVR survives the game (returns to Home/void). The disconnect->lower path is correct and fires (Unload logged), but nothing logs the actual focus raise/lower, and only accepted app connects are logged — so we can't see what becomes the scene app after the game exits and whether we spuriously auto-raise for it (on Linux the game filter is just 'non-empty name'). - vk_renderer focus block: log every RAISE/LOWER with the FocusInputs snapshot (is_on_top/man/auto/pid/running/menu). - device_provider: include event type + pid on accepted connects, and log connect/scene-app-change events that are ignored (skip-list or filter) with the resolved process name — this reveals the fallback scene app. Diagnostic only; no behavior change. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…e gate Root cause of 'went on top for the game but never lowered after exit': the present-thread focus/z-order block sat *below* the 'if (!have_frame) continue;' gate. On app disconnect the driver both queues the LOWER (LoadSettings clears is_on_top_/man_on_top_) and pauses the renderer (OnAppDisconnect -> paused_for_disconnect_ -> OnDirectModeFrame drops all frames). With no frames, have_frame stays false and the loop continues before ever reaching the focus block, so SetAlwaysOnTop(false) is never called and the window stays in its last state (raised). Move the focus/z-order/input-capture block above the have_frame gate so it runs every loop iteration (incl. the 50ms no-frame timeouts while paused), applying the queued lower promptly. The block touches only the display connection and focus atoms — no frame data — so it's safe to run frameless. Also makes 'start lowered' apply before the first frame. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…inhook Replace the in-tree D3D9Ex/NVAPI 3D Vision presenter and its MinHook-based OSD suppressor with the external NV3D-Lib (submodule at external/NV3D-Lib, nv3d-glass branch). The library owns the FSE popup + window thread, D3D9Ex device, stereo bring-up, LightBoost, the in-process suppressor (MinHook is compiled into NV3DLib.lib), the DX11->D3D9 import, and an async present worker. NvStereoDx9Presenter is now a thin wrapper that keeps VRto3D's focus policy (ComputeWantOnTop -> SetVisible, joinable game-focus watcher) and owns a 3-deep MISC_SHARED staging ring. - tracked_game_pid = own PID so popup visibility is purely SetVisible-driven and our focus policy stays authoritative. - Host-side device-removed watch + 40-frame present-failure streak -> NotifyDeviceLost before Delete() (non-blocking teardown). - MyDeviceProvider::Cleanup TerminateProcess when NV3D ran this session, to skip the NVIDIA DLL_PROCESS_DETACH freeze (NV3D-Glass pattern). - Remove external/minhook submodule (only the deleted suppressor used it; keeping it would LNK2005 against NV3DLib.lib's embedded MinHook). - vcxproj: PreBuildEvent builds the NV3DLib static lib (Config-MD), link NV3DLib-md/-mdd.lib. CMake: separate nv3dlib STATIC target (DX11 backend only) so its vendored nvapi/json/minhook headers can't shadow VRto3D's. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…268f594) Three fixes for the NV3D-Lib wrapper found in first hardware testing: - Startup visibility sync: the library creates its popup visible while our policy starts lowered; the transitions-only focus loop never reconciled them, so the popup was stuck up and the first Ctrl+F8 was a no-op. Force SetVisible on the first iteration. - OSD clicks: the OSD's WH_MOUSE_LL hook is installed from the presenter's render thread, and LL-hook callbacks only fire while the installing thread pumps messages. The old presenter pumped via its window thread; the new render loop owned no window and never pumped, so clicks were dead. Drain the thread message queue every loop iteration. - OSD usability: hand the library popup HWND to the OSD for cursor mapping (its FindWindow fallback looks for the old VRto3D_PresentWindow class), drive the popup solid/click-through from menu visibility via the new InterfaceDX11::SetInteractive, and force the popup visible while the menu is open (mirrors the Linux VkRenderer force_on_top) so opening the menu with the popup hidden can't softlock hotkeys. ApplyMenuVisibility now leaves the FSE window styles to the library in NvidiaDX9 mode. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Both presenters carried hand-rolled copies of the on-top policy that focus_policy.h exists to centralize. Replace the inline blocks with ComputeWantOnTop + FocusLatchState (verified semantically identical: same precedence, same auto-raise-once-per-PID latch, same reset when the app exits). All five presenter focus loops now share the single rule. No behavior change; watchers, reassert counters and WibbleWobble's per-tick style reconciliation are untouched. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
oneup03
force-pushed
the
direct_experiment
branch
from
July 17, 2026 23:58
19f8c5b to
33ce6cb
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
VRto3D — Direct Mode Release
The big one: VRto3D now renders and presents stereo 3D natively/in direct mode, instead of relying on ReShade + external tools. This unlocks a full menu of output formats, an in-3D settings UI, auto-depth, proper screenshots, and native Linux support.
🎬 Native 3D output modes
All modes are produced directly by the driver (no ReShade required):
vd_fsbs_hack)🐧 Linux support (new)
wwserver🖥️ On-Screen Display (OSD)
🔎 Auto-Depth
🎯 Head tracking
📸 Screenshots
⌨️ Hotkeys & profiles
📦 Installer
🛠️ Fixes & polish
ComputeWantOnTopfocus policy; fixes overlay stuck-on-top after game exit; consistent auto-focus)