diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index 1a29e2003e9..905f272df2c 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -3035,6 +3035,10 @@
If [code]true[/code], the forward renderer will fall back to Direct3D 12 if Vulkan is not supported. The fallback is always attempted regardless of this setting if Vulkan driver support was disabled at compile time.
[b]Note:[/b] This setting is implemented only on Windows.
+
+ If [code]true[/code], the forward renderer will fall back to Metal if Vulkan is not supported.
+ [b]Note:[/b] This setting is implemented only on macOS and iOS.
+
If [code]true[/code], the forward renderer will fall back to OpenGL 3 if Direct3D 12, Metal, and Vulkan are not supported.
[b]Note:[/b] This setting is implemented only on Windows, Android, macOS, iOS, and Linux/X11.
diff --git a/main/main.cpp b/main/main.cpp
index 10064b35037..317589bd1aa 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -2081,6 +2081,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
GLOBAL_DEF_RST("rendering/rendering_device/fallback_to_vulkan", true);
GLOBAL_DEF_RST("rendering/rendering_device/fallback_to_d3d12", true);
+ GLOBAL_DEF_RST("rendering/rendering_device/fallback_to_metal", true);
GLOBAL_DEF_RST("rendering/rendering_device/fallback_to_opengl3", true);
}
diff --git a/platform/ios/display_server_ios.mm b/platform/ios/display_server_ios.mm
index 09acc199bf9..f862db7e3a2 100644
--- a/platform/ios/display_server_ios.mm
+++ b/platform/ios/display_server_ios.mm
@@ -109,18 +109,39 @@ DisplayServerIOS::DisplayServerIOS(const String &p_rendering_driver, WindowMode
#endif
if (rendering_context) {
if (rendering_context->initialize() != OK) {
+ bool failed = true;
memdelete(rendering_context);
rendering_context = nullptr;
+#if defined(METAL_ENABLED)
+ bool fallback_to_metal = GLOBAL_GET("rendering/rendering_device/fallback_to_metal");
+ if (failed && fallback_to_metal && rendering_driver != "metal") {
+ if (@available(iOS 14.0, *)) {
+ memdelete(rendering_context);
+ layer = [AppDelegate.viewController.godotView initializeRenderingForDriver:@"metal"];
+ wpd.metal.layer = (CAMetalLayer *)layer;
+ rendering_context = memnew(RenderingContextDriverMetal);
+ if (rendering_context->initialize() == OK) {
+ WARN_PRINT("Your device seem not to support MoltenVK, switching to Metal.");
+ rendering_driver = "metal";
+ OS::get_singleton()->set_current_rendering_driver_name(rendering_driver);
+ failed = false;
+ }
+ }
+ }
+#endif
#if defined(GLES3_ENABLED)
bool fallback_to_opengl3 = GLOBAL_GET("rendering/rendering_device/fallback_to_opengl3");
- if (fallback_to_opengl3 && rendering_driver != "opengl3") {
+ if (failed && fallback_to_opengl3 && rendering_driver != "opengl3") {
+ failed = false;
+ memdelete(rendering_context);
+ rendering_context = nullptr;
WARN_PRINT("Your device seem not to support MoltenVK or Metal, switching to OpenGL 3.");
rendering_driver = "opengl3";
OS::get_singleton()->set_current_rendering_method("gl_compatibility");
OS::get_singleton()->set_current_rendering_driver_name(rendering_driver);
- } else
+ }
#endif
- {
+ if (failed) {
ERR_PRINT(vformat("Failed to initialize %s context", rendering_driver));
r_error = ERR_UNAVAILABLE;
return;
diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm
index 556c4c966ef..223ebd59e02 100644
--- a/platform/macos/display_server_macos.mm
+++ b/platform/macos/display_server_macos.mm
@@ -3812,18 +3812,36 @@ DisplayServerMacOS::DisplayServerMacOS(const String &p_rendering_driver, WindowM
if (rendering_context) {
if (rendering_context->initialize() != OK) {
+ bool failed = true;
memdelete(rendering_context);
rendering_context = nullptr;
+#if defined(METAL_ENABLED)
+ bool fallback_to_metal = GLOBAL_GET("rendering/rendering_device/fallback_to_metal");
+ if (failed && fallback_to_metal && rendering_driver != "metal") {
+ memdelete(rendering_context);
+ rendering_context = memnew(RenderingContextDriverMetal);
+ rendering_driver = "metal";
+ if (rendering_context->initialize() == OK) {
+ WARN_PRINT("Your device seem not to support MoltenVK, switching to Metal.");
+ rendering_driver = "metal";
+ OS::get_singleton()->set_current_rendering_driver_name(rendering_driver);
+ failed = false;
+ }
+ }
+#endif
#if defined(GLES3_ENABLED)
bool fallback_to_opengl3 = GLOBAL_GET("rendering/rendering_device/fallback_to_opengl3");
- if (fallback_to_opengl3 && rendering_driver != "opengl3") {
+ if (failed && fallback_to_opengl3 && rendering_driver != "opengl3") {
+ failed = false;
+ memdelete(rendering_context);
+ rendering_context = nullptr;
WARN_PRINT("Your device seem not to support MoltenVK or Metal, switching to OpenGL 3.");
rendering_driver = "opengl3";
OS::get_singleton()->set_current_rendering_method("gl_compatibility");
OS::get_singleton()->set_current_rendering_driver_name(rendering_driver);
- } else
+ }
#endif
- {
+ if (failed) {
r_error = ERR_CANT_CREATE;
ERR_FAIL_MSG("Could not initialize " + rendering_driver);
}