Skip to content

Commit 62de80d

Browse files
authored
Merge pull request godotengine#88199 from stuartcarnie/metal-rdd
Add Metal support for macOS (arm64) and iOS
2 parents 826de79 + 2d01655 commit 62de80d

File tree

72 files changed

+67923
-28
lines changed

Some content is hidden

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

72 files changed

+67923
-28
lines changed

.github/actions/godot-build/action.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,14 @@ inputs:
77
tests:
88
description: Unit tests.
99
default: false
10+
required: false
1011
platform:
1112
description: Target platform.
1213
required: false
1314
sconsflags:
15+
description: Additional SCons flags.
1416
default: ""
17+
required: false
1518
scons-cache:
1619
description: The SCons cache path.
1720
default: "${{ github.workspace }}/.scons-cache/"

COPYRIGHT.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,11 @@ Comment: RVO2
475475
Copyright: 2016, University of North Carolina at Chapel Hill
476476
License: Apache-2.0
477477

478+
Files: ./thirdparty/spirv-cross/
479+
Comment: SPIRV-Cross
480+
Copyright: 2015-2021, Arm Limited
481+
License: Apache-2.0 or Expat
482+
478483
Files: ./thirdparty/spirv-reflect/
479484
Comment: SPIRV-Reflect
480485
Copyright: 2017-2022, Google Inc.

SConstruct

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ opts.Add(BoolVariable("xaudio2", "Enable the XAudio2 audio driver", False))
222222
opts.Add(BoolVariable("vulkan", "Enable the vulkan rendering driver", True))
223223
opts.Add(BoolVariable("opengl3", "Enable the OpenGL/GLES3 rendering driver", True))
224224
opts.Add(BoolVariable("d3d12", "Enable the Direct3D 12 rendering driver", False))
225+
opts.Add(BoolVariable("metal", "Enable the Metal rendering driver (Apple arm64 only)", False))
225226
opts.Add(BoolVariable("openxr", "Enable the OpenXR driver", True))
226227
opts.Add(BoolVariable("use_volk", "Use the volk library to load the Vulkan loader dynamically", True))
227228
opts.Add(BoolVariable("disable_exceptions", "Force disabling exception handling code", True))

