diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index c48b05002c8..df3005ce3f6 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -2987,6 +2987,10 @@ If [code]true[/code], the forward renderer will fall back to Vulkan if Direct3D 12 (on Windows) or Metal (on macOS x86_64) are not supported. [b]Note:[/b] This setting is implemented only on Windows and macOS. + + 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. + Enable the pipeline cache that is saved to disk if the graphics API supports it. [b]Note:[/b] This property is unable to control the pipeline caching the GPU driver itself does. Only turn this off along with deleting the contents of the driver's cache if you wish to simulate the experience a user will get when starting the game for the first time. diff --git a/main/main.cpp b/main/main.cpp index 6cd9c89fa8b..bb92b296096 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -2063,6 +2063,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..0b2e226a081 100644 --- a/platform/ios/display_server_ios.mm +++ b/platform/ios/display_server_ios.mm @@ -109,18 +109,37 @@ 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" && @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 bd6d435f83d..800d9be2b5d 100644 --- a/platform/macos/display_server_macos.mm +++ b/platform/macos/display_server_macos.mm @@ -3805,18 +3805,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); }