Skip to content

Conversation

@huisedenanhai
Copy link
Contributor

This PR adds depth resolve for metal driver. So you can use MSAA for visionOS immersive rendering.

Depends on

#109975

and

#78598

Only the last commit in this PR is meaningful. Other commits are cherrypicked from the two PRs above.

This is a working implementation. I put it here in case someone needs it. This is not ready for merge.

#109975 implements immersive rendering on visionOS. But MSAA does not work, because depth buffer is not correctly resolved.

Depth resolve is a long standing issue. #78598 implements depth resolve for vulkan. This PR implements depth resolve for metal.

NOTE: Dependency on #109975 can be detached if someone can provide a better use case to test MSAA depth resolve on metal.

rsanchezsaez and others added 6 commits October 6, 2025 16:57
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
```

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.
- `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.
RESOURCE_USAGE_ATTACHMENT_RASTERIZATION_RATE_MAP_READ
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants