5521 Commits
Author SHA1 Message Date
Jeremy Bowers 0356a3221e Fix the handling of stopping the emulation so it doesn't seem to just freeze.
Trying to stop the emulation in VR or S3D modes would result in a QT
dialog box popping up about whether you were sure you wanted to end
the emulation, but that caused no visible effect on the screen.
Now there's a dialog visible for it when emulating in those modes,
and it should correctly work for flat emulation and when pressing
the Stop button in the QT UI.

This fixes #11.
2026-10-18 22:38:46 -04:00
Jeremy Bowers 64cc2b2e13 When Immersive VR is used, lock certain settings in place that are necessary for it.
This fixes #5.
2026-10-18 19:21:47 -04:00
Jeremy Bowers 80f9cd15c3 Make the emulation work more like it is supposed to with focus.
This fixes #14 and fixes #8 to my satisfaction. At least now, since
the game starts in the user's visual field, it is obvious that they
need to dismiss the Baiji UI to get to the game. This works like
everything else in the Steam Frame windowing environment.

Now the emulation never freezes, no matter how hard I focus off
of Baiji. May still be some problems here. But this is the closest
to correct it has been working yet.
2026-10-17 15:50:43 -04:00
Jeremy Bowers 38cf5cf933 Make the best fix for Room View in S3D we can, given what the OS gives us. 2026-10-11 22:16:20 -04:00
Jeremy Bowers fbeefedb2a Updates to the Readme.md and compiling scripts. 2026-10-05 17:06:08 -04:00
Jeremy Bowers 9dd817d864 OpenXR: add independent stereo separation control
Immersive VR previously used the full runtime-reported left/right view
positions, with Units per Meter scaling both world geometry and the
per-eye offsets. That left no direct way to soften strong near-field
pop-out without also changing the apparent world scale.

Add Graphics.VR.StereoSeparation as a 0-200 percent setting, defaulting
to 100 percent. Scale each eye's positional offset around the average
eye center independently of shared head translation. At 100 percent the
projection is unchanged, 0 percent brings the virtual view positions
together toward mono, and values above 100 percent amplify stereo depth.
Units per Meter continues to set world scale and head-motion mapping.

Expose the setting in the global VR pane and per-game VR configuration,
include it in game VR override application/reset, and refresh cached
projection rows when it changes. Help text explains the scale/depth
tradeoff, possible near-field comfort benefit, and that Stereo 3D Screen
continues to use the existing Stereoscopic Depth control.
2026-10-05 00:21:28 -04:00
Jeremy Bowers 6c95b40453 Steam Frame: complete stereo eye writes before XR release
StereoScreen previously submitted and released each Vulkan eye separately
while its image writes could still be in flight. On native Steam Frame
this produced conspicuous doubled/stale-image hiccups and apparent
backward jumps, even though API-side frame identities remained ordered.
A capture covering 16,699 XFB copies found no gameplay source regression,
GPU-submit reversal, XR display-time reversal, or eye-ID mismatch.
SteamVR motion smoothing was already forced off.

For Baiji StereoScreen, defer eye releases until both blits are recorded,
submit their GPU work together, wait once for completion, release both
images under the graphics-queue lock, then publish the quad layers.
Keep this wait even with timeline semaphores enabled: submitted writes
alone were insufficient for correct image delivery on Frame. The wait
trades some CPU/GPU overlap for a completed stereo pair.

Also exclude xrEndFrame from the video blit/completion/release/publish
transaction with a handoff mutex. The previous atomic flag had a
check-to-submit race. Take the handoff lock before publish/queue locks,
and never hold the graphics-queue lock during the completion wait.
PresentBackbuffer already advances frame resources; the stereo submit
must not advance them again.

