Skip to content

Add minimal support to OpenXR in Android#1766

Open
yuripourre wants to merge 3 commits into
BabylonJS:masterfrom
yuripourre:android-openxr-backend
Open

Add minimal support to OpenXR in Android#1766
yuripourre wants to merge 3 commits into
BabylonJS:masterfrom
yuripourre:android-openxr-backend

Conversation

@yuripourre

@yuripourre yuripourre commented Jul 3, 2026

Copy link
Copy Markdown

With this PR is possible to create apk files and run on Quest devices. I didn't heavily tested all capabilities but could successfully render a scene with very high FPS.

Currently it does not support:

  • Vulkan
  • Inputs (Controllers) Done
  • Hand Tracking

Tested on an Oculus Quest 2 Device (the old one before rebranding to Meta).

Maybe this PR can be simplified if #1552 is merged

Adds a new xr::System backend (Dependencies/xr/Source/OpenXR/Android)
that implements the cross-platform pImpl interface directly against
OpenXR + XR_KHR_opengl_es_enable, for use on Meta Quest where the
existing ARCore backend doesn't apply.

Also fixes a SIGSEGV in NativeXrImpl::BeginUpdate: the JS-thread
continuation that clears the XR framebuffer called
DeviceImpl::GetActiveEncoder() (via FrameBuffer::Clear()) without
pinning a Graphics::FrameCompletionScope, so it could run after the
render thread had already closed the frame and nulled the encoder.

Adds host-thread boot-lifecycle logging to RunFirstAttachInit to make
first-attach hangs diagnosable from the embedder side.
BeginUpdate()'s per-swapchain-texture framebuffer creation chain
captured its FrameCompletionScope in a lambda capture-list
initializer, which C++ evaluates eagerly when the .then(...) call is
constructed (still inside BeginUpdate(), mid-frame) rather than when
the continuation actually runs (after the AfterRenderScheduler hop).

Since AfterRenderScheduler is only pumped once
FinishRenderingCurrentFrame's own pendingScopes==0 wait succeeds,
holding this scope open that early permanently pinned
m_pendingFrameScopes above zero, deadlocking every frame after the
first swapchain texture was created. Moving the acquisition into the
lambda body defers it to the correct point in time.
Wires up a persistent instance-scoped xrCreateActionSet/xrCreateAction
set (grip/aim pose, trigger, squeeze, thumbstick x/y, thumbstick
click, primary/secondary click) bound to the oculus/touch_controller
interaction profile, plus per-session action spaces attached via
xrAttachSessionActionSets. Each frame, xrSyncActions populates the
two persistent InputSource entries (pose, gamepad buttons/axes,
current interaction profile) consumed by XRSession's WebXR input
plumbing.

XRSession.cpp now maps the reported OpenXR interaction profile path to
the corresponding WebXR profile id (oculus-touch vs. the previous
hardcoded generic-trigger-squeeze-touchpad-thumbstick), so
CreateXRInputSource reports the right profile once Touch controllers
are actually bound.

Also removes the temporary __android_log_print/log() tracing added
while diagnosing the earlier first-attach hang and native XR
init/session-state issues, now that those are resolved.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant