Skip to content

Resolve merge conflicts; PR feedback by AThousandShips#3

Open
stuartcarnie wants to merge 45 commits intorsanchezsaez:apple/visionos-xrfrom
stuartcarnie:sgc/visionos-xr
Open

Resolve merge conflicts; PR feedback by AThousandShips#3
stuartcarnie wants to merge 45 commits intorsanchezsaez:apple/visionos-xrfrom
stuartcarnie:sgc/visionos-xr

Conversation

@stuartcarnie
Copy link
Copy Markdown

@stuartcarnie stuartcarnie commented Mar 22, 2026

This PR merges the main branch, resolves conflicts and includes all the review feedback from @AThousandShips.

@rsanchezsaez I have confirmed this brach compiles and runs and works great on visionOS. The immersive mode is fantastic!

The visionOS XR module only supports the Mobile renderer for now, the Forward+ renderer is not supported.

To use the visionOS XR module you must set the new 'application/app_role' export setting to Immersive. You can choose if you want passthrough or not by the new 'application/immersion_style' export option.

Then, initialize the visionOS VR module in a script:

```
    var interface = XRServer.find_interface("visionOS")
    if interface and interface.initialize():
        var viewport : Viewport = get_viewport()
        viewport.use_xr = true
        viewport.vrs_mode = Viewport.VRS_XR
        viewport.use_hdr_2d = true
```

Implementation details:
- The visionOS platform now has two different execution paths implemented by the `GodotWindowScene` and `CompositorServicesImmersiveSpace` scenes in `app_visionos.swift`. The `application/app_role` export setting controls which scene is used.
- The visionOS VR interface tries to be as close to the OpenXR interface as possible, to keep main renderer code changes to a minimum. It adopts Compositor Services and ARKit APIs, which is how you render Metal content on visionOS.
- `XRInterface` has these new methods to spport the platform: `get_viewports_are_hdr()` (which avoids the sRGB conversion step on the tonemapper), `get_viewport_for_view()` (which provides individual viewports for each eye, which are larger than the render area when foveation is on).
- We obtain and set the head pose twice, once in `process()` so scripts can use it if needed, and another in `pre_render()`, so the pose is more accurate for rendering.
- The projection matrices returned by visionOS have an inverse depth correction applied (visionOS uses the [0, 1] z space, but Godot expects the [-1, 1] z space until the rendering step).
- The `rasterizationRateMap` (the structure that supports foveation on visionOS) is provided through the `get_vrs_texture()` function, using the new `XR_VRS_TEXTURE_FORMAT_RASTERIZATION_RATE_MAP` texture type. It's' passed through the renderer when creating passes/subpasses, to be ultimately set by the Metal driver.
- The Metal driver now needs to be able to set several viewports (one for each eye), so the DrawListInstructions `TYPE_SET_VIEWPORT` and TYPE_SET_SCISSOR have been replaced by `TYPE_SET_VIEWPORTS` and  `TYPE_SET_SCISSORS`. If you pass a single viewport to the functions, they work as it used to.
- The skybox shader has a new `SKY_VERSION_BACKGROUND_MULTIVIEW_WRITE_DEPTH` variant, because visionOS in immersive mode needs to write appropriate depth values.
- Apple Vision Pro's' minimum supported near plane is `0.1`. There's a new editor warning emited by `XRCamera3D` if you set it to a lower value.
- `XRCamera3D` also emits a warning if you change the FOV, as this has no effect on XR platforms. They use the platforms FOV.
- `XROrigin3D` emits a new editor warning if you change the scale, as it causes the rendered depth texture values to be incongruent to what XR platforms expect to perform reprojection (this applies to OpenXR platforms as well).
- The Metal driver has a new dummy `SurfaceCompositorServices`, which replaces `SurfaceLayer` when running in immersive mode. The reason for this is that the Compositor Services API needs to do a `cp_drawable_encode_present()` step with the `MTLCommandBuffer` used by the renderer, and this seemed the most natural way of overriding the `present()` call normally done by the Metal driver.
…ing() call from renderer_viewport

Instead, call it on VisionOSXRInterface::post_draw_viewport()
Resolve conflicts from Metal driver refactor (b815c88) which converted
Objective-C++ to C++ using metal-cpp:

- Move VisionOS SIMD helpers to modules/visionos_xr/visionos_simd_helpers.h
- Add RenderModeVisionOS utility class (platform/visionos/render_mode_visionos.h/mm)
  to provide C++ access to visionOS render mode and compositor services device
@rsanchezsaez rsanchezsaez force-pushed the apple/visionos-xr branch 3 times, most recently from acc0704 to 7dc239d Compare March 31, 2026 01:43
@rsanchezsaez rsanchezsaez force-pushed the apple/visionos-xr branch 3 times, most recently from 0e95347 to b2cd272 Compare April 16, 2026 21:16
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.

2 participants