CPU-side handoff locking alone did not cure the artifact. Headset tests
with the completed-pair handoff in Super Mario Galaxy 2 at 2x/120 Hz
confirmed that remaining misses look like ordinary dropped frames,
rather than doubled images or huge hiccups. The clean Frame SDK build
and launcher CLI smoke check passed. Remove the temporary timing/order
capture code and retain the findings and lock-order guidance in AGENTS.md.
2026-10-04 23:10:20 -04:00
Jeremy Bowers 4465c932fb Steam Frame: decouple XR heartbeat from game timing 2026-10-04 20:54:26 -04:00
Jeremy Bowers 22f6884ca0 Checkpoint. This has a number of things including defaulting eager_heartbeat to true. 2026-10-04 14:41:52 -04:00
Jeremy Bowers ef1a3a0500 OpenXR: synchronize flat-screen reanchor cache 2026-10-04 14:38:56 -04:00
Jeremy Bowers 834cdddd2e OpenXR: add Steam Frame controller input 2026-10-03 22:21:35 -04:00
Jeremy Bowers bec9d1beae OpenXR: keep controller input in Flat Vulkan mode 2026-10-03 21:00:54 -04:00
Jeremy Bowers 3ec01541fd OpenXR: add configurable presentation modes 2026-10-03 20:06:38 -04:00
Jeremy Bowers 0e74b57e09 OpenXR: remove temporary recenter/aim debug logging
Diagnosis confirmed: the runtime rebases the reference space on system
recenter (logged head_yaw matched the user's per-run offset exactly), and
controllers share the HMD's tracking frame. Keep only the low-volume
reference-space-change and recenter log lines.
2026-10-03 13:51:35 -04:00
Jeremy Bowers 2e826d8914 OpenXR: re-anchor flat screen on reference space change
The runtime rebases the reference space on system recenter, universe
switches, and relocalization, and notifies apps via
XrEventDataReferenceSpaceChangePending. Dolphin only logged the event, so
the world-locked flat-screen quad kept its stale coordinates and appeared
to jump by the rebase yaw every time the user used the system recenter
(the HMD's yaw in the runtime's arbitrary local frame — random per run).

On the event, invalidate the cached flat-screen pose so the panel is
re-placed in front of the user's current gaze, which is also the expected
behavior after a system recenter. Log the event's poseInPreviousSpace yaw
delta, and add a throttled view-yaw vs aim-yaw diagnostic to check whether
the runtime reports controllers in a different tracking frame.
2026-10-03 13:20:18 -04:00
Jeremy Bowers 1190e903be OpenXR: add minimal recenter/screen-pose debug logging
Log head yaw, screen yaw, and screen direction at initial flat-screen
placement and after recenter, to diagnose the underlying offset issue.
2026-10-03 12:44:50 -04:00
Jeremy Bowers a02a554c86 OpenXR: revert recenter changes to pre-d9ed82e state
Remove the reference-space recreation recenter, ScreenYawOffset config, and
debug logging. Restore the original home-position recenter and world-locked
flat screen placement so we can diagnose the underlying issue from a clean
baseline.
2026-10-03 12:41:08 -04:00
Jeremy Bowers cf72cfeb53 OpenXR: add recenter debug logging
Log head yaw, reference-space offset yaw, and post-recenter screen pose for
5 frames after each recenter. This is diagnostic to find why recenter
produces a fixed per-run error.
2026-10-03 12:29:22 -04:00
Jeremy Bowers 8fb66a2936 Revert "OpenXR: make repeated recenter operations compose correctly"
This reverts commit 75dc76990b.
2026-10-03 12:25:36 -04:00
Jeremy Bowers 75dc76990b OpenXR: make repeated recenter operations compose correctly
The previous recenter code computed the head pose in the current (already
recentered) reference space and passed it directly to xrCreateReferenceSpace,
which interprets the pose relative to the runtime's natural LOCAL frame. This
made repeated recenters compound incorrectly and produced a random-looking
offset per run.

Accumulate the head-in-current-space offset onto a persistent
m_recenter_offset pose relative to the natural LOCAL frame, and create each new
reference space from that accumulated offset. Also add diagnostic logging for
recenter.
2026-10-03 12:11:56 -04:00
Jeremy Bowers 328997747a OpenXR: add ScreenYawOffset config to adjust virtual screen horizontal angle
Adds a VR/ScreenYawOffset setting (degrees, default 0). Positive values
rotate the virtual screen counter-clockwise from above (to the left);
negative values rotate clockwise (to the right). This is intended as a
diagnostic/tuning knob for the stereoscopic virtual screen placement.
2026-10-03 11:38:37 -04:00
Jeremy Bowers f6d7395ea2 OpenXR: fix recenter offset sign
The recenter offset was computing the inverse of the desired transform.
The new reference space should be placed at the current head pose (yaw-only)
so that the current gaze becomes forward, not rotated the opposite way.
2026-10-03 11:16:19 -04:00
Jeremy Bowers c7499b4ccf OpenXR: fix recenter by reorienting reference space
Recenter now recreates the OpenXR reference space with a yaw-only offset
that maps the user's current head pose to the origin. This makes the flat
virtual screen appear directly in front of the user after recentering, with
upright orientation, instead of being left at an arbitrary session-start
forward direction.

Reverts the temporary head-locked stereo-screen behavior; the screen is
world-locked again, so the Wiimote pointer orientation stays consistent.
2026-10-03 11:09:36 -04:00
Jeremy Bowers d9ed82e38f OpenXR: make stereoscopic virtual screen head-locked
In stereo-screen mode, recompute the virtual screen pose every frame from the
user's current head yaw so the screen always stays in front of their gaze.
This avoids the confusing behavior where the initial world-locked placement
captured a random head pose during startup and recenter could leave the screen
off to one side.

Flat mono panel mode keeps the existing world-locked behavior.
2026-10-03 10:55:52 -04:00
Jeremy Bowers 4359d8c989 OpenXR: remove refresh-rate request diagnostics
SteamVR on the Steam Frame returns XR_ERROR_FEATURE_UNSUPPORTED for both
60 Hz and 120 Hz requests, so the request function works but the runtime
has no such modes. Remove the temporary diagnostic log and keep the
feature available for runtimes that do support app-controlled refresh rates.
2026-10-03 10:29:40 -04:00
Jeremy Bowers 7726dbe5a5 OpenXR: add requested display refresh rate
Add GFX_VR_REQUESTED_REFRESH_RATE setting (Auto/60/72/90/120 Hz). When a
non-zero rate is configured, call xrRequestDisplayRefreshRateFB after the
session begins so the runtime can switch the headset panel to a rate that
matches the game's frame rate (e.g. 60 Hz or 120 Hz for 60 fps Wii games,
instead of the default 72 Hz).

