ExplorXR

What Is OpenXR? The Cross-Platform XR API Explained

By ExplorXR Editorial · · Updated October 27, 2026 · 12 min read

What is OpenXR?

OpenXR is a royalty-free, open standard API from The Khronos Group that gives an application one way to talk to any XR runtime: headsets, controllers, trackers, haptics and the compositor that puts frames on the displays. Instead of writing an Oculus path, an OpenVR path and a Windows Mixed Reality path, an application targets OpenXR and the runtime underneath translates those calls into what the hardware actually needs.

Khronos published OpenXR 1.0 on July 29, 2019, and OpenXR 1.1 on April 15, 2024. Version 1.1 folded several widely used extensions into the core specification, and the specification in the registry today is 1.1.65. The 1.1 document includes all of the 1.0 content, so the two versions are not competing dialects, and the Khronos loader supports applications written against either one.

The closest comparison is Vulkan or OpenGL, but for tracking and input rather than for drawing triangles. OpenXR is not a renderer, not a game engine, not a store and not a UI toolkit. It is the contract between the part of a program that knows about XR and the part of the system that owns the hardware.

The problem it was built to fix

Before OpenXR, every headset vendor shipped its own SDK and its own runtime interface. Khronos states the consequence directly: developers needed separate proprietary code paths to support all the different devices on the market. A studio that wanted to reach Quest, SteamVR and Pico maintained three integrations of the same feature, and each integration had its own bugs, its own input mapping and its own submission cadence.

That fragmentation had a second cost. Porting was expensive enough that small teams picked one platform, content clustered on the largest install base, and the largest platform got larger. OpenXR turns the hardware layer into a runtime problem instead of an application problem. It also decouples the app from the headset generation: a title built against OpenXR 1.0 in 2019 can run on hardware released years later, as long as the runtime on that hardware is conformant.

How the pieces fit: application, loader, runtime

An OpenXR program talks to a loader, and the loader talks to the active runtime.

  • The application creates an XrInstance, which establishes the connection and declares the extensions and API layers it wants.
  • The loader is a thin library, openxr_loader. It finds the installed runtime, loads it and forwards calls. On a PC it can be pointed at SteamVR, at a vendor runtime or at Monado through runtime selection. API layers can sit between loader and runtime, which is how validation layers and debugging tools observe calls without changing the application.
  • The runtime is the vendor’s implementation. It owns tracking, display timing, the compositor and input. Meta’s Quest runtime, Valve’s SteamVR, Pico’s runtime, Android XR and Monado are all OpenXR runtimes.

After the instance, the application asks for a system with xrGetSystem. A system represents a physical display plus a set of input and tracking devices. The application then creates a session with xrCreateSession and starts the frame loop.

That loop is small and explicit:

  1. xrWaitFrame blocks until the runtime wants a frame and returns an XrFrameState carrying a predicted display time.
  2. xrBeginFrame opens the frame.
  3. xrLocateViews returns the predicted head pose and the projection parameters for each eye at that display time.
  4. The application renders into swapchain images.
  5. xrEndFrame submits composition layers, usually an XrCompositionLayerProjection, and the runtime composites and presents them.

The predicted display time is the point of the whole design. Rendering against the pose the head holds now, rather than the pose it will hold when photons leave the display, produces latency the user feels as swim. The runtime owns prediction and reprojection; the application owns submitting a frame on time.

The session lifecycle is explicit too. A session moves through IDLE, READY, SYNCHRONIZED, VISIBLE and FOCUSED, with STOPPING, LOSS_PENDING and EXITING on the way down. Focus is the state that matters for input: an application should stop reacting to input when it loses focus, because the system has handed attention to something else.

Input is action based, not button based

OpenXR does not expose “the trigger”. It exposes actions.

An application defines actions such as grab, teleport or menu, groups them into action sets, and supplies suggested bindings that map those actions onto a device’s interaction profile. The runtime picks the profile that matches the hardware and resolves the binding. Each frame the application calls xrSyncActions and then reads state with xrGetActionStateBoolean, xrGetActionStateFloat, xrGetActionStateVector2f or xrGetActionStatePose. The specification describes an action set as an application-defined collection of actions.