core/core_bind.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,7 @@ void OS::_bind_methods() {
692692
BIND_ENUM_CONSTANT(RENDERING_DRIVER_VULKAN);
693693
BIND_ENUM_CONSTANT(RENDERING_DRIVER_OPENGL3);
694694
BIND_ENUM_CONSTANT(RENDERING_DRIVER_D3D12);
695+
BIND_ENUM_CONSTANT(RENDERING_DRIVER_METAL);
695696

696697
BIND_ENUM_CONSTANT(SYSTEM_DIR_DESKTOP);
697698
BIND_ENUM_CONSTANT(SYSTEM_DIR_DCIM);

core/core_bind.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ class OS : public Object {
132132
RENDERING_DRIVER_VULKAN,
133133
RENDERING_DRIVER_OPENGL3,
134134
RENDERING_DRIVER_D3D12,
135+
RENDERING_DRIVER_METAL,
135136
};
136137

137138
PackedByteArray get_entropy(int p_bytes);

doc/classes/OS.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,9 @@
802802
<constant name="RENDERING_DRIVER_D3D12" value="2" enum="RenderingDriver">
803803
The Direct3D 12 rendering driver.
804804
</constant>
805+
<constant name="RENDERING_DRIVER_METAL" value="3" enum="RenderingDriver">
806+
The Metal rendering driver.
807+
</constant>
805808
<constant name="SYSTEM_DIR_DESKTOP" value="0" enum="SystemDir">
806809
Refers to the Desktop directory path.
807810
</constant>

drivers/SCsub

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ if env["opengl3"]:
3333
SConscript("gl_context/SCsub")
3434
SConscript("gles3/SCsub")
3535
SConscript("egl/SCsub")
36+
if env["metal"]:
37+
SConscript("metal/SCsub")
3638

3739
# Core dependencies
3840
SConscript("png/SCsub")

drivers/metal/README.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Metal Rendering Device
2+
3+
This document aims to describe the Metal rendering device implementation in Godot.
4+
5+
## Future work / ideas
6+
7+
* Use placement heaps
8+
* Explicit hazard tracking
9+
* [MetalFX] upscaling support?
10+
11+
## Acknowledgments
12+
13+
The Metal rendering owes a lot to the work of the [MoltenVK] project, which is a Vulkan implementation on top of Metal.
14+
In accordance with the Apache 2.0 license, the following copyright notices have been included where applicable:
15+
16+
```
17+
/**************************************************************************/
18+
/* */
19+
/* Portions of this code were derived from MoltenVK. */
20+
/* */
21+
/* Copyright (c) 2015-2023 The Brenwill Workshop Ltd. */
22+
/* (http://www.brenwill.com) */
23+
/* */
24+
/* Licensed under the Apache License, Version 2.0 (the "License"); */
25+
/* you may not use this file except in compliance with the License. */
26+
/* You may obtain a copy of the License at */
27+
/* */
28+
/* http://www.apache.org/licenses/LICENSE-2.0 */
29+
/* */
30+
/* Unless required by applicable law or agreed to in writing, software */
31+
/* distributed under the License is distributed on an "AS IS" BASIS, */
32+
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
33+
/* implied. See the License for the specific language governing */
34+
/* permissions and limitations under the License. */
35+
/**************************************************************************/
36+
```
37+
38+
[MoltenVK]: https://github.com/KhronosGroup/MoltenVK
39+
[MetalFX]: https://developer.apple.com/documentation/metalfx?language=objc

drivers/metal/SCsub

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#!/usr/bin/env python
2+
3+
Import("env")
4+
5+
env_metal = env.Clone()
6+
7+
# Thirdparty source files
8+
9+
thirdparty_obj = []
10+
11+
thirdparty_dir = "#thirdparty/spirv-cross/"
12+
thirdparty_sources = [
13+
"spirv_cfg.cpp",
14+
"spirv_cross_util.cpp",
15+
"spirv_cross.cpp",
16+
"spirv_parser.cpp",
17+
"spirv_msl.cpp",
18+
"spirv_reflect.cpp",
19+
"spirv_glsl.cpp",
20+
"spirv_cross_parsed_ir.cpp",
21+
]
22+
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
23+
24+
env_metal.Prepend(CPPPATH=[thirdparty_dir, thirdparty_dir + "/include"])
25+
26+
# Must enable exceptions for SPIRV-Cross; otherwise, it will abort the process on errors.
27+
if "-fno-exceptions" in env_metal["CXXFLAGS"]:
28+
env_metal["CXXFLAGS"].remove("-fno-exceptions")
29+
env_metal.Append(CXXFLAGS=["-fexceptions"])
30+
31+
env_thirdparty = env_metal.Clone()
32+
env_thirdparty.disable_warnings()
33+
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_sources)
34+
env_metal.drivers_sources += thirdparty_obj
35+
36+
# Enable C++20 for the Objective-C++ Metal code, which uses C++20 concepts.
37+
if "-std=gnu++17" in env_metal["CXXFLAGS"]:
38+
env_metal["CXXFLAGS"].remove("-std=gnu++17")
39+
env_metal.Append(CXXFLAGS=["-std=c++20"])
40+
41+
# Driver source files
42+
43+
driver_obj = []
44+
45+
env_metal.add_source_files(driver_obj, "*.mm")
46+
env.drivers_sources += driver_obj
47+
48+
# Needed to force rebuilding the driver files when the thirdparty library is updated.
49+
env.Depends(driver_obj, thirdparty_obj)
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
/**************************************************************************/
2+
/* metal_device_properties.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+
/**************************************************************************/
32+
/* */
33+
/* Portions of this code were derived from MoltenVK. */
34+
/* */
35+
/* Copyright (c) 2015-2023 The Brenwill Workshop Ltd. */
36+
/* (http://www.brenwill.com) */
37+
/* */
38+
/* Licensed under the Apache License, Version 2.0 (the "License"); */
39+
/* you may not use this file except in compliance with the License. */
40+
/* You may obtain a copy of the License at */
41+
/* */
42+
/* http://www.apache.org/licenses/LICENSE-2.0 */
43+
/* */
44+
/* Unless required by applicable law or agreed to in writing, software */
45+
/* distributed under the License is distributed on an "AS IS" BASIS, */
46+
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
47+
/* implied. See the License for the specific language governing */
48+
/* permissions and limitations under the License. */
49+
/**************************************************************************/
50+
51+
#ifndef METAL_DEVICE_PROPERTIES_H
52+
#define METAL_DEVICE_PROPERTIES_H
53+
54+
#import "servers/rendering/rendering_device.h"
55+
56+
#import <Foundation/Foundation.h>
57+
#import <Metal/Metal.h>
58+
59+
/** The buffer index to use for vertex content. */
60+
const static uint32_t VERT_CONTENT_BUFFER_INDEX = 0;
61+
const static uint32_t MAX_COLOR_ATTACHMENT_COUNT = 8;
62+
63+
typedef NS_OPTIONS(NSUInteger, SampleCount) {
64+
SampleCount1 = (1UL << 0),
65+
SampleCount2 = (1UL << 1),
66+
SampleCount4 = (1UL << 2),
67+
SampleCount8 = (1UL << 3),
68+
SampleCount16 = (1UL << 4),
69+
SampleCount32 = (1UL << 5),
70+
SampleCount64 = (1UL << 6),
71+
};
72+
73+
struct API_AVAILABLE(macos(11.0), ios(14.0)) MetalFeatures {
74+
uint32_t mslVersion;
75+
MTLGPUFamily highestFamily;
76+
MTLLanguageVersion mslVersionEnum;
77+
SampleCount supportedSampleCounts;
78+
long hostMemoryPageSize;
79+
bool layeredRendering;
80+
bool multisampleLayeredRendering;
81+
bool quadPermute; /**< If true, quadgroup permutation functions (vote, ballot, shuffle) are supported in shaders. */
82+
bool simdPermute; /**< If true, SIMD-group permutation functions (vote, ballot, shuffle) are supported in shaders. */
83+
bool simdReduction; /**< If true, SIMD-group reduction functions (arithmetic) are supported in shaders. */
84+
bool tessellationShader; /**< If true, tessellation shaders are supported. */
85+
bool imageCubeArray; /**< If true, image cube arrays are supported. */
86+
};
87+
88+
struct MetalLimits {
89+
uint64_t maxImageArrayLayers;
90+
uint64_t maxFramebufferHeight;
91+
uint64_t maxFramebufferWidth;
92+
uint64_t maxImageDimension1D;
93+
uint64_t maxImageDimension2D;
94+
uint64_t maxImageDimension3D;
95+
uint64_t maxImageDimensionCube;
96+
uint64_t maxViewportDimensionX;
97+
uint64_t maxViewportDimensionY;
98+
MTLSize maxThreadsPerThreadGroup;
99+
MTLSize maxComputeWorkGroupCount;
100+
uint64_t maxBoundDescriptorSets;
101+
uint64_t maxColorAttachments;
102+
uint64_t maxTexturesPerArgumentBuffer;
103+
uint64_t maxSamplersPerArgumentBuffer;
104+
uint64_t maxBuffersPerArgumentBuffer;
105+
uint64_t maxBufferLength;
106+
uint64_t minUniformBufferOffsetAlignment;
107+
uint64_t maxVertexDescriptorLayoutStride;
108+
uint16_t maxViewports;
109+
uint32_t maxPerStageBufferCount; /**< The total number of per-stage Metal buffers available for shader uniform content and attributes. */
110+
uint32_t maxPerStageTextureCount; /**< The total number of per-stage Metal textures available for shader uniform content. */
111+
uint32_t maxPerStageSamplerCount; /**< The total number of per-stage Metal samplers available for shader uniform content. */
112+
uint32_t maxVertexInputAttributes;
113+
uint32_t maxVertexInputBindings;
114+
uint32_t maxVertexInputBindingStride;
115+
uint32_t maxDrawIndexedIndexValue;
116+
117+
uint32_t minSubgroupSize; /**< The minimum number of threads in a SIMD-group. */
118+
uint32_t maxSubgroupSize; /**< The maximum number of threads in a SIMD-group. */
119+
BitField<RDD::ShaderStage> subgroupSupportedShaderStages;
120+
BitField<RD::SubgroupOperations> subgroupSupportedOperations; /**< The subgroup operations supported by the device. */
121+
};
122+
123+
class API_AVAILABLE(macos(11.0), ios(14.0)) MetalDeviceProperties {
124+
private:
125+
void init_features(id<MTLDevice> p_device);
126+
void init_limits(id<MTLDevice> p_device);
127+
128+
public:
129+
MetalFeatures features;
130+
MetalLimits limits;
131+
132+
SampleCount find_nearest_supported_sample_count(RenderingDevice::TextureSamples p_samples) const;
133+
134+
MetalDeviceProperties(id<MTLDevice> p_device);
135+
~MetalDeviceProperties();
136+
137+
private:
138+
static const SampleCount sample_count[RenderingDevice::TextureSamples::TEXTURE_SAMPLES_MAX];
139+
};
140+
141+
#endif // METAL_DEVICE_PROPERTIES_H

0 commit comments

Comments
 (0)