This should reduce judder caused by the compositor showing 60 fps content on
a 72 Hz display. The runtime may clamp the request to the nearest supported
rate; the result is logged.

UI exposed in VRPane and VRConfigWidget.
2026-10-03 10:12:22 -04:00
Jeremy Bowers fb2e70a608 OpenXR: implement stereoscopic virtual screen mode
- Add IOpenXRSwapchain::GetEyeSwapchainHandle() and SubmitStereoFlatFrame(),
  with per-backend overrides for Vulkan, D3D11, D3D12, and OGL.
- Add OpenXRManager::SubmitStereoQuadFrame() which builds two world-locked
  XrCompositionLayerQuad layers with XR_EYE_VISIBILITY_LEFT/RIGHT and publishes
  them through the pacing thread (or EndFrame on the legacy path).
- Extend PublishedXRFrame and FrameThreadLoop to submit the stereo quad pair.
- Add UI checkbox for Stereo Screen in VRPane and VRConfigWidget.

The game renders with classic SBS stereoscopy; left/right XFB layers are blit
into the corresponding OpenXR eye swapchains and shown as a 3D floating screen.
2026-10-03 01:29:02 -04:00
Jeremy Bowers 49cf50d0e2 Presenter: add stereoscopic virtual screen submission path
Add IsOpenXRStereoScreen() and route classic SBS frames through a new
SubmitStereoFlatFrame() path. The left XFB layer is blit into the left
OpenXR eye swapchain and the right layer into the right eye swapchain,
then the backend submits two quad layers at the virtual-screen pose.

Stereo-screen mode is treated like flat mode for direct-to-HMD and
pacing-thread deferral: the eye blits happen at submit time, not during
the desktop mirror path.
2026-10-03 01:24:39 -04:00
Jeremy Bowers 3deb147e55 Config: add vr_stereo_screen mode
Add GFX_VR_STEREO_SCREEN setting. When OpenXR is enabled and this mode is
active, force stereo_mode to SBS so the game renders with Dolphin's classic
side-by-side stereoscopy. Extend VRSessionActive() to keep the OpenXR session
alive for this path. This is the first step toward submitting a stereoscopic
virtual screen via OpenXR quad layers.
2026-10-03 01:23:38 -04:00
Jeremy Bowers aa2871d9e6 VK/OpenXR: support headless Vulkan VR session
- Skip Vulkan surface creation when VR session is active; output goes to
  OpenXR swapchains, not a desktop window. This avoids WSI crashes under
  compositors such as Gamescope.
- Guard VKGfx backbuffer/present/fullscreen paths against a null swapchain
  in headless mode.
- Allow Present() and Presenter::Initialize() to run on any VR-active
  backend, not only Android GLES, so the XR frame lifecycle works with
  headless Vulkan.

Cleaned up diagnostic init logging added during earlier debugging.
2026-10-03 01:22:39 -04:00
iChris4 ffe128309f Add tracked eye projection rows to OpenXRManager for HUD independence 2026-09-30 19:55:15 +02:00
iChris4 9bd33b5f6b Clears m_loaded_game_id when stopping emulation 2026-08-11 17:22:42 +02:00
iChris4 ca5e69a427 Fixed Vulkan Depth clear value 2026-07-26 03:49:25 +02:00
iChris4 3ddf87e56e Updated VRPane UI & Settings 2026-07-25 18:53:44 +02:00
iChris4andClaude Opus 5 05d91da8bf Fixed Vulkan VR crash when opening a second game in one process
Opening a game, closing it, and opening another crashed or device-lost on
the Vulkan backend with VR enabled. D3D11 and D3D12 both restart cleanly,
so this was Vulkan-specific rather than an OpenXR runtime limitation.