The registry defines interaction profiles for Touch controllers, Index controllers, Vive wands, Pico controllers, Windows Mixed Reality controllers, hand tracking and eye gaze, among others. The practical effect is that one action set runs on a Quest 3, a Steam Frame and a Pico headset, and hand tracking can substitute for a controller without a second code path. The application never asks what the hardware is, only what the user did.

That abstraction has limits. A grip is not a squeeze on every device, and a two handed pose is not the same gesture on wands as on tracked hands. OpenXR supplies the portability, not the interaction design.

Extensions: how the standard grows without breaking

Core OpenXR changes slowly. New hardware features arrive as extensions, which are optional API additions with a strict naming convention:

  • KHR for Khronos-defined extensions, such as the graphics API bindings.
  • EXT for ratified multi-vendor extensions, such as XR_EXT_hand_tracking.
  • Vendor prefixes for platform features, including META, FB, BD for ByteDance, HTC, VARJO and ML for Magic Leap.

An application enables the extensions it needs at instance or session creation and must check support first. An extension a runtime does not implement is not a soft failure, it is a missing entry point.

The promotion path keeps the core coherent. OpenXR 1.1 folded in local floor (XR_EXT_local_floor), quad view rendering for foveated displays (XR_VARJO_quad_views), palm pose (XR_EXT_palm_pose), UUIDs (XR_EXT_uuid) and batch space location (xrLocateSpaces, from XR_KHR_locate_spaces). Quad views is the clearest case for promotion: the same foveated rendering that eye tracking makes practical became a core view configuration instead of a single vendor’s trick, and Khronos notes it was adopted natively in Unity, Unreal and NVIDIA Omniverse.

Who supports OpenXR, and who does not

Khronos lists conformant implementations from Acer, ByteDance, Canon, Collabora’s Monado, Google (Android XR), HTC, Magic Leap, Meta, Microsoft, Qualcomm, Sony, Valve, Varjo and XREAL. In practice that covers Quest 3, Quest Pro and Quest 2, SteamVR on PC, Pico headsets, Vive, HoloLens, Magic Leap 2, Snapdragon Spaces devices and Android XR headsets.

Engine support matters more than a headset count:

  • Unity ships an OpenXR plugin, supported since Unity 2020 LTS.
  • Unreal Engine has supported OpenXR since 4.24.
  • Godot has built-in OpenXR support since 4.0, through a plugin on 3.2.
  • Blender, NVIDIA Omniverse, Qt Quick 3D from 6.8, StereoKit, Autodesk VRED and LÖVR integrate it as well.

The exceptions are as important as the list. Apple Vision Pro does not implement OpenXR, and neither does PlayStation VR2 when it runs on a PS5; both expose their own frameworks instead. That is why cross-platform XR projects still ship separate builds for those two platforms, and why an OpenXR-only pipeline is not yet a universal pipeline.

For a platform-level view of how one conformant runtime is assembled, what Android XR actually is covers the stack that sits on top of OpenXR, including its own session and composition model.

What OpenXR deliberately leaves out

OpenXR standardizes the boundary to the hardware, not the product. It does not provide:

  • A renderer or a scene graph. You bring your own, or your engine’s.
  • Passthrough camera access in one portable form. Passthrough arrives through vendor extensions, and Meta’s XR_META_passthrough_* extensions are not Khronos standards.
  • Store, entitlement, achievement or social APIs.
  • Avatars, networking or spatial anchors as a single portable feature set.
  • Identical performance. Conformance means the calls behave as specified, not that two runtimes hit the same frame time, the same reprojection quality or the same late latch behaviour.

That last point is the one that bites teams. An application can pass on one runtime and stutter on another because it used a legal but suboptimal frame pattern. Khronos shipped a Best Practices Validation Layer for exactly this case: it warns about frame timing and composition patterns that are valid but not portable, including swapchain and blend mode mistakes that produce reprojection artifacts and stereo inconsistency on other hardware.

Where the API is going: spatial containers

The largest change since 1.1 landed on October 19, 2026, when Khronos ratified XR_EXT_spatial_container and XR_EXT_spatial_container_self_rendering. A spatial container is a system-managed volume where an application draws 3D content, roughly what a window is for a 2D application. Containers switch between a bounded mode for multitasking and a full-screen immersive mode, and the runtime controls placement, including following the user as they move.

