Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/drivers/metal/rendering_shader_container_metal.h
9973 views
1
/**************************************************************************/
2
/* rendering_shader_container_metal.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
#pragma once
32
33
#import "sha256_digest.h"
34
35
#import "servers/rendering/rendering_device_driver.h"
36
#import "servers/rendering/rendering_shader_container.h"
37
38
constexpr uint32_t R32UI_ALIGNMENT_CONSTANT_ID = 65535;
39
/// Metal buffer index for the view mask when rendering multi-view.
40
const uint32_t VIEW_MASK_BUFFER_INDEX = 24;
41
42
class RenderingShaderContainerFormatMetal;
43
44
/// @brief A minimal structure that defines a device profile for Metal.
45
///
46
/// This structure is used by the `RenderingShaderContainerMetal` class to
47
/// determine options for compiling SPIR-V to Metal source. It currently only
48
/// contains the minimum properties required to transform shaders from SPIR-V to Metal
49
/// and potentially compile to a `.metallib`.
50
struct MetalDeviceProfile {
51
enum class Platform : uint32_t {
52
macOS = 0,
53
iOS = 1,
54
};
55
56
/// @brief The GPU family.
57
enum class GPU : uint32_t {
58
Apple1,
59
Apple2,
60
Apple3,
61
Apple4,
62
Apple5,
63
Apple6,
64
Apple7,
65
Apple8,
66
Apple9,
67
};
68
69
enum class ArgumentBuffersTier : uint32_t {
70
Tier1 = 0,
71
Tier2 = 1,
72
};
73
74
struct Features {
75
uint32_t mslVersionMajor = 0;
76
uint32_t mslVersionMinor = 0;
77
ArgumentBuffersTier argument_buffers_tier = ArgumentBuffersTier::Tier1;
78
bool simdPermute = false;
79
};
80
81
Platform platform = Platform::macOS;
82
GPU gpu = GPU::Apple4;
83
Features features;
84
85
static const MetalDeviceProfile *get_profile(Platform p_platform, GPU p_gpu);
86
87
MetalDeviceProfile() = default;
88
89
private:
90
static Mutex profiles_lock; ///< Mutex to protect access to the profiles map.
91
static HashMap<uint32_t, MetalDeviceProfile> profiles;
92
};
93
94
class RenderingShaderContainerMetal : public RenderingShaderContainer {
95
GDSOFTCLASS(RenderingShaderContainerMetal, RenderingShaderContainer);
96
97
public:
98
struct HeaderData {
99
enum Flags : uint32_t {
100
NONE = 0,
101
NEEDS_VIEW_MASK_BUFFER = 1 << 0,
102
USES_ARGUMENT_BUFFERS = 1 << 1,
103
};
104
105
/// The base profile that was used to generate this shader.
106
MetalDeviceProfile profile;
107
108
/// The Metal language version specified when compiling SPIR-V to MSL.
109
/// Format is major * 10000 + minor * 100 + patch.
110
uint32_t msl_version = UINT32_MAX;
111
uint32_t flags = NONE;
112
113
/// @brief Returns `true` if the shader is compiled with multi-view support.
114
bool needs_view_mask_buffer() const {
115
return flags & NEEDS_VIEW_MASK_BUFFER;
116
}
117
118
void set_needs_view_mask_buffer(bool p_value) {
119
if (p_value) {
120
flags |= NEEDS_VIEW_MASK_BUFFER;
121
} else {
122
flags &= ~NEEDS_VIEW_MASK_BUFFER;
123
}
124
}
125
126
/// @brief Returns `true` if the shader was compiled with argument buffer support.
127
bool uses_argument_buffers() const {
128
return flags & USES_ARGUMENT_BUFFERS;
129
}
130
131
void set_uses_argument_buffers(bool p_value) {
132
if (p_value) {
133
flags |= USES_ARGUMENT_BUFFERS;
134
} else {
135
flags &= ~USES_ARGUMENT_BUFFERS;
136
}
137
}
138
};
139
140
struct StageData {
141
uint32_t vertex_input_binding_mask = 0;
142
uint32_t is_position_invariant = 0; ///< <c>true</c> if the position output is invariant
143
uint32_t supports_fast_math = 0;
144
SHA256Digest hash; ///< SHA 256 hash of the shader code
145
uint32_t source_size = 0; ///< size of the source code in the returned bytes
146
uint32_t library_size = 0; ///< size of the compiled library in the returned bytes, 0 if it is not compiled
147
uint32_t push_constant_binding = UINT32_MAX; ///< Metal binding slot for the push constant data
148
};
149
150
struct BindingInfoData {
151
uint32_t shader_stage = UINT32_MAX; ///< The shader stage this binding is used in, or UINT32_MAX if not used.
152
uint32_t data_type = 0; // MTLDataTypeNone
153
uint32_t index = 0;
154
uint32_t access = 0; // MTLBindingAccessReadOnly
155
uint32_t usage = 0; // MTLResourceUsage (none)
156
uint32_t texture_type = 2; // MTLTextureType2D
157
uint32_t image_format = 0;
158
uint32_t array_length = 0;
159
uint32_t is_multisampled = 0;
160
};
161
162
struct UniformData {
163
/// Specifies the index into the `bindings` array for the shader stage.
164
///
165
/// For example, a vertex and fragment shader use slots 0 and 1 of the bindings and bindings_secondary arrays.
166
static constexpr uint32_t STAGE_INDEX[RenderingDeviceCommons::SHADER_STAGE_MAX] = {
167
0, // SHADER_STAGE_VERTEX
168
1, // SHADER_STAGE_FRAGMENT
169
0, // SHADER_STAGE_TESSELATION_CONTROL
170
1, // SHADER_STAGE_TESSELATION_EVALUATION
171
0, // SHADER_STAGE_COMPUTE
172
};
173
174
/// Specifies the stages the uniform data is
175
/// used by the Metal shader.
176
uint32_t active_stages = 0;
177
/// The primary binding information for the uniform data.
178
///
179
/// A maximum of two stages is expected for any given pipeline, such as a vertex and fragment, so
180
/// the array size is fixed to 2.
181
BindingInfoData bindings[2];
182
/// The secondary binding information for the uniform data.
183
///
184
/// This is typically a sampler for an image-sampler uniform
185
BindingInfoData bindings_secondary[2];
186
187
_FORCE_INLINE_ constexpr uint32_t get_index_for_stage(RenderingDeviceCommons::ShaderStage p_stage) const {
188
return STAGE_INDEX[p_stage];
189
}
190
191
_FORCE_INLINE_ BindingInfoData &get_binding_for_stage(RenderingDeviceCommons::ShaderStage p_stage) {
192
BindingInfoData &info = bindings[get_index_for_stage(p_stage)];
193
DEV_ASSERT(info.shader_stage == UINT32_MAX || info.shader_stage == p_stage); // make sure this uniform isn't used in the other stage
194
info.shader_stage = p_stage;
195
return info;
196
}
197
198
_FORCE_INLINE_ BindingInfoData &get_secondary_binding_for_stage(RenderingDeviceCommons::ShaderStage p_stage) {
199
BindingInfoData &info = bindings_secondary[get_index_for_stage(p_stage)];
200
DEV_ASSERT(info.shader_stage == UINT32_MAX || info.shader_stage == p_stage); // make sure this uniform isn't used in the other stage
201
info.shader_stage = p_stage;
202
return info;
203
}
204
};
205
206
struct SpecializationData {
207
uint32_t used_stages = 0;
208
};
209
210
HeaderData mtl_reflection_data; // compliment to reflection_data
211
Vector<StageData> mtl_shaders; // compliment to shaders
212
213
private:
214
const MetalDeviceProfile *device_profile = nullptr;
215
bool export_mode = false;
216
217
Vector<UniformData> mtl_reflection_binding_set_uniforms_data; // compliment to reflection_binding_set_uniforms_data
218
Vector<SpecializationData> mtl_reflection_specialization_data; // compliment to reflection_specialization_data
219
220
Error compile_metal_source(const char *p_source, const StageData &p_stage_data, Vector<uint8_t> &r_binary_data);
221
222
public:
223
static constexpr uint32_t FORMAT_VERSION = 1;
224
225
void set_export_mode(bool p_export_mode) { export_mode = p_export_mode; }
226
void set_device_profile(const MetalDeviceProfile *p_device_profile) { device_profile = p_device_profile; }
227
228
struct MetalShaderReflection {
229
Vector<Vector<UniformData>> uniform_sets;
230
Vector<SpecializationData> specialization_constants;
231
};
232
233
MetalShaderReflection get_metal_shader_reflection() const;
234
235
protected:
236
virtual uint32_t _from_bytes_reflection_extra_data(const uint8_t *p_bytes) override;
237
virtual uint32_t _from_bytes_reflection_binding_uniform_extra_data_start(const uint8_t *p_bytes) override;
238
virtual uint32_t _from_bytes_reflection_binding_uniform_extra_data(const uint8_t *p_bytes, uint32_t p_index) override;
239
virtual uint32_t _from_bytes_reflection_specialization_extra_data_start(const uint8_t *p_bytes) override;
240
virtual uint32_t _from_bytes_reflection_specialization_extra_data(const uint8_t *p_bytes, uint32_t p_index) override;
241
virtual uint32_t _from_bytes_shader_extra_data_start(const uint8_t *p_bytes) override;
242
virtual uint32_t _from_bytes_shader_extra_data(const uint8_t *p_bytes, uint32_t p_index) override;
243
244
virtual uint32_t _to_bytes_reflection_extra_data(uint8_t *p_bytes) const override;
245
virtual uint32_t _to_bytes_reflection_binding_uniform_extra_data(uint8_t *p_bytes, uint32_t p_index) const override;
246
virtual uint32_t _to_bytes_reflection_specialization_extra_data(uint8_t *p_bytes, uint32_t p_index) const override;
247
virtual uint32_t _to_bytes_shader_extra_data(uint8_t *p_bytes, uint32_t p_index) const override;
248
249
virtual uint32_t _format() const override;
250
virtual uint32_t _format_version() const override;
251
virtual bool _set_code_from_spirv(const Vector<RenderingDeviceCommons::ShaderStageSPIRVData> &p_spirv) override;
252
};
253
254
class RenderingShaderContainerFormatMetal : public RenderingShaderContainerFormat {
255
bool export_mode = false;
256
257
const MetalDeviceProfile *device_profile = nullptr;
258
259
public:
260
virtual Ref<RenderingShaderContainer> create_container() const override;
261
virtual ShaderLanguageVersion get_shader_language_version() const override;
262
virtual ShaderSpirvVersion get_shader_spirv_version() const override;
263
RenderingShaderContainerFormatMetal(const MetalDeviceProfile *p_device_profile, bool p_export = false);
264
virtual ~RenderingShaderContainerFormatMetal() = default;
265
};
266
267