Root cause, proven with VK_EXT_device_fault plus
VK_EXT_device_address_binding_report: the fault is a write-invalid at a
page-aligned address that the binding tracer reports as not owned by the
second game device. The OpenXR compositor still references resources that
lived on the first game VkDevice; destroying that device frees the memory
and the compositor later writes into the freed page. The D3D backends are
immune because their shared compositor resources are COM ref-counted,
while vkDestroyDevice frees unconditionally.

Fix: persist and reuse the VulkanContext (VkInstance and VkDevice) across
VR games, so vkCreateDevice/vkDestroyDevice run once per process and those
pages are never unmapped. Per-game objects are still fully recreated,
including the surface, swapchain, object cache, command buffers, and the
OpenXR session and XrInstance. A device-lost context is never persisted. A
non-VR launch, or a runtime requiring a device extension the persisted
device lacks, discards it and initializes fresh.

Two problems that persisting exposed:

- InitBackendInfo() creates and destroys a temporary VkInstance on every
  game boot and then calls UnloadVulkanLibrary(), which nulls every global
  Vulkan function pointer. Reuse now re-resolves the instance and device
  dispatch for the persisted handles.

- That same UnloadVulkanLibrary() unmaps vulkan-1.dll on runtimes that do
  not otherwise pin it, invalidating the persisted handles. This is why
  VDXR still failed after SteamVR worked. Added KeepVulkanLibraryLoaded()
  so unloading is suppressed while a device is persisted.

Also removes the XR_KHR_vulkan_enable2 path. Creating a second device
against a retained XrInstance crashes inside the runtime in a way SEH
cannot catch. The backend now always uses legacy XR_KHR_vulkan_enable,
where Dolphin owns instance and device creation and the runtime binds at
xrCreateSession.

Supporting changes: ordered OpenXR session teardown (ShutdownSession and
DestroySession), a device-lost guard in CommandBufferManager that stops
emulation instead of resubmitting to a dead device, synchronous release of
Dolphin views and framebuffers before xrDestroySwapchain, and the two GPU
fault diagnostics. Note that vkGetDeviceFaultInfoEXT must be called with
vendorBinarySize zeroed on the second call, or the driver writes the
vendor blob to a null pointer.

Verified on SteamVR/PSVR2, VDXR/Quest 3, and Meta Link over repeated
open/close cycles.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-25 15:43:14 +02:00
iChris4 b38bebb869 Added semantic family scheme to the shader hunter 2026-07-24 17:41:25 +02:00
iChris4 0b3f728999 Removed Debug Logs 2026-07-24 16:56:48 +02:00
iChris4 56261dca10 Added "preserve_stereo_efb" to Fullscreen override 2026-07-24 16:28:46 +02:00
iChris4 c42e41c88e Added Global Flag Override and "Flag" type to Texture Override 2026-07-24 04:00:51 +02:00
iChris4 a409877f3d Added texture override parser support for tex1_WxH_m_<hash> 2026-07-23 23:59:02 +02:00
iChris4 6ff81b072f Added Screen Pane Depth options type "Original, Physical, Flat" 2026-07-23 23:40:13 +02:00
iChris4 a5f7dd1084 Screen_pane depth fix (MKDD) 2026-07-23 20:12:02 +02:00
iChris4 d85e292b12 Presentation-stage fix & Added screen_pane type override 2026-07-23 17:45:43 +02:00
iChris4 f3d3975fe2 Improving OpenXR Wii pointer aim during fast wrist motion 2026-07-23 01:52:28 +02:00
iChris4 b4796daa35 Added Frame Size from XFB Copy, Small 3D Viewports and Detect Render-to-Texture Viewports 2026-07-23 00:14:58 +02:00
iChris4 fc00505bab OpenXR Wii Remote Absolute pointing and Motion fixes 2026-07-22 18:32:55 +02:00
iChris4 f4c435dc3b Fixed "Configure in VR" on Quest 2026-07-22 14:57:59 +02:00
iChris4 ba2baf3a52 VR Config UI Tweaks 2026-07-22 04:51:53 +02:00
iChris4 3f7bab1a03 Added new Hotkeys for the Texture Override Tool and Anchor Overrides 2026-07-22 04:23:19 +02:00
iChris4 e963819d00 Added "Configure in VR" for Hotkey Settings 2026-07-22 03:37:00 +02:00