The session model shifts with it. In OpenXR 1.x one application owns the view and walks the session state machine as the system hands it attention. With containers, a session can stay in the background while individual containers report visibility and closure, and the application renders into each container against its own recommended view configuration.

Khronos says the extensions came out of 18 months of collaboration across runtime and engine vendors, with implementations expected to roll out during 2026. Google’s XR platform and SDK lead Jared Finder said the company is “excited to bring Spatial Container support to Android XR”; Meta did not commit. Until runtimes ship it, the extension is a specification and a sample, not a feature to rely on. That is the same problem the platform owners have been solving separately, the subject of why the 3D compositor is the next platform war, and the ratification writeup collects the day’s platform commitments.

Versions, conformance and the adopter program

OpenXR 1.0 arrived in July 2019, and the 1.0 line ran to 1.0.34 before 1.1 replaced it in April 2024. The current specification is 1.1.65. Khronos publishes a Conformance Test Suite on GitHub: an implementation that passes it can call itself conformant, and using the OpenXR trademark requires joining the adopter program and paying the adopter fee, while the specification itself stays free to implement.

How to start

Three routes, depending on what you are building:

  1. In an engine. Enable the OpenXR plugin and let the engine own the instance, session and frame loop. This is the right default for most projects, and it is what makes one build run on Quest, SteamVR and Pico.
  2. In native code. Start from the OpenXR-SDK and the hello_xr sample, which still targets OpenXR 1.0 so it runs on the widest set of runtimes.
  3. On Linux or custom hardware. Test against Monado, the open source runtime, which is useful as a second implementation even when you ship on a vendor runtime.

Whatever the route, test on at least two runtimes before shipping, enable the validation layers during development, and query extension support at runtime instead of assuming it. The inside-out tracking explainer covers the reference spaces and tracking poses that xrLocateViews depends on.

Limitations

  • Portability is not automatic. Core OpenXR is portable; the features that sell headsets usually arrive as vendor extensions.
  • Two major platforms sit outside the standard: visionOS and PSVR2 on PS5.
  • Spatial containers are ratified but not yet broadly implemented.
  • Conformance does not equal performance parity, and frame pacing bugs often surface only on a runtime you did not develop against.
  • Extensions get deprecated or superseded, so pin the ones you depend on and read the SDK changelog between releases.

Sources

Frequently asked questions

What is OpenXR?
OpenXR is a royalty-free open standard API from The Khronos Group that lets one application talk to any conformant XR runtime. It covers head and controller tracking, input, haptics, swapchain rendering and composition, so a build can run on different headsets without a vendor-specific code path for each one. Khronos published OpenXR 1.0 on July 29, 2019 and OpenXR 1.1 on April 15, 2024.
Is OpenXR free to use?
Yes. The specification is free to download and implement, and Khronos describes OpenXR as royalty-free. The OpenXR Conformance Test Suite is also public on GitHub. Using the OpenXR trademark for a conformant product requires joining the Khronos adopter program and paying the adopter fee.
Does Meta Quest support OpenXR?
Yes. Khronos lists Meta among its conformant implementers, naming Quest 3, Quest Pro, Quest 2, Quest, Rift S and the Meta XR Simulator. An application built against OpenXR runs on Quest through Meta's runtime, and Meta-specific capabilities arrive as vendor extensions such as XR_META_passthrough_preferences.
Does Apple Vision Pro support OpenXR?
No. visionOS exposes Apple's own frameworks, and OpenXR is absent from the platform. UploadVR notes that Apple Vision Pro and PlayStation VR2 running on a PS5 are the two notable exceptions to OpenXR support across headsets, which is why cross-platform projects still keep separate builds for them.
What is the difference between OpenXR and WebXR?
OpenXR is the native API that engines and applications use, while WebXR is the JavaScript API browsers expose to web pages. Khronos lists WebXR as supporting OpenXR as its default backend, but they are separate interfaces with different capabilities and different deployment targets.
What is the current version of OpenXR?
OpenXR 1.1 is the current major version, published on April 15, 2024, and the specification in the Khronos registry is 1.1.65. It includes all of the 1.0 content, and the Khronos loader supports both 1.0 and 1.1 applications.

Related reading