From 446e874c607561b493955b89de9e2de30ebeef90 Mon Sep 17 00:00:00 2001 From: bruvzg <7645683+bruvzg@users.noreply.github.com> Date: Tue, 9 Jan 2024 08:54:41 +0200 Subject: [PATCH] Add iOS build support, fix Metal command buffer leaks. --- SConstruct | 61 +++++++--- godot-patches/patch_metal_cmd_buf_leak.diff | 39 +++++++ godot-tools/ios.py | 107 ++++++++++++++++++ src/libANGLE/renderer/metal/ProgramMtl.mm | 2 +- .../renderer/metal/ProvokingVertexHelper.mm | 2 +- src/libANGLE/renderer/metal/VertexArrayMtl.mm | 2 +- .../renderer/metal/mtl_buffer_pool.mm | 4 +- 7 files changed, 199 insertions(+), 18 deletions(-) create mode 100644 godot-patches/patch_metal_cmd_buf_leak.diff create mode 100644 godot-tools/ios.py diff --git a/SConstruct b/SConstruct index ada886be152..4d79323ba01 100644 --- a/SConstruct +++ b/SConstruct @@ -67,7 +67,7 @@ if profile: customs.append(profile + ".py") opts = Variables(customs, ARGUMENTS) -platforms = ("macos", "windows") +platforms = ("macos", "ios", "windows") opts.Add( EnumVariable( key="platform", @@ -512,11 +512,37 @@ angle_sources = [ ] if env["platform"] == "macos": angle_sources += [ - "src/common/apple_platform_utils.mm", "src/common/system_utils_apple.cpp", - "src/common/system_utils_posix.cpp", "src/common/system_utils_mac.cpp", + "src/gpu_info_util/SystemInfo_macos.mm", + "src/libANGLE/renderer/driver_utils_mac.mm", "src/common/gl/cgl/FunctionsCGL.cpp", + "src/libANGLE/renderer/gl/cgl/ContextCGL.cpp", + "src/libANGLE/renderer/gl/cgl/DisplayCGL.mm", + "src/libANGLE/renderer/gl/cgl/DeviceCGL.cpp", + "src/libANGLE/renderer/gl/cgl/IOSurfaceSurfaceCGL.cpp", + "src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.cpp", + "src/libANGLE/renderer/gl/cgl/RendererCGL.cpp", + "src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm", + ] +if env["platform"] == "ios": + angle_sources += [ + "src/common/system_utils_ios.mm", + "src/gpu_info_util/SystemInfo_ios.cpp", + "src/libANGLE/renderer/driver_utils_ios.mm", + "src/libANGLE/renderer/gl/eagl/ContextEAGL.cpp", + "src/libANGLE/renderer/gl/eagl/DeviceEAGL.cpp", + "src/libANGLE/renderer/gl/eagl/DisplayEAGL.mm", + "src/libANGLE/renderer/gl/eagl/FunctionsEAGL.mm", + "src/libANGLE/renderer/gl/eagl/IOSurfaceSurfaceEAGL.mm", + "src/libANGLE/renderer/gl/eagl/PbufferSurfaceEAGL.cpp", + "src/libANGLE/renderer/gl/eagl/RendererEAGL.cpp", + "src/libANGLE/renderer/gl/eagl/WindowSurfaceEAGL.mm", + ] +if env["platform"] == "macos" or env["platform"] == "ios": + angle_sources += [ + "src/common/apple_platform_utils.mm", + "src/common/system_utils_posix.cpp", "src/compiler/translator/msl/AstHelpers.cpp", "src/compiler/translator/msl/ConstantNames.cpp", "src/compiler/translator/msl/DiscoverDependentFunctions.cpp", @@ -559,8 +585,6 @@ if env["platform"] == "macos": "src/compiler/translator/tree_ops/msl/TransposeRowMajorMatrices.cpp", "src/compiler/translator/tree_ops/msl/WrapMain.cpp", "src/gpu_info_util/SystemInfo_apple.mm", - "src/gpu_info_util/SystemInfo_macos.mm", - "src/libANGLE/renderer/driver_utils_mac.mm", "src/libANGLE/renderer/metal/BufferMtl.mm", "src/libANGLE/renderer/metal/CompilerMtl.mm", "src/libANGLE/renderer/metal/ContextMtl.mm", @@ -629,13 +653,6 @@ if env["platform"] == "macos": "src/libANGLE/renderer/gl/RenderbufferGL.cpp", "src/libANGLE/renderer/gl/SurfaceGL.cpp", "src/libANGLE/renderer/gl/null_functions.cpp", - "src/libANGLE/renderer/gl/cgl/ContextCGL.cpp", - "src/libANGLE/renderer/gl/cgl/DisplayCGL.mm", - "src/libANGLE/renderer/gl/cgl/DeviceCGL.cpp", - "src/libANGLE/renderer/gl/cgl/IOSurfaceSurfaceCGL.cpp", - "src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.cpp", - "src/libANGLE/renderer/gl/cgl/RendererCGL.cpp", - "src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm", ] if env["platform"] == "windows": angle_sources += [ @@ -760,11 +777,16 @@ env.Append(CPPDEFINES=[("ANGLE_CAPTURE_ENABLED", 0)]) env.Append(CPPDEFINES=[("ANGLE_ENABLE_ESSL", 1)]) env.Append(CPPDEFINES=[("ANGLE_ENABLE_GLSL", 1)]) env.Append(CPPDEFINES=[("ANGLE_EXPORT", '""')]) + +extra_suffix = "" + if env["arch"] in ["x86_64", "arm64"]: env.Append(CPPDEFINES=[("ANGLE_IS_64_BIT_CPU", 1)]) else: env.Append(CPPDEFINES=[("ANGLE_IS_32_BIT_CPU", 1)]) + if env["platform"] == "macos": + env.Append(CPPDEFINES=["ANGLE_PLATFORM_MACOS"]) env.Append(CPPDEFINES=[("ANGLE_IS_MAC", 1)]) env.Append(CPPDEFINES=[("ANGLE_ENABLE_METAL", 1)]) env.Append(CPPDEFINES=[("ANGLE_ENABLE_OPENGL", 1)]) @@ -772,6 +794,19 @@ if env["platform"] == "macos": env.Append(CPPDEFINES=[("ANGLE_ENABLE_GL_NULL", 1)]) env.Append(CPPDEFINES=[("ANGLE_ENABLE_CGL", 1)]) env.Append(CCFLAGS=["-fno-objc-arc", "-fno-objc-msgsend-selector-stubs", "-Wno-unused-command-line-argument"]) + +if env["platform"] == "ios": + if env["ios_simulator"]: + env.Append(CPPDEFINES=["ANGLE_PLATFORM_IOS_FAMILY"]) + extra_suffix = ".simulator" + extra_suffix + else: + env.Append(CPPDEFINES=["ANGLE_PLATFORM_IOS_FAMILY_SIMULATOR"]) + env.Append(CPPDEFINES=[("ANGLE_ENABLE_METAL", 1)]) + env.Append(CPPDEFINES=[("ANGLE_ENABLE_OPENGL", 1)]) + env.Append(CPPDEFINES=[("ANGLE_ENABLE_GL_NULL", 1)]) + env.Append(CPPDEFINES=[("ANGLE_ENABLE_EAGL", 1)]) + env.Append(CCFLAGS=["-fno-objc-arc", "-fno-objc-msgsend-selector-stubs", "-Wno-unused-command-line-argument"]) + if env["platform"] == "windows": env.Append(CPPDEFINES=[("ANGLE_IS_WIN", 1)]) env.Append( @@ -833,7 +868,7 @@ env_gles.Append(CPPDEFINES=[("LIBGLESV2_IMPLEMENTATION", 1)]) env_gles.Append(CPPDEFINES=[("EGL_EGL_PROTOTYPES", 0)]) env_gles.Append(CPPDEFINES=[("GL_GLES_PROTOTYPES", 0)]) -suffix = ".{}.{}".format(env["platform"], env["arch"]) +suffix = ".{}.{}".format(env["platform"], env["arch"]) + extra_suffix # Expose it when included from another project env["suffix"] = suffix diff --git a/godot-patches/patch_metal_cmd_buf_leak.diff b/godot-patches/patch_metal_cmd_buf_leak.diff new file mode 100644 index 00000000000..2f84ab9d079 --- /dev/null +++ b/godot-patches/patch_metal_cmd_buf_leak.diff @@ -0,0 +1,39 @@ +diff --git a/src/libANGLE/renderer/metal/ProgramMtl.mm b/src/libANGLE/renderer/metal/ProgramMtl.mm +index 04fc45023..b2a4f3f96 100644 +--- a/src/libANGLE/renderer/metal/ProgramMtl.mm ++++ b/src/libANGLE/renderer/metal/ProgramMtl.mm +@@ -350,7 +350,7 @@ void InitArgumentBufferEncoder(mtl::Context *context, + if (encoder->metalArgBufferEncoder) + { + encoder->bufferPool.initialize(context, encoder->metalArgBufferEncoder.get().encodedLength, +- mtl::kArgumentBufferOffsetAlignment, 0); ++ mtl::kArgumentBufferOffsetAlignment, 10); + } + } + +diff --git a/src/libANGLE/renderer/metal/ProvokingVertexHelper.mm b/src/libANGLE/renderer/metal/ProvokingVertexHelper.mm +index 3c3b47be1..0a186b63a 100644 +--- a/src/libANGLE/renderer/metal/ProvokingVertexHelper.mm ++++ b/src/libANGLE/renderer/metal/ProvokingVertexHelper.mm +@@ -101,7 +101,7 @@ static inline gl::PrimitiveMode getNewPrimitiveMode(const uint fixIndexBufferKey + } + ProvokingVertexHelper::ProvokingVertexHelper(ContextMtl *context) : mIndexBuffers(false) + { +- mIndexBuffers.initialize(context, kInitialIndexBufferSize, mtl::kIndexBufferOffsetAlignment, 0); ++ mIndexBuffers.initialize(context, kInitialIndexBufferSize, mtl::kIndexBufferOffsetAlignment, 10); + } + + void ProvokingVertexHelper::onDestroy(ContextMtl *context) +diff --git a/src/libANGLE/renderer/metal/VertexArrayMtl.mm b/src/libANGLE/renderer/metal/VertexArrayMtl.mm +index 1d30b2534..50e894ac3 100644 +--- a/src/libANGLE/renderer/metal/VertexArrayMtl.mm ++++ b/src/libANGLE/renderer/metal/VertexArrayMtl.mm +@@ -198,7 +198,7 @@ VertexArrayMtl::VertexArrayMtl(const gl::VertexArrayState &state, ContextMtl *co + /** maxBuffers */ 10 * mtl::kMaxVertexAttribs); + + mDynamicIndexData.initialize(context, kDynamicIndexDataSize, mtl::kIndexBufferOffsetAlignment, +- 0); ++ 10); + } + VertexArrayMtl::~VertexArrayMtl() {} + diff --git a/godot-tools/ios.py b/godot-tools/ios.py new file mode 100644 index 00000000000..84d41c48c43 --- /dev/null +++ b/godot-tools/ios.py @@ -0,0 +1,107 @@ +import os +import sys +import subprocess +from SCons.Variables import * + +if sys.version_info < (3,): + + def decode_utf8(x): + return x + +else: + import codecs + + def decode_utf8(x): + return codecs.utf_8_decode(x)[0] + + +def has_ios_osxcross(): + return "OSXCROSS_IOS" in os.environ + + +def options(opts): + opts.Add(BoolVariable("ios_simulator", "Target iOS Simulator", False)) + opts.Add(BoolVariable("ios_static", "Build iOS library", True)) + opts.Add("ios_min_version", "Target minimum iphoneos/iphonesimulator version", "12.0") + opts.Add( + "IOS_TOOLCHAIN_PATH", + "Path to iOS toolchain", + "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain", + ) + opts.Add("IOS_SDK_PATH", "Path to the iOS SDK", "") + + if has_ios_osxcross(): + opts.Add("ios_triple", "Triple for ios toolchain", "") + + +def exists(env): + return sys.platform == "darwin" or has_ios_osxcross() + + +def generate(env): + if env["arch"] not in ("universal", "arm64", "x86_64"): + raise ValueError("Only universal, arm64, and x86_64 are supported on iOS. Exiting.") + + if env["ios_simulator"]: + sdk_name = "iphonesimulator" + env.Append(CCFLAGS=["-mios-simulator-version-min=" + env["ios_min_version"]]) + else: + sdk_name = "iphoneos" + env.Append(CCFLAGS=["-miphoneos-version-min=" + env["ios_min_version"]]) + + if sys.platform == "darwin": + if env["IOS_SDK_PATH"] == "": + try: + env["IOS_SDK_PATH"] = decode_utf8( + subprocess.check_output(["xcrun", "--sdk", sdk_name, "--show-sdk-path"]).strip() + ) + except (subprocess.CalledProcessError, OSError): + raise ValueError( + "Failed to find SDK path while running xcrun --sdk {} --show-sdk-path.".format(sdk_name) + ) + + compiler_path = env["IOS_TOOLCHAIN_PATH"] + "/usr/bin/" + env["CC"] = compiler_path + "clang" + env["CXX"] = compiler_path + "clang++" + env["AR"] = compiler_path + "ar" + env["RANLIB"] = compiler_path + "ranlib" + env["SHLIBSUFFIX"] = ".dylib" + env["ENV"]["PATH"] = env["IOS_TOOLCHAIN_PATH"] + "/Developer/usr/bin/:" + env["ENV"]["PATH"] + + else: + # OSXCross + compiler_path = "$IOS_TOOLCHAIN_PATH/usr/bin/${ios_triple}" + env["CC"] = compiler_path + "clang" + env["CXX"] = compiler_path + "clang++" + env["AR"] = compiler_path + "ar" + env["RANLIB"] = compiler_path + "ranlib" + env["SHLIBSUFFIX"] = ".dylib" + + env.Prepend( + CPPPATH=[ + "$IOS_SDK_PATH/usr/include", + "$IOS_SDK_PATH/System/Library/Frameworks/AudioUnit.framework/Headers", + ] + ) + + env.Append(CCFLAGS=["-stdlib=libc++"]) + + binpath = os.path.join(env["IOS_TOOLCHAIN_PATH"], "usr", "bin") + if binpath not in env["ENV"]["PATH"]: + env.PrependENVPath("PATH", binpath) + + if env["arch"] == "universal": + if env["ios_simulator"]: + env.Append(LINKFLAGS=["-arch", "x86_64", "-arch", "arm64"]) + env.Append(CCFLAGS=["-arch", "x86_64", "-arch", "arm64"]) + else: + env.Append(LINKFLAGS=["-arch", "arm64"]) + env.Append(CCFLAGS=["-arch", "arm64"]) + else: + env.Append(LINKFLAGS=["-arch", env["arch"]]) + env.Append(CCFLAGS=["-arch", env["arch"]]) + + env.Append(CCFLAGS=["-isysroot", env["IOS_SDK_PATH"]]) + env.Append(LINKFLAGS=["-isysroot", env["IOS_SDK_PATH"], "-F" + env["IOS_SDK_PATH"]]) + + env.Append(CPPDEFINES=["IOS_ENABLED", "UNIX_ENABLED"]) diff --git a/src/libANGLE/renderer/metal/ProgramMtl.mm b/src/libANGLE/renderer/metal/ProgramMtl.mm index 04fc4502349..b2a4f3f96af 100644 --- a/src/libANGLE/renderer/metal/ProgramMtl.mm +++ b/src/libANGLE/renderer/metal/ProgramMtl.mm @@ -350,7 +350,7 @@ void InitArgumentBufferEncoder(mtl::Context *context, if (encoder->metalArgBufferEncoder) { encoder->bufferPool.initialize(context, encoder->metalArgBufferEncoder.get().encodedLength, - mtl::kArgumentBufferOffsetAlignment, 0); + mtl::kArgumentBufferOffsetAlignment, 10); } } diff --git a/src/libANGLE/renderer/metal/ProvokingVertexHelper.mm b/src/libANGLE/renderer/metal/ProvokingVertexHelper.mm index 3c3b47be1d5..0a186b63ad2 100644 --- a/src/libANGLE/renderer/metal/ProvokingVertexHelper.mm +++ b/src/libANGLE/renderer/metal/ProvokingVertexHelper.mm @@ -101,7 +101,7 @@ static inline uint indexCountForPrimCount(const uint fixIndexBufferKey, const ui } ProvokingVertexHelper::ProvokingVertexHelper(ContextMtl *context) : mIndexBuffers(false) { - mIndexBuffers.initialize(context, kInitialIndexBufferSize, mtl::kIndexBufferOffsetAlignment, 0); + mIndexBuffers.initialize(context, kInitialIndexBufferSize, mtl::kIndexBufferOffsetAlignment, 10); } void ProvokingVertexHelper::onDestroy(ContextMtl *context) diff --git a/src/libANGLE/renderer/metal/VertexArrayMtl.mm b/src/libANGLE/renderer/metal/VertexArrayMtl.mm index 1d30b25345d..50e894ac320 100644 --- a/src/libANGLE/renderer/metal/VertexArrayMtl.mm +++ b/src/libANGLE/renderer/metal/VertexArrayMtl.mm @@ -198,7 +198,7 @@ inline void SetDefaultVertexBufferLayout(mtl::VertexBufferLayoutDesc *layout) /** maxBuffers */ 10 * mtl::kMaxVertexAttribs); mDynamicIndexData.initialize(context, kDynamicIndexDataSize, mtl::kIndexBufferOffsetAlignment, - 0); + 10); } VertexArrayMtl::~VertexArrayMtl() {} diff --git a/src/libANGLE/renderer/metal/mtl_buffer_pool.mm b/src/libANGLE/renderer/metal/mtl_buffer_pool.mm index 2791fd12e1e..d287e3084cf 100644 --- a/src/libANGLE/renderer/metal/mtl_buffer_pool.mm +++ b/src/libANGLE/renderer/metal/mtl_buffer_pool.mm @@ -118,14 +118,14 @@ angle::Result BufferPool::allocateNewBuffer(ContextMtl *contextMtl) { - if (mMaxBuffers > 0 && mBuffersAllocated >= mMaxBuffers) + if ((mMaxBuffers > 0 && mBuffersAllocated >= mMaxBuffers)) { // We reach the max number of buffers allowed. // Try to deallocate old and smaller size inflight buffers. releaseInFlightBuffers(contextMtl); } - if (mMaxBuffers > 0 && mBuffersAllocated >= mMaxBuffers) + if ((mMaxBuffers > 0 && mBuffersAllocated >= mMaxBuffers)) { // If we reach this point, it means there was no buffer deallocated inside // releaseInFlightBuffers() thus, the number of buffers allocated still exceeds number