Apple: Add tvOS platform support#118332
Draft
stuartcarnie wants to merge 2 commits intogodotengine:masterfrom
Draft
Apple: Add tvOS platform support#118332stuartcarnie wants to merge 2 commits intogodotengine:masterfrom
stuartcarnie wants to merge 2 commits intogodotengine:masterfrom
Conversation
Contributor
I doubt I'll be building anything for tvOS anytime soon, so this is mostly out of curiosity: if you build with ANGLE is it possible to use the compatibility renderer? |
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 XR 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 XR 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.
- We obtain the head pose twice, once in `process()` in the game thread so scripts can use it if needed, and another from the render thread in set_frame(), so the rendered pose is accurate.
- 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.
- Apple Vision Pro's' minimum supported near plane is `0.1`. There's a runtime error message that shows if you try to use a lower near plane.
- 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.
Co-Authored-By: huisedenanhai <winser@pku.edu.cn>
Co-Authored-By: Stuart Carnie <stuart.carnie@gmail.com>
99af3a2 to
700817e
Compare
Contributor
Author
|
Important tvOS templates can now be build using the official Linux build containers with the following PRs: |
3bfb01c to
d63baff
Compare
d63baff to
9daefb0
Compare
Contributor
Author
|
Updated PRs to build tvOS (and all other platforms): |
|
|
||
| float DisplayServerTVOS::_screen_potential_edr_headroom() const { | ||
| UIScreen *screen = _get_ui_screen(); | ||
| ERR_FAIL_NULL_V(screen, false); |
Member
There was a problem hiding this comment.
Suggested change
| ERR_FAIL_NULL_V(screen, false); | |
| ERR_FAIL_NULL_V(screen, 0.0); |
Or some appropriate value
|
|
||
| float DisplayServerTVOS::_screen_current_edr_headroom() const { | ||
| UIScreen *screen = _get_ui_screen(); | ||
| ERR_FAIL_NULL_V(screen, false); |
Member
There was a problem hiding this comment.
Suggested change
| ERR_FAIL_NULL_V(screen, false); | |
| ERR_FAIL_NULL_V(screen, 0.0); |
Same here
| Error err = OK; | ||
| Ref<Image> img = _load_icon_or_splash_image(icon_path, &err); | ||
| if (err != OK || img.is_null() || img->is_empty()) { | ||
| add_message(EXPORT_MESSAGE_ERROR, TTR("Export Icons"), vformat("Invalid icon (%s): '%s'.", info.preset_key, icon_path)); |
Member
There was a problem hiding this comment.
Should these be translated, like so:
Suggested change
| add_message(EXPORT_MESSAGE_ERROR, TTR("Export Icons"), vformat("Invalid icon (%s): '%s'.", info.preset_key, icon_path)); | |
| add_message(EXPORT_MESSAGE_ERROR, TTR("Export Icons"), vformat(TTR("Invalid icon (%s): '%s'."), info.preset_key, icon_path)); |
| err = img->save_png(p_iconset_dir + exp_name); | ||
| } | ||
| if (err) { | ||
| add_message(EXPORT_MESSAGE_ERROR, TTR("Export Icons"), vformat("Failed to export icon (%s): '%s'.", info.preset_key, icon_path)); |
| Error err = OK; | ||
| Ref<Image> img = _load_icon_or_splash_image(icon_path, &err); | ||
| if (err != OK || img.is_null() || img->is_empty()) { | ||
| add_message(EXPORT_MESSAGE_ERROR, TTR("Export Icons"), vformat("Invalid icon (%s): '%s'.", info.preset_key, icon_path)); |
| return ERR_UNCONFIGURED; | ||
| } else if (info.force_opaque && img->detect_alpha() != Image::ALPHA_NONE) { | ||
| if (resize_warning) { | ||
| add_message(EXPORT_MESSAGE_WARNING, TTR("Export Icons"), vformat("Icon (%s) must be opaque.", info.preset_key)); |
| err = new_img->save_png(p_iconset_dir + exp_name); | ||
| } else if (img->get_width() != target_width || img->get_height() != target_height) { | ||
| if (resize_warning) { | ||
| add_message(EXPORT_MESSAGE_WARNING, TTR("Export Icons"), vformat("Icon (%s): '%s' has incorrect size %s and was automatically resized to %s.", info.preset_key, icon_path, img->get_size(), Vector2i(target_width, target_height))); |
| } | ||
|
|
||
| if (err) { | ||
| add_message(EXPORT_MESSAGE_ERROR, TTR("Export Icons"), vformat("Failed to export icon (%s): '%s'.", info.preset_key, icon_path)); |
Contributor
Author
|
Thanks for the review, @AThousandShips – I'll correct those issues |
Contributor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Depends on
tvOS platform support for Godot.
What's included?
Outstanding Issues
Menu / back button support
tvOS has a similar behaviour to Android with a back (Siri Remote) / menu button (game controllers) that navigate back towards the home screen. We can leverage the existing APIs for Android:
quit_on_go_backWINDOW_EVENT_GO_BACK_REQUESTquit_on_go_backisfalseNOTIFICATION_WM_GO_BACK_REQUESTquit_on_go_backisfalseA suggested flow would be that a game would set
quit_on_go_backtofalsewhilst in play, so that when a user presses back / menu, the game intercepts and displays a pause menu to the user. Whilst the pause menu is active, the game should setquit_on_go_backtotrue, so that if the user presses back / home again, the game naturally exits to the home screen, providing the correct HIG experience for users.Exiting an app is prohibited on Apple embedded platforms, namely iOS, visionOS and tvOS. The OS manages the lifetime and applications are suspended by user action, such as pressing the Menu / back button. These platforms ignore the return value of
Main::iterationin their C++ implementations, where returningtruenormally signals the process should exit. If an Godot application quits, it puts the entire game into an inconsistent state, asSceneTree::_quitis nowtrue, and certain processes no longer run correctly. There is no way for an end user or a Godot developer to fix this without force-quitting, and would be perceived as bugs by users.My recommendation is that that the following APIs and behaviours be changed for APPLE_EMBEDDED platforms only:
SceneTree::quit(exit_code)falsefor tvOSFootnotes
Metal simulator device features do not meet the minimum requirements for the mobile or forward+ renderers ↩
tvOS only supports OpenGL ES 2.0; Godot requires ES 3.0 ↩