From 481553693d2bbc5a1de5cc029ec8d3925fdbeb22 Mon Sep 17 00:00:00 2001 From: SheepYhangCN Date: Wed, 12 Feb 2025 04:24:28 +0800 Subject: [PATCH 1/3] Fall back to Metal when Vulkan is not supported --- doc/classes/ProjectSettings.xml | 4 ++++ main/main.cpp | 1 + platform/ios/display_server_ios.mm | 25 ++++++++++++++++++++++--- platform/macos/display_server_macos.mm | 24 +++++++++++++++++++++--- 4 files changed, 48 insertions(+), 6 deletions(-) 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); } From 6b3be6b8edf24d2101d2f268f2f88edf7c71b273 Mon Sep 17 00:00:00 2001 From: SheepYhangCN Date: Wed, 12 Feb 2025 06:34:43 +0800 Subject: [PATCH 2/3] Update ProjectSettings.xml --- doc/classes/ProjectSettings.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index df3005ce3f6..83b81aa0c95 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -2979,6 +2979,10 @@ If [code]true[/code], the forward renderer will fall back to Direct3D 12 if Vulkan is not supported. [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. @@ -2987,10 +2991,6 @@ 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. From a08103f8d7c346fa3533566a66120571a4052773 Mon Sep 17 00:00:00 2001 From: SheepYhangCN Date: Wed, 12 Feb 2025 06:50:48 +0800 Subject: [PATCH 3/3] Update display_server_ios.mm --- platform/ios/display_server_ios.mm | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/platform/ios/display_server_ios.mm b/platform/ios/display_server_ios.mm index 0b2e226a081..f862db7e3a2 100644 --- a/platform/ios/display_server_ios.mm +++ b/platform/ios/display_server_ios.mm @@ -114,16 +114,18 @@ DisplayServerIOS::DisplayServerIOS(const String &p_rendering_driver, WindowMode 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; + 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