Skip to content

Commit 33c345a

Browse files
committed
[visionOS] Implement visionOS VR module
The visionOS VR module only supports the Mobile renderer for now, the Forward+ renderer is not supported. To use the visionOS VR 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(): get_viewport().use_xr = true ``` Implementation details: - The visionOS platform now has two different execution paths implemented by th GodotWindowScene and CompositorServicesImmersiveSpace scenes in 'app_visionos.swift'. The 'application/app_role' export setting controls which scene is used. - 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), and get_rasterization_rate_map() (which provides the structure that supports foveation on visionOS). - 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. - 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 function, it works as it used to. - The skybox shader has a new SKY_VERSION_BACKGROUND_MULTIVIEW_WRITE_DEPTH variant, because visionOS in immersive mode needs appropriate depth values. - The 'rasterizationRateMap' is queried by the visionOS VR module, and passed through the renderer when creating passes/subpasses, to be ultimately set by the Metal driver.
1 parent 0438c42 commit 33c345a

File tree

71 files changed

+2135
-233
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+2135
-233
lines changed

drivers/apple_embedded/apple_embedded.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030

3131
#import "apple_embedded.h"
3232

33-
#import "app_delegate_service.h"
33+
#import "godot_app_delegate_service_apple_embedded.h"
3434
#import "godot_view_controller.h"
3535

3636
#import <CoreHaptics/CoreHaptics.h>

drivers/apple_embedded/bridging_header_apple_embedded.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,6 @@
3030

3131
#pragma once
3232

33-
#import "app_delegate_service.h"
34-
#import "godot_app_delegate.h"
33+
#import "godot_app_delegate_service_apple_embedded.h"
34+
#import "godot_view_apple_embedded.h"
3535
#import "godot_view_controller.h"

drivers/apple_embedded/display_server_apple_embedded.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@
3030

3131
#import "display_server_apple_embedded.h"
3232

33-
#import "app_delegate_service.h"
3433
#import "apple_embedded.h"
34+
#import "godot_app_delegate_service_apple_embedded.h"
3535
#import "godot_keyboard_input_view.h"
3636
#import "godot_view_apple_embedded.h"
3737
#import "godot_view_controller.h"

drivers/apple_embedded/godot_app_delegate.h renamed to drivers/apple_embedded/godot_app_delegate_apple_embedded.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**************************************************************************/
2-
/* godot_app_delegate.h */
2+
/* godot_app_delegate_apple_embedded.h */
33
/**************************************************************************/
44
/* This file is part of: */
55
/* GODOT ENGINE */
@@ -34,7 +34,7 @@
3434

3535
typedef NSObject<UIApplicationDelegate> GDTAppDelegateServiceProtocol;
3636

37-
@interface GDTApplicationDelegate : NSObject <UIApplicationDelegate>
37+
@interface GDTAppDelegate : NSObject <UIApplicationDelegate>
3838

3939
@property(class, readonly, strong) NSArray<GDTAppDelegateServiceProtocol *> *services;
4040

drivers/apple_embedded/godot_app_delegate.mm renamed to drivers/apple_embedded/godot_app_delegate_apple_embedded.mm

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**************************************************************************/
2-
/* godot_app_delegate.mm */
2+
/* godot_app_delegate_apple_embedded.mm */
33
/**************************************************************************/
44
/* This file is part of: */
55
/* GODOT ENGINE */
@@ -28,12 +28,13 @@
2828
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
2929
/**************************************************************************/
3030

31-
#import "godot_app_delegate.h"
31+
#import "godot_app_delegate_apple_embedded.h"
32+
33+
#import "godot_app_delegate_service_apple_embedded.h"
3234

33-
#import "app_delegate_service.h"
3435
#include "core/typedefs.h"
3536

36-
@implementation GDTApplicationDelegate
37+
@implementation GDTAppDelegate
3738

3839
static NSMutableArray<GDTAppDelegateServiceProtocol *> *services = nil;
3940

@@ -43,7 +44,7 @@ @implementation GDTApplicationDelegate
4344

4445
+ (void)load {
4546
services = [NSMutableArray new];
46-
[services addObject:[GDTAppDelegateService new]];
47+
// Add the specific GDTAppDelegateService subclass in each inheriting platform
4748
}
4849

4950
+ (void)addService:(GDTAppDelegateServiceProtocol *)service {

drivers/apple_embedded/app_delegate_service.h renamed to drivers/apple_embedded/godot_app_delegate_service_apple_embedded.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**************************************************************************/
2-
/* app_delegate_service.h */
2+
/* godot_app_delegate_service_apple_embedded.h */
33
/**************************************************************************/
44
/* This file is part of: */
55
/* GODOT ENGINE */
@@ -36,6 +36,6 @@
3636

3737
@interface GDTAppDelegateService : NSObject <UIApplicationDelegate>
3838

39-
@property(strong, class, nonatomic) GDTViewController *viewController;
39+
@property(weak, class, nonatomic, nullable) GDTViewController *viewController;
4040

4141
@end

drivers/apple_embedded/app_delegate_service.mm renamed to drivers/apple_embedded/godot_app_delegate_service_apple_embedded.mm

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**************************************************************************/
2-
/* app_delegate_service.mm */
2+
/* godot_app_delegate_service_apple_embedded.mm */
33
/**************************************************************************/
44
/* This file is part of: */
55
/* GODOT ENGINE */
@@ -28,7 +28,7 @@
2828
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
2929
/**************************************************************************/
3030

31-
#import "app_delegate_service.h"
31+
#import "godot_app_delegate_service_apple_embedded.h"
3232

3333
#import "godot_view_apple_embedded.h"
3434
#import "godot_view_controller.h"
@@ -58,14 +58,14 @@ @implementation GDTAppDelegateService
5858
SESSION_CATEGORY_SOLO_AMBIENT
5959
};
6060

61-
static GDTViewController *mainViewController = nil;
61+
static __weak GDTViewController *_viewController = nil;
6262

6363
+ (GDTViewController *)viewController {
64-
return mainViewController;
64+
return _viewController;
6565
}
6666

6767
+ (void)setViewController:(GDTViewController *)viewController {
68-
mainViewController = viewController;
68+
_viewController = viewController;
6969
}
7070

7171
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**************************************************************************/
2+
/* godot_renderer.h */
3+
/**************************************************************************/
4+
/* This file is part of: */
5+
/* GODOT ENGINE */
6+
/* https://godotengine.org */
7+
/**************************************************************************/
8+
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9+
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10+
/* */
11+
/* Permission is hereby granted, free of charge, to any person obtaining */
12+
/* a copy of this software and associated documentation files (the */
13+
/* "Software"), to deal in the Software without restriction, including */
14+
/* without limitation the rights to use, copy, modify, merge, publish, */
15+
/* distribute, sublicense, and/or sell copies of the Software, and to */
16+
/* permit persons to whom the Software is furnished to do so, subject to */
17+
/* the following conditions: */
18+
/* */
19+
/* The above copyright notice and this permission notice shall be */
20+
/* included in all copies or substantial portions of the Software. */
21+
/* */
22+
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23+
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24+
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25+
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26+
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27+
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28+
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29+
/**************************************************************************/
30+
31+
#pragma once
32+
33+
#import <Foundation/Foundation.h>
34+
35+
inline void safeDispatchSyncToMain(void (^block)(void)) {
36+
if ([NSThread isMainThread]) {
37+
block();
38+
} else {
39+
dispatch_sync(dispatch_get_main_queue(), block);
40+
}
41+
}
42+
43+
@interface GDTRenderer : NSObject
44+
45+
@property(assign, readonly, nonatomic) BOOL hasFinishedSetup;
46+
47+
- (BOOL)setUp;
48+
49+
@end
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/**************************************************************************/
2+
/* godot_renderer.mm */
3+
/**************************************************************************/
4+
/* This file is part of: */
5+
/* GODOT ENGINE */
6+
/* https://godotengine.org */
7+
/**************************************************************************/
8+
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9+
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10+
/* */
11+
/* Permission is hereby granted, free of charge, to any person obtaining */
12+
/* a copy of this software and associated documentation files (the */
13+
/* "Software"), to deal in the Software without restriction, including */
14+
/* without limitation the rights to use, copy, modify, merge, publish, */
15+
/* distribute, sublicense, and/or sell copies of the Software, and to */
16+
/* permit persons to whom the Software is furnished to do so, subject to */
17+
/* the following conditions: */
18+
/* */
19+
/* The above copyright notice and this permission notice shall be */
20+
/* included in all copies or substantial portions of the Software. */
21+
/* */
22+
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23+
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24+
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25+
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26+
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27+
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28+
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29+
/**************************************************************************/
30+
31+
#import "godot_renderer.h"
32+
33+
#import "display_server_apple_embedded.h"
34+
#import "os_apple_embedded.h"
35+
36+
#include "core/config/project_settings.h"
37+
#include "main/main.h"
38+
39+
@interface GDTRenderer ()
40+
41+
@property(assign, nonatomic) BOOL hasCalledProjectDataSetUp;
42+
@property(assign, nonatomic) BOOL hasStartedMain;
43+
@property(assign, nonatomic) BOOL hasFinishedSetUp;
44+
45+
@end
46+
47+
@implementation GDTRenderer
48+
49+
- (BOOL)setUp {
50+
if (self.hasFinishedSetUp) {
51+
return NO;
52+
}
53+
54+
if (!OS::get_singleton()) {
55+
exit(0);
56+
}
57+
58+
if (!self.hasCalledProjectDataSetUp) {
59+
[self setUpProjectData];
60+
}
61+
62+
if (!self.hasStartedMain) {
63+
[self startMain];
64+
}
65+
66+
self.hasFinishedSetUp = YES;
67+
68+
return NO;
69+
}
70+
71+
- (void)setUpProjectData {
72+
self.hasCalledProjectDataSetUp = YES;
73+
safeDispatchSyncToMain(^{
74+
Main::setup2();
75+
76+
// this might be necessary before here
77+
NSDictionary *dict = [[NSBundle mainBundle] infoDictionary];
78+
for (NSString *key in dict) {
79+
NSObject *value = [dict objectForKey:key];
80+
String ukey = String::utf8([key UTF8String]);
81+
82+
// we need a NSObject to Variant conversor
83+
84+
if ([value isKindOfClass:[NSString class]]) {
85+
NSString *str = (NSString *)value;
86+
String uval = String::utf8([str UTF8String]);
87+
88+
ProjectSettings::get_singleton()->set("Info.plist/" + ukey, uval);
89+
90+
} else if ([value isKindOfClass:[NSNumber class]]) {
91+
NSNumber *n = (NSNumber *)value;
92+
double dval = [n doubleValue];
93+
94+
ProjectSettings::get_singleton()->set("Info.plist/" + ukey, dval);
95+
}
96+
// do stuff
97+
}
98+
});
99+
}
100+
101+
- (void)startMain {
102+
self.hasStartedMain = YES;
103+
safeDispatchSyncToMain(^{
104+
OS_AppleEmbedded::get_singleton()->start();
105+
});
106+
}
107+
108+
@end
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/**************************************************************************/
2+
/* app.swift */
3+
/**************************************************************************/
4+
/* This file is part of: */
5+
/* GODOT ENGINE */
6+
/* https://godotengine.org */
7+
/**************************************************************************/
8+
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9+
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10+
/* */
11+
/* Permission is hereby granted, free of charge, to any person obtaining */
12+
/* a copy of this software and associated documentation files (the */
13+
/* "Software"), to deal in the Software without restriction, including */
14+
/* without limitation the rights to use, copy, modify, merge, publish, */
15+
/* distribute, sublicense, and/or sell copies of the Software, and to */
16+
/* permit persons to whom the Software is furnished to do so, subject to */
17+
/* the following conditions: */
18+
/* */
19+
/* The above copyright notice and this permission notice shall be */
20+
/* included in all copies or substantial portions of the Software. */
21+
/* */
22+
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23+
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24+
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25+
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26+
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27+
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28+
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29+
/**************************************************************************/
30+
31+
import SwiftUI
32+
import UIKit
33+
34+
struct GodotSwiftUIViewController: UIViewControllerRepresentable {
35+
36+
func makeUIViewController(context: Context) -> GDTViewController {
37+
let viewController = GDTViewController()
38+
GDTAppDelegateService.viewController = viewController
39+
return viewController
40+
}
41+
42+
func updateUIViewController(_ uiViewController: GDTViewController, context: Context) {
43+
// NOOP
44+
}
45+
46+
}
47+
48+
struct GodotWindowScene: Scene {
49+
@Environment(\.scenePhase) private var scenePhase
50+
51+
var body: some Scene {
52+
WindowGroup {
53+
GodotSwiftUIViewController()
54+
.ignoresSafeArea()
55+
56+
// UIViewControllerRepresentable does not call viewWillDisappear() nor viewDidDisappear() when
57+
// backgrounding the app, or closing the app's main window, update the renderer here.
58+
.onChange(of: scenePhase) { phase in
59+
// For some reason UIViewControllerRepresentable is not calling viewWillDisappear()
60+
// nor viewDidDisappear when closing the app's main window, call it here so we
61+
// stop the renderer.
62+
switch phase {
63+
case .active:
64+
print("GodotSwiftUIViewController scene active")
65+
GDTAppDelegateService.viewController?.godotView.startRendering()
66+
case .inactive:
67+
print("GodotSwiftUIViewController scene inactive")
68+
GDTAppDelegateService.viewController?.godotView.stopRendering()
69+
case .background:
70+
print("GodotSwiftUIViewController scene backgrounded")
71+
GDTAppDelegateService.viewController?.godotView.stopRendering()
72+
@unknown default:
73+
print("unknown default")
74+
}
75+
}
76+
77+
}
78+
}
79+
}

0 commit comments

Comments
 (0)