blob: aa6de744b3f93d34c4ea9eb997b4135b7e1772e3 [file] [log] [blame]
Bill Hollings103aabf2016-04-06 17:42:27 -04001/*
Hans-Kristian Arntzen47044822021-01-14 16:07:49 +01002 * Copyright 2016-2021 The Brenwill Workshop Ltd.
Jon Leechf2a65542021-05-08 01:47:48 -07003 * SPDX-License-Identifier: Apache-2.0 OR MIT
Bill Hollings103aabf2016-04-06 17:42:27 -04004 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
Hans-Kristian Arntzencf1e9e02020-11-25 15:22:08 +010018/*
19 * At your option, you may choose to accept this material under either:
20 * 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
21 * 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
Hans-Kristian Arntzencf1e9e02020-11-25 15:22:08 +010022 */
23
Hans-Kristian Arntzendad4a342016-11-11 18:04:14 +010024#ifndef SPIRV_CROSS_MSL_HPP
25#define SPIRV_CROSS_MSL_HPP
Bill Hollings103aabf2016-04-06 17:42:27 -040026
27#include "spirv_glsl.hpp"
Bill Hollings81757502017-01-29 13:28:20 -050028#include <map>
Bill Hollings103aabf2016-04-06 17:42:27 -040029#include <set>
Hans-Kristian Arntzenb4e01632019-06-21 16:02:22 +020030#include <stddef.h>
Bill Hollings1a5dc0e2016-12-18 21:42:10 -050031#include <unordered_map>
Bill Hollings32ae2ec2016-12-18 18:48:15 -050032#include <unordered_set>
Bill Hollings103aabf2016-04-06 17:42:27 -040033
Hans-Kristian Arntzen9b92e682019-03-29 10:29:44 +010034namespace SPIRV_CROSS_NAMESPACE
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +020035{
Bill Hollings103aabf2016-04-06 17:42:27 -040036
Chip Davis5281d992020-06-13 23:03:30 -050037// Indicates the format of a shader input. Currently limited to specifying
38// if the input is an 8-bit unsigned integer, 16-bit unsigned integer, or
Chip Davis6db79b82018-12-04 13:54:29 -060039// some other format.
Chip Davis5281d992020-06-13 23:03:30 -050040enum MSLShaderInputFormat
Chip Davis6db79b82018-12-04 13:54:29 -060041{
Chip Davis5281d992020-06-13 23:03:30 -050042 MSL_SHADER_INPUT_FORMAT_OTHER = 0,
43 MSL_SHADER_INPUT_FORMAT_UINT8 = 1,
44 MSL_SHADER_INPUT_FORMAT_UINT16 = 2,
Chip Davis688c5fc2020-02-20 21:38:28 -060045 MSL_SHADER_INPUT_FORMAT_ANY16 = 3,
46 MSL_SHADER_INPUT_FORMAT_ANY32 = 4,
Chip Davis5281d992020-06-13 23:03:30 -050047
48 // Deprecated aliases.
49 MSL_VERTEX_FORMAT_OTHER = MSL_SHADER_INPUT_FORMAT_OTHER,
50 MSL_VERTEX_FORMAT_UINT8 = MSL_SHADER_INPUT_FORMAT_UINT8,
51 MSL_VERTEX_FORMAT_UINT16 = MSL_SHADER_INPUT_FORMAT_UINT16,
52
53 MSL_SHADER_INPUT_FORMAT_INT_MAX = 0x7fffffff
Chip Davis6db79b82018-12-04 13:54:29 -060054};
Bill Hollings103aabf2016-04-06 17:42:27 -040055
Chip Davis5281d992020-06-13 23:03:30 -050056// Defines MSL characteristics of an input variable at a particular location.
57// After compilation, it is possible to query whether or not this location was used.
58// If vecsize is nonzero, it must be greater than or equal to the vecsize declared in the shader,
59// or behavior is undefined.
60struct MSLShaderInput
61{
62 uint32_t location = 0;
Bill Hollings548a23d2021-09-20 17:57:11 -040063 uint32_t component = 0;
Chip Davis5281d992020-06-13 23:03:30 -050064 MSLShaderInputFormat format = MSL_SHADER_INPUT_FORMAT_OTHER;
65 spv::BuiltIn builtin = spv::BuiltInMax;
66 uint32_t vecsize = 0;
67};
68
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +020069// Matches the binding index of a MSL resource for a binding within a descriptor set.
70// Taken together, the stage, desc_set and binding combine to form a reference to a resource
Bill Hollings4bdd49d2020-11-02 22:15:20 -050071// descriptor used in a particular shading stage. The count field indicates the number of
Bill Hollingsb7b0e802020-10-29 18:50:42 -040072// resources consumed by this binding, if the binding represents an array of resources.
73// If the resource array is a run-time-sized array, which are legal in GLSL or SPIR-V, this value
74// will be used to declare the array size in MSL, which does not support run-time-sized arrays.
Bill Hollings17dab612021-04-13 19:01:20 -040075// If pad_argument_buffer_resources is enabled, the base_type and count values are used to
76// specify the base type and array size of the resource in the argument buffer, if that resource
77// is not defined and used by the shader. With pad_argument_buffer_resources enabled, this
78// information will be used to pad the argument buffer structure, in order to align that
79// structure consistently for all uses, across all shaders, of the descriptor set represented
80// by the arugment buffer. If pad_argument_buffer_resources is disabled, base_type does not
81// need to be populated, and if the resource is also not a run-time sized array, the count
82// field does not need to be populated.
Chip Davis10381702019-09-04 13:57:17 -050083// If using MSL 2.0 argument buffers, the descriptor set is not marked as a discrete descriptor set,
84// and (for iOS only) the resource is not a storage image (sampled != 2), the binding reference we
85// remap to will become an [[id(N)]] attribute within the "descriptor set" argument buffer structure.
Bill Hollings17dab612021-04-13 19:01:20 -040086// For resources which are bound in the "classic" MSL 1.0 way or discrete descriptors, the remap will
87// become a [[buffer(N)]], [[texture(N)]] or [[sampler(N)]] depending on the resource types used.
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +020088struct MSLResourceBinding
89{
Hans-Kristian Arntzen9bbdccd2019-02-12 11:11:29 +010090 spv::ExecutionModel stage = spv::ExecutionModelMax;
Bill Hollingsb3bfe222021-04-18 17:34:55 -040091 SPIRType::BaseType basetype = SPIRType::Unknown;
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +020092 uint32_t desc_set = 0;
93 uint32_t binding = 0;
Bill Hollings4bdd49d2020-11-02 22:15:20 -050094 uint32_t count = 0;
Hans-Kristian Arntzene74c21a2019-03-04 10:08:31 +010095 uint32_t msl_buffer = 0;
96 uint32_t msl_texture = 0;
97 uint32_t msl_sampler = 0;
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +020098};
Bill Hollings8f30f072016-04-07 21:25:51 -040099
Hans-Kristian Arntzendf58deb2018-04-17 17:43:10 +0200100enum MSLSamplerCoord
101{
Hans-Kristian Arntzen9bbdccd2019-02-12 11:11:29 +0100102 MSL_SAMPLER_COORD_NORMALIZED = 0,
103 MSL_SAMPLER_COORD_PIXEL = 1,
104 MSL_SAMPLER_INT_MAX = 0x7fffffff
Hans-Kristian Arntzendf58deb2018-04-17 17:43:10 +0200105};
106
107enum MSLSamplerFilter
108{
Hans-Kristian Arntzen9bbdccd2019-02-12 11:11:29 +0100109 MSL_SAMPLER_FILTER_NEAREST = 0,
110 MSL_SAMPLER_FILTER_LINEAR = 1,
111 MSL_SAMPLER_FILTER_INT_MAX = 0x7fffffff
Hans-Kristian Arntzendf58deb2018-04-17 17:43:10 +0200112};
113
114enum MSLSamplerMipFilter
115{
Hans-Kristian Arntzen9bbdccd2019-02-12 11:11:29 +0100116 MSL_SAMPLER_MIP_FILTER_NONE = 0,
117 MSL_SAMPLER_MIP_FILTER_NEAREST = 1,
118 MSL_SAMPLER_MIP_FILTER_LINEAR = 2,
119 MSL_SAMPLER_MIP_FILTER_INT_MAX = 0x7fffffff
Hans-Kristian Arntzendf58deb2018-04-17 17:43:10 +0200120};
121
122enum MSLSamplerAddress
123{
Hans-Kristian Arntzen9bbdccd2019-02-12 11:11:29 +0100124 MSL_SAMPLER_ADDRESS_CLAMP_TO_ZERO = 0,
125 MSL_SAMPLER_ADDRESS_CLAMP_TO_EDGE = 1,
126 MSL_SAMPLER_ADDRESS_CLAMP_TO_BORDER = 2,
127 MSL_SAMPLER_ADDRESS_REPEAT = 3,
128 MSL_SAMPLER_ADDRESS_MIRRORED_REPEAT = 4,
129 MSL_SAMPLER_ADDRESS_INT_MAX = 0x7fffffff
Hans-Kristian Arntzendf58deb2018-04-17 17:43:10 +0200130};
131
132enum MSLSamplerCompareFunc
133{
Hans-Kristian Arntzen9bbdccd2019-02-12 11:11:29 +0100134 MSL_SAMPLER_COMPARE_FUNC_NEVER = 0,
135 MSL_SAMPLER_COMPARE_FUNC_LESS = 1,
136 MSL_SAMPLER_COMPARE_FUNC_LESS_EQUAL = 2,
137 MSL_SAMPLER_COMPARE_FUNC_GREATER = 3,
138 MSL_SAMPLER_COMPARE_FUNC_GREATER_EQUAL = 4,
139 MSL_SAMPLER_COMPARE_FUNC_EQUAL = 5,
140 MSL_SAMPLER_COMPARE_FUNC_NOT_EQUAL = 6,
141 MSL_SAMPLER_COMPARE_FUNC_ALWAYS = 7,
142 MSL_SAMPLER_COMPARE_FUNC_INT_MAX = 0x7fffffff
Hans-Kristian Arntzendf58deb2018-04-17 17:43:10 +0200143};
144
145enum MSLSamplerBorderColor
146{
Hans-Kristian Arntzen9bbdccd2019-02-12 11:11:29 +0100147 MSL_SAMPLER_BORDER_COLOR_TRANSPARENT_BLACK = 0,
148 MSL_SAMPLER_BORDER_COLOR_OPAQUE_BLACK = 1,
149 MSL_SAMPLER_BORDER_COLOR_OPAQUE_WHITE = 2,
150 MSL_SAMPLER_BORDER_COLOR_INT_MAX = 0x7fffffff
Hans-Kristian Arntzendf58deb2018-04-17 17:43:10 +0200151};
152
Chip Davis39dce882019-08-02 15:11:19 -0500153enum MSLFormatResolution
154{
155 MSL_FORMAT_RESOLUTION_444 = 0,
156 MSL_FORMAT_RESOLUTION_422,
157 MSL_FORMAT_RESOLUTION_420,
158 MSL_FORMAT_RESOLUTION_INT_MAX = 0x7fffffff
159};
160
161enum MSLChromaLocation
162{
163 MSL_CHROMA_LOCATION_COSITED_EVEN = 0,
164 MSL_CHROMA_LOCATION_MIDPOINT,
165 MSL_CHROMA_LOCATION_INT_MAX = 0x7fffffff
166};
167
168enum MSLComponentSwizzle
169{
170 MSL_COMPONENT_SWIZZLE_IDENTITY = 0,
171 MSL_COMPONENT_SWIZZLE_ZERO,
172 MSL_COMPONENT_SWIZZLE_ONE,
173 MSL_COMPONENT_SWIZZLE_R,
174 MSL_COMPONENT_SWIZZLE_G,
175 MSL_COMPONENT_SWIZZLE_B,
176 MSL_COMPONENT_SWIZZLE_A,
177 MSL_COMPONENT_SWIZZLE_INT_MAX = 0x7fffffff
178};
179
180enum MSLSamplerYCbCrModelConversion
181{
182 MSL_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY = 0,
183 MSL_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY,
184 MSL_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_BT_709,
185 MSL_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_BT_601,
186 MSL_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_BT_2020,
187 MSL_SAMPLER_YCBCR_MODEL_CONVERSION_INT_MAX = 0x7fffffff
188};
189
190enum MSLSamplerYCbCrRange
191{
192 MSL_SAMPLER_YCBCR_RANGE_ITU_FULL = 0,
193 MSL_SAMPLER_YCBCR_RANGE_ITU_NARROW,
194 MSL_SAMPLER_YCBCR_RANGE_INT_MAX = 0x7fffffff
195};
196
Hans-Kristian Arntzendf58deb2018-04-17 17:43:10 +0200197struct MSLConstexprSampler
198{
Hans-Kristian Arntzene30a9422018-04-18 16:19:55 +0200199 MSLSamplerCoord coord = MSL_SAMPLER_COORD_NORMALIZED;
200 MSLSamplerFilter min_filter = MSL_SAMPLER_FILTER_NEAREST;
201 MSLSamplerFilter mag_filter = MSL_SAMPLER_FILTER_NEAREST;
202 MSLSamplerMipFilter mip_filter = MSL_SAMPLER_MIP_FILTER_NONE;
203 MSLSamplerAddress s_address = MSL_SAMPLER_ADDRESS_CLAMP_TO_EDGE;
204 MSLSamplerAddress t_address = MSL_SAMPLER_ADDRESS_CLAMP_TO_EDGE;
205 MSLSamplerAddress r_address = MSL_SAMPLER_ADDRESS_CLAMP_TO_EDGE;
206 MSLSamplerCompareFunc compare_func = MSL_SAMPLER_COMPARE_FUNC_NEVER;
207 MSLSamplerBorderColor border_color = MSL_SAMPLER_BORDER_COLOR_TRANSPARENT_BLACK;
208 float lod_clamp_min = 0.0f;
209 float lod_clamp_max = 1000.0f;
210 int max_anisotropy = 1;
Hans-Kristian Arntzendf58deb2018-04-17 17:43:10 +0200211
Chip Davis39dce882019-08-02 15:11:19 -0500212 // Sampler Y'CbCr conversion parameters
213 uint32_t planes = 0;
214 MSLFormatResolution resolution = MSL_FORMAT_RESOLUTION_444;
215 MSLSamplerFilter chroma_filter = MSL_SAMPLER_FILTER_NEAREST;
216 MSLChromaLocation x_chroma_offset = MSL_CHROMA_LOCATION_COSITED_EVEN;
217 MSLChromaLocation y_chroma_offset = MSL_CHROMA_LOCATION_COSITED_EVEN;
218 MSLComponentSwizzle swizzle[4]; // IDENTITY, IDENTITY, IDENTITY, IDENTITY
219 MSLSamplerYCbCrModelConversion ycbcr_model = MSL_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY;
220 MSLSamplerYCbCrRange ycbcr_range = MSL_SAMPLER_YCBCR_RANGE_ITU_FULL;
221 uint32_t bpc = 8;
222
Hans-Kristian Arntzene30a9422018-04-18 16:19:55 +0200223 bool compare_enable = false;
224 bool lod_clamp_enable = false;
225 bool anisotropy_enable = false;
Chip Davis39dce882019-08-02 15:11:19 -0500226 bool ycbcr_conversion_enable = false;
227
228 MSLConstexprSampler()
229 {
230 for (uint32_t i = 0; i < 4; i++)
231 swizzle[i] = MSL_COMPONENT_SWIZZLE_IDENTITY;
232 }
233 bool swizzle_is_identity() const
234 {
235 return (swizzle[0] == MSL_COMPONENT_SWIZZLE_IDENTITY && swizzle[1] == MSL_COMPONENT_SWIZZLE_IDENTITY &&
236 swizzle[2] == MSL_COMPONENT_SWIZZLE_IDENTITY && swizzle[3] == MSL_COMPONENT_SWIZZLE_IDENTITY);
237 }
238 bool swizzle_has_one_or_zero() const
239 {
240 return (swizzle[0] == MSL_COMPONENT_SWIZZLE_ZERO || swizzle[0] == MSL_COMPONENT_SWIZZLE_ONE ||
241 swizzle[1] == MSL_COMPONENT_SWIZZLE_ZERO || swizzle[1] == MSL_COMPONENT_SWIZZLE_ONE ||
242 swizzle[2] == MSL_COMPONENT_SWIZZLE_ZERO || swizzle[2] == MSL_COMPONENT_SWIZZLE_ONE ||
243 swizzle[3] == MSL_COMPONENT_SWIZZLE_ZERO || swizzle[3] == MSL_COMPONENT_SWIZZLE_ONE);
244 }
Hans-Kristian Arntzendf58deb2018-04-17 17:43:10 +0200245};
246
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200247// Special constant used in a MSLResourceBinding desc_set
248// element to indicate the bindings for the push constants.
Hans-Kristian Arntzencc153f82020-01-09 11:18:14 +0100249// Kinda deprecated. Just use ResourceBindingPushConstant{DescriptorSet,Binding} directly.
250static const uint32_t kPushConstDescSet = ResourceBindingPushConstantDescriptorSet;
Bill Hollings103aabf2016-04-06 17:42:27 -0400251
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200252// Special constant used in a MSLResourceBinding binding
253// element to indicate the bindings for the push constants.
Hans-Kristian Arntzencc153f82020-01-09 11:18:14 +0100254// Kinda deprecated. Just use ResourceBindingPushConstant{DescriptorSet,Binding} directly.
255static const uint32_t kPushConstBinding = ResourceBindingPushConstantBinding;
Bill Hollings103aabf2016-04-06 17:42:27 -0400256
Hans-Kristian Arntzeneaf7afe2019-05-09 12:15:45 +0200257// Special constant used in a MSLResourceBinding binding
258// element to indicate the buffer binding for swizzle buffers.
259static const uint32_t kSwizzleBufferBinding = ~(1u);
Hans-Kristian Arntzene47a77d2019-03-14 10:29:34 +0100260
Hans-Kristian Arntzen7b9e0fb2019-05-27 11:59:29 +0200261// Special constant used in a MSLResourceBinding binding
262// element to indicate the buffer binding for buffer size buffers to support OpArrayLength.
263static const uint32_t kBufferSizeBufferBinding = ~(2u);
264
Hans-Kristian Arntzen048f2382019-06-24 10:45:13 +0200265// Special constant used in a MSLResourceBinding binding
266// element to indicate the buffer binding used for the argument buffer itself.
267// This buffer binding should be kept as small as possible as all automatic bindings for buffers
268// will start at max(kArgumentBufferBinding) + 1.
269static const uint32_t kArgumentBufferBinding = ~(3u);
270
Hans-Kristian Arntzeneaf7afe2019-05-09 12:15:45 +0200271static const uint32_t kMaxArgumentBuffers = 8;
Chip Davisf55253d2019-02-06 14:45:26 -0600272
Corentin Wallezbcd71532020-09-04 10:04:25 +0200273// The arbitrary maximum for the nesting of array of array copies.
274static const uint32_t kArrayCopyMultidimMax = 6;
275
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200276// Decompiles SPIR-V to Metal Shading Language
277class CompilerMSL : public CompilerGLSL
278{
279public:
Bill Hollings5550c872017-03-12 17:42:51 -0400280 // Options for compiling to Metal Shading Language
281 struct Options
282 {
Hans-Kristian Arntzen382101b2018-04-03 14:08:15 +0200283 typedef enum
284 {
Hans-Kristian Arntzen9bbdccd2019-02-12 11:11:29 +0100285 iOS = 0,
286 macOS = 1
Bill Hollings3fcdce02017-12-26 13:39:07 -0500287 } Platform;
288
289 Platform platform = macOS;
Bill Hollings10148472017-11-10 16:40:33 -0500290 uint32_t msl_version = make_msl_version(1, 2);
Hans-Kristian Arntzen9ddbd5a2018-06-28 23:00:26 +0200291 uint32_t texel_buffer_texture_width = 4096; // Width of 2D Metal textures used as 1D texel buffers
Chip Davis21d38f72020-10-13 13:20:49 -0500292 uint32_t r32ui_linear_texture_alignment = 4;
293 uint32_t r32ui_alignment_constant_id = 65535;
Hans-Kristian Arntzeneaf7afe2019-05-09 12:15:45 +0200294 uint32_t swizzle_buffer_index = 30;
Chip Davis056c0e22019-02-06 15:17:14 -0600295 uint32_t indirect_params_buffer_index = 29;
296 uint32_t shader_output_buffer_index = 28;
Chip Daviseb89c3a2019-02-03 23:58:46 -0600297 uint32_t shader_patch_output_buffer_index = 27;
298 uint32_t shader_tess_factor_buffer_index = 26;
Hans-Kristian Arntzen7b9e0fb2019-05-27 11:59:29 +0200299 uint32_t buffer_size_buffer_index = 25;
Chip Davis7eecf5a2019-05-31 12:06:20 -0500300 uint32_t view_mask_buffer_index = 24;
Chip Daviscb359342019-09-05 23:14:12 -0500301 uint32_t dynamic_offsets_buffer_index = 23;
Chip Davis688c5fc2020-02-20 21:38:28 -0600302 uint32_t shader_input_buffer_index = 22;
303 uint32_t shader_index_buffer_index = 21;
Chip Daviseb89c3a2019-02-03 23:58:46 -0600304 uint32_t shader_input_wg_index = 0;
Chip Davis6a585542019-07-12 21:50:50 -0500305 uint32_t device_index = 0;
Chip Davisb29f83c2020-04-10 01:13:33 -0500306 uint32_t enable_frag_output_mask = 0xffffffff;
Tomek Ponitka18f23c42020-07-22 18:37:17 +0200307 // Metal doesn't allow setting a fixed sample mask directly in the pipeline.
308 // We can evade this restriction by ANDing the internal sample_mask output
309 // of the shader with the additional fixed sample mask.
310 uint32_t additional_fixed_sample_mask = 0xffffffff;
Bill Hollings1c180782017-11-05 21:34:42 -0500311 bool enable_point_size_builtin = true;
Chip Davisb29f83c2020-04-10 01:13:33 -0500312 bool enable_frag_depth_builtin = true;
313 bool enable_frag_stencil_ref_builtin = true;
Bill Hollings0d6202e2018-07-26 16:40:32 -0400314 bool disable_rasterization = false;
Chip Davisc51e5b72019-01-08 16:33:32 -0600315 bool capture_output_to_buffer = false;
Chip Davis25833212018-09-19 20:36:33 -0500316 bool swizzle_texture_samples = false;
Chip Davis41d94242019-02-05 23:47:50 -0600317 bool tess_domain_origin_lower_left = false;
Chip Davis7eecf5a2019-05-31 12:06:20 -0500318 bool multiview = false;
Chip Daviscab73352020-08-23 16:44:41 -0500319 bool multiview_layered_rendering = true;
Chip Davis6a585542019-07-12 21:50:50 -0500320 bool view_index_from_device_index = false;
Chip Davisfb5ee4c2019-07-22 13:08:04 -0500321 bool dispatch_base = false;
Bill Hollings4b5c6c12019-10-24 12:31:20 -0400322 bool texture_1D_as_2D = false;
Hans-Kristian Arntzena5f072d2019-03-15 13:07:59 +0100323
324 // Enable use of MSL 2.0 indirect argument buffers.
325 // MSL 2.0 must also be enabled.
Hans-Kristian Arntzene47a77d2019-03-14 10:29:34 +0100326 bool argument_buffers = false;
Bill Hollingsbac657d2017-11-07 15:38:13 -0500327
Lukas Hermanns7ad0a842019-09-23 18:05:04 -0400328 // Ensures vertex and instance indices start at zero. This reflects the behavior of HLSL with SV_VertexID and SV_InstanceID.
329 bool enable_base_index_zero = false;
330
Hans-Kristian Arntzenb8033d72019-01-14 14:53:47 +0100331 // Fragment output in MSL must have at least as many components as the render pass.
332 // Add support to explicit pad out components.
333 bool pad_fragment_output_components = false;
334
Lukas Hermanns7ad0a842019-09-23 18:05:04 -0400335 // Specifies whether the iOS target version supports the [[base_vertex]] and [[base_instance]] attributes.
336 bool ios_support_base_vertex_instance = false;
337
338 // Use Metal's native frame-buffer fetch API for subpass inputs.
Chip Davisc20d5942020-10-27 21:42:33 -0500339 bool use_framebuffer_fetch_subpasses = false;
Lukas Hermanns7ad0a842019-09-23 18:05:04 -0400340
Lukas Hermannsffbd8012019-10-09 11:22:25 -0400341 // Enables use of "fma" intrinsic for invariant float math
Mark Satterthwaite69b703f2019-08-14 11:25:18 -0400342 bool invariant_float_math = false;
Lukas Hermanns7ad0a842019-09-23 18:05:04 -0400343
344 // Emulate texturecube_array with texture2d_array for iOS where this type is not available
345 bool emulate_cube_array = false;
346
347 // Allow user to enable decoration binding
348 bool enable_decoration_binding = false;
Bill Hollingsbac657d2017-11-07 15:38:13 -0500349
Hans-Kristian Arntzenfc4f39b2019-04-23 12:17:21 +0200350 // Requires MSL 2.1, use the native support for texel buffers.
351 bool texture_buffer_native = false;
352
Hans-Kristian Arntzenc3bd1362020-01-16 11:07:30 +0100353 // Forces all resources which are part of an argument buffer to be considered active.
354 // This ensures ABI compatibility between shaders where some resources might be unused,
355 // and would otherwise declare a different IAB.
356 bool force_active_argument_buffer_resources = false;
357
Bill Hollings17dab612021-04-13 19:01:20 -0400358 // Aligns each resource in an argument buffer to its assigned index value, id(N),
359 // by adding synthetic padding members in the argument buffer struct for any resources
360 // in the argument buffer that are not defined and used by the shader. This allows
361 // the shader to index into the correct argument in a descriptor set argument buffer
362 // that is shared across shaders, where not all resources in the argument buffer are
363 // defined in each shader. For this to work, an MSLResourceBinding must be provided for
364 // all descriptors in any descriptor set held in an argument buffer in the shader, and
365 // that MSLResourceBinding must have the basetype and count members populated correctly.
366 // The implementation here assumes any inline blocks in the argument buffer is provided
367 // in a Metal buffer, and doesn't take into consideration inline blocks that are
368 // optionally embedded directly into the argument buffer via add_inline_uniform_block().
369 bool pad_argument_buffer_resources = false;
370
Hans-Kristian Arntzenc9d4f9c2020-02-24 12:47:14 +0100371 // Forces the use of plain arrays, which works around certain driver bugs on certain versions
372 // of Intel Macbooks. See https://github.com/KhronosGroup/SPIRV-Cross/issues/1210.
373 // May reduce performance in scenarios where arrays are copied around as value-types.
374 bool force_native_arrays = false;
375
Hans-Kristian Arntzenebf46362020-04-20 09:48:20 +0200376 // If a shader writes clip distance, also emit user varyings which
377 // can be read in subsequent stages.
378 bool enable_clip_distance_user_varying = true;
379
Chip Davis688c5fc2020-02-20 21:38:28 -0600380 // In a tessellation control shader, assume that more than one patch can be processed in a
381 // single workgroup. This requires changes to the way the InvocationId and PrimitiveId
382 // builtins are processed, but should result in more efficient usage of the GPU.
383 bool multi_patch_workgroup = false;
384
385 // If set, a vertex shader will be compiled as part of a tessellation pipeline.
386 // It will be translated as a compute kernel, so it can use the global invocation ID
387 // to index the output buffer.
388 bool vertex_for_tessellation = false;
389
Chip Davis4cf840e2020-08-27 19:24:20 -0500390 // Assume that SubpassData images have multiple layers. Layered input attachments
391 // are addressed relative to the Layer output from the vertex pipeline. This option
392 // has no effect with multiview, since all input attachments are assumed to be layered
393 // and will be addressed using the current ViewIndex.
394 bool arrayed_subpass_input = false;
395
Chip Davis68908352020-11-18 23:16:46 -0600396 // Whether to use SIMD-group or quadgroup functions to implement group nnon-uniform
397 // operations. Some GPUs on iOS do not support the SIMD-group functions, only the
398 // quadgroup functions.
399 bool ios_use_simdgroup_functions = false;
400
401 // If set, the subgroup size will be assumed to be one, and subgroup-related
402 // builtins and operations will be emitted accordingly. This mode is intended to
403 // be used by MoltenVK on hardware/software configurations which do not provide
404 // sufficient support for subgroups.
405 bool emulate_subgroups = false;
406
407 // If nonzero, a fixed subgroup size to assume. Metal, similarly to VK_EXT_subgroup_size_control,
408 // allows the SIMD-group size (aka thread execution width) to vary depending on
409 // register usage and requirements. In certain circumstances--for example, a pipeline
410 // in MoltenVK without VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT--
411 // this is undesirable. This fixes the value of the SubgroupSize builtin, instead of
412 // mapping it to the Metal builtin [[thread_execution_width]]. If the thread
413 // execution width is reduced, the extra invocations will appear to be inactive.
414 // If zero, the SubgroupSize will be allowed to vary, and the builtin will be mapped
415 // to the Metal [[thread_execution_width]] builtin.
416 uint32_t fixed_subgroup_size = 0;
417
Chip Davis688c5fc2020-02-20 21:38:28 -0600418 enum class IndexType
419 {
420 None = 0,
421 UInt16 = 1,
422 UInt32 = 2
423 };
424
425 // The type of index in the index buffer, if present. For a compute shader, Metal
426 // requires specifying the indexing at pipeline creation, rather than at draw time
427 // as with graphics pipelines. This means we must create three different pipelines,
428 // for no indexing, 16-bit indices, and 32-bit indices. Each requires different
429 // handling for the gl_VertexIndex builtin. We may as well, then, create three
430 // different shaders for these three scenarios.
431 IndexType vertex_index_type = IndexType::None;
432
Chip Davisfd738e32020-11-20 15:41:46 -0600433 // If set, a dummy [[sample_id]] input is added to a fragment shader if none is present.
434 // This will force the shader to run at sample rate, assuming Metal does not optimize
435 // the extra threads away.
436 bool force_sample_rate_shading = false;
437
Hans-Kristian Arntzen6ef47d62020-04-27 11:23:24 +0200438 bool is_ios() const
Bill Hollings3fcdce02017-12-26 13:39:07 -0500439 {
440 return platform == iOS;
441 }
Bill Hollings5ee6b462018-01-05 23:22:36 -0500442
Hans-Kristian Arntzen6ef47d62020-04-27 11:23:24 +0200443 bool is_macos() const
Bill Hollings3fcdce02017-12-26 13:39:07 -0500444 {
445 return platform == macOS;
446 }
447
Bill Hollingsbac657d2017-11-07 15:38:13 -0500448 void set_msl_version(uint32_t major, uint32_t minor = 0, uint32_t patch = 0)
449 {
Bill Hollings10148472017-11-10 16:40:33 -0500450 msl_version = make_msl_version(major, minor, patch);
Bill Hollingsbac657d2017-11-07 15:38:13 -0500451 }
452
Chip Davisfb5ee4c2019-07-22 13:08:04 -0500453 bool supports_msl_version(uint32_t major, uint32_t minor = 0, uint32_t patch = 0) const
Bill Hollingsbac657d2017-11-07 15:38:13 -0500454 {
Bill Hollings10148472017-11-10 16:40:33 -0500455 return msl_version >= make_msl_version(major, minor, patch);
456 }
457
458 static uint32_t make_msl_version(uint32_t major, uint32_t minor = 0, uint32_t patch = 0)
459 {
460 return (major * 10000) + (minor * 100) + patch;
Bill Hollingsbac657d2017-11-07 15:38:13 -0500461 }
Bill Hollings5550c872017-03-12 17:42:51 -0400462 };
Bill Hollings103aabf2016-04-06 17:42:27 -0400463
Hans-Kristian Arntzena803e5a2018-03-09 15:25:25 +0100464 const Options &get_msl_options() const
465 {
466 return msl_options;
467 }
468
Hans-Kristian Arntzena803e5a2018-03-09 15:25:25 +0100469 void set_msl_options(const Options &opts)
470 {
471 msl_options = opts;
Bill Hollings5550c872017-03-12 17:42:51 -0400472 }
473
Bill Hollings0d6202e2018-07-26 16:40:32 -0400474 // Provide feedback to calling API to allow runtime to disable pipeline
475 // rasterization if vertex shader requires rasterization to be disabled.
476 bool get_is_rasterization_disabled() const
477 {
Chip Daviseb89c3a2019-02-03 23:58:46 -0600478 return is_rasterization_disabled && (get_entry_point().model == spv::ExecutionModelVertex ||
Chip Davis68b09f22019-02-19 16:44:57 -0600479 get_entry_point().model == spv::ExecutionModelTessellationControl ||
480 get_entry_point().model == spv::ExecutionModelTessellationEvaluation);
Bill Hollings0d6202e2018-07-26 16:40:32 -0400481 }
482
Chip Davis7107f402018-09-24 13:38:27 -0500483 // Provide feedback to calling API to allow it to pass an auxiliary
Hans-Kristian Arntzeneaf7afe2019-05-09 12:15:45 +0200484 // swizzle buffer if the shader needs it.
485 bool needs_swizzle_buffer() const
Chip Davis7107f402018-09-24 13:38:27 -0500486 {
Hans-Kristian Arntzeneaf7afe2019-05-09 12:15:45 +0200487 return used_swizzle_buffer;
Chip Davis7107f402018-09-24 13:38:27 -0500488 }
489
Hans-Kristian Arntzen7b9e0fb2019-05-27 11:59:29 +0200490 // Provide feedback to calling API to allow it to pass a buffer
491 // containing STORAGE_BUFFER buffer sizes to support OpArrayLength.
492 bool needs_buffer_size_buffer() const
493 {
494 return !buffers_requiring_array_length.empty();
495 }
496
Chip Davis7eecf5a2019-05-31 12:06:20 -0500497 // Provide feedback to calling API to allow it to pass a buffer
498 // containing the view mask for the current multiview subpass.
499 bool needs_view_mask_buffer() const
500 {
Chip Davis6a585542019-07-12 21:50:50 -0500501 return msl_options.multiview && !msl_options.view_index_from_device_index;
Chip Davis7eecf5a2019-05-31 12:06:20 -0500502 }
503
Chip Davisfb5ee4c2019-07-22 13:08:04 -0500504 // Provide feedback to calling API to allow it to pass a buffer
505 // containing the dispatch base workgroup ID.
506 bool needs_dispatch_base_buffer() const
507 {
508 return msl_options.dispatch_base && !msl_options.supports_msl_version(1, 2);
509 }
510
Chip Davisae87c412019-02-06 17:22:12 -0600511 // Provide feedback to calling API to allow it to pass an output
512 // buffer if the shader needs it.
513 bool needs_output_buffer() const
514 {
Hans-Kristian Arntzen333980a2019-09-05 12:43:40 +0200515 return capture_output_to_buffer && stage_out_var_id != ID(0);
Chip Davisae87c412019-02-06 17:22:12 -0600516 }
517
Chip Daviseb89c3a2019-02-03 23:58:46 -0600518 // Provide feedback to calling API to allow it to pass a patch output
519 // buffer if the shader needs it.
520 bool needs_patch_output_buffer() const
521 {
Hans-Kristian Arntzen333980a2019-09-05 12:43:40 +0200522 return capture_output_to_buffer && patch_stage_out_var_id != ID(0);
Chip Daviseb89c3a2019-02-03 23:58:46 -0600523 }
524
525 // Provide feedback to calling API to allow it to pass an input threadgroup
526 // buffer if the shader needs it.
527 bool needs_input_threadgroup_mem() const
528 {
Hans-Kristian Arntzen333980a2019-09-05 12:43:40 +0200529 return capture_output_to_buffer && stage_in_var_id != ID(0);
Chip Daviseb89c3a2019-02-03 23:58:46 -0600530 }
531
Hans-Kristian Arntzen3fe57d32019-04-09 12:46:23 +0200532 explicit CompilerMSL(std::vector<uint32_t> spirv);
Hans-Kristian Arntzen9bbdccd2019-02-12 11:11:29 +0100533 CompilerMSL(const uint32_t *ir, size_t word_count);
534 explicit CompilerMSL(const ParsedIR &ir);
535 explicit CompilerMSL(ParsedIR &&ir);
536
Chip Davis5281d992020-06-13 23:03:30 -0500537 // input is a shader input description used to fix up shader input variables.
538 // If shader inputs are provided, is_msl_shader_input_used() will return true after
539 // calling ::compile() if the location was used by the MSL code.
Chip Davis688c5fc2020-02-20 21:38:28 -0600540 void add_msl_shader_input(const MSLShaderInput &input);
Chip Davis5281d992020-06-13 23:03:30 -0500541
Hans-Kristian Arntzen9bbdccd2019-02-12 11:11:29 +0100542 // resource is a resource binding to indicate the MSL buffer,
543 // texture or sampler index to use for a particular SPIR-V description set
544 // and binding. If resource bindings are provided,
545 // is_msl_resource_binding_used() will return true after calling ::compile() if
546 // the set/binding combination was used by the MSL code.
547 void add_msl_resource_binding(const MSLResourceBinding &resource);
548
Chip Daviscb359342019-09-05 23:14:12 -0500549 // desc_set and binding are the SPIR-V descriptor set and binding of a buffer resource
550 // in this shader. index is the index within the dynamic offset buffer to use. This
551 // function marks that resource as using a dynamic offset (VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC
552 // or VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC). This function only has any effect if argument buffers
553 // are enabled. If so, the buffer will have its address adjusted at the beginning of the shader with
554 // an offset taken from the dynamic offset buffer.
555 void add_dynamic_buffer(uint32_t desc_set, uint32_t binding, uint32_t index);
556
Chip Davisfedbc352019-12-16 22:58:16 -0600557 // desc_set and binding are the SPIR-V descriptor set and binding of a buffer resource
558 // in this shader. This function marks that resource as an inline uniform block
559 // (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT). This function only has any effect if argument buffers
560 // are enabled. If so, the buffer block will be directly embedded into the argument
561 // buffer, instead of being referenced indirectly via pointer.
562 void add_inline_uniform_block(uint32_t desc_set, uint32_t binding);
563
Hans-Kristian Arntzenb3380ec2019-03-15 14:07:03 +0100564 // When using MSL argument buffers, we can force "classic" MSL 1.0 binding schemes for certain descriptor sets.
565 // This corresponds to VK_KHR_push_descriptor in Vulkan.
Hans-Kristian Arntzene2aadf82019-03-15 21:53:21 +0100566 void add_discrete_descriptor_set(uint32_t desc_set);
Hans-Kristian Arntzenb3380ec2019-03-15 14:07:03 +0100567
Hans-Kristian Arntzen4bb673a2019-10-14 12:51:48 +0200568 // If an argument buffer is large enough, it may need to be in the device storage space rather than
569 // constant. Opt-in to this behavior here on a per set basis.
570 void set_argument_buffer_device_address_space(uint32_t desc_set, bool device_storage);
571
Chip Davis5281d992020-06-13 23:03:30 -0500572 // Query after compilation is done. This allows you to check if an input location was used by the shader.
573 bool is_msl_shader_input_used(uint32_t location);
574
Hans-Kristian Arntzence552f42021-02-17 12:21:21 +0100575 // If not using add_msl_shader_input, it's possible
576 // that certain builtin attributes need to be automatically assigned locations.
577 // This is typical for tessellation builtin inputs such as tess levels, gl_Position, etc.
578 // This returns k_unknown_location if the location was explicitly assigned with
579 // add_msl_shader_input or the builtin is not used, otherwise returns N in [[attribute(N)]].
580 uint32_t get_automatic_builtin_input_location(spv::BuiltIn builtin) const;
581
Hans-Kristian Arntzen30bb1972019-06-10 15:41:36 +0200582 // NOTE: Only resources which are remapped using add_msl_resource_binding will be reported here.
583 // Constexpr samplers are always assumed to be emitted.
584 // No specific MSLResourceBinding remapping is required for constexpr samplers as long as they are remapped
585 // by remap_constexpr_sampler(_by_binding).
Hans-Kristian Arntzencc153f82020-01-09 11:18:14 +0100586 bool is_msl_resource_binding_used(spv::ExecutionModel model, uint32_t set, uint32_t binding) const;
Hans-Kristian Arntzen9bbdccd2019-02-12 11:11:29 +0100587
Hans-Kristian Arntzen3a4a9ac2019-06-21 13:19:59 +0200588 // This must only be called after a successful call to CompilerMSL::compile().
589 // For a variable resource ID obtained through reflection API, report the automatically assigned resource index.
590 // If the descriptor set was part of an argument buffer, report the [[id(N)]],
591 // or [[buffer/texture/sampler]] binding for other resources.
592 // If the resource was a combined image sampler, report the image binding here,
593 // use the _secondary version of this call to query the sampler half of the resource.
594 // If no binding exists, uint32_t(-1) is returned.
595 uint32_t get_automatic_msl_resource_binding(uint32_t id) const;
596
597 // Same as get_automatic_msl_resource_binding, but should only be used for combined image samplers, in which case the
598 // sampler's binding is returned instead. For any other resource type, -1 is returned.
Hans-Kristian Arntzen6f1f6772021-02-17 10:42:58 +0100599 // Secondary bindings are also used for the auxillary image atomic buffer.
Hans-Kristian Arntzen3a4a9ac2019-06-21 13:19:59 +0200600 uint32_t get_automatic_msl_resource_binding_secondary(uint32_t id) const;
601
Chip Davis39dce882019-08-02 15:11:19 -0500602 // Same as get_automatic_msl_resource_binding, but should only be used for combined image samplers for multiplanar images,
603 // in which case the second plane's binding is returned instead. For any other resource type, -1 is returned.
604 uint32_t get_automatic_msl_resource_binding_tertiary(uint32_t id) const;
605
606 // Same as get_automatic_msl_resource_binding, but should only be used for combined image samplers for triplanar images,
607 // in which case the third plane's binding is returned instead. For any other resource type, -1 is returned.
608 uint32_t get_automatic_msl_resource_binding_quaternary(uint32_t id) const;
609
Hans-Kristian Arntzen9bbdccd2019-02-12 11:11:29 +0100610 // Compiles the SPIR-V code into Metal Shading Language.
611 std::string compile() override;
612
613 // Remap a sampler with ID to a constexpr sampler.
614 // Older iOS targets must use constexpr samplers in certain cases (PCF),
615 // so a static sampler must be used.
616 // The sampler will not consume a binding, but be declared in the entry point as a constexpr sampler.
617 // This can be used on both combined image/samplers (sampler2D) or standalone samplers.
618 // The remapped sampler must not be an array of samplers.
Hans-Kristian Arntzen30bb1972019-06-10 15:41:36 +0200619 // Prefer remap_constexpr_sampler_by_binding unless you're also doing reflection anyways.
Hans-Kristian Arntzen333980a2019-09-05 12:43:40 +0200620 void remap_constexpr_sampler(VariableID id, const MSLConstexprSampler &sampler);
Hans-Kristian Arntzen9bbdccd2019-02-12 11:11:29 +0100621
Hans-Kristian Arntzen30bb1972019-06-10 15:41:36 +0200622 // Same as remap_constexpr_sampler, except you provide set/binding, rather than variable ID.
623 // Remaps based on ID take priority over set/binding remaps.
624 void remap_constexpr_sampler_by_binding(uint32_t desc_set, uint32_t binding, const MSLConstexprSampler &sampler);
625
Hans-Kristian Arntzen9bbdccd2019-02-12 11:11:29 +0100626 // If using CompilerMSL::Options::pad_fragment_output_components, override the number of components we expect
627 // to use for a particular location. The default is 4 if number of components is not overridden.
628 void set_fragment_output_components(uint32_t location, uint32_t components);
629
Hans-Kristian Arntzenbd1ee432020-10-14 14:52:18 +0200630 void set_combined_sampler_suffix(const char *suffix);
631 const char *get_combined_sampler_suffix() const;
632
Hans-Kristian Arntzen9bbdccd2019-02-12 11:11:29 +0100633protected:
Bill Hollings8f6df772017-05-19 18:14:08 -0400634 // An enum of SPIR-V functions that are implemented in additional
635 // source code that is added to the shader if necessary.
636 enum SPVFuncImpl
637 {
638 SPVFuncImplNone,
639 SPVFuncImplMod,
640 SPVFuncImplRadians,
641 SPVFuncImplDegrees,
642 SPVFuncImplFindILsb,
643 SPVFuncImplFindSMsb,
644 SPVFuncImplFindUMsb,
Connor McLaughlin1dd676c2018-11-07 22:24:21 +1000645 SPVFuncImplSSign,
Hans-Kristian Arntzen38d19822018-09-11 12:58:03 +0200646 SPVFuncImplArrayCopyMultidimBase,
647 // Unfortunately, we cannot use recursive templates in the MSL compiler properly,
648 // so stamp out variants up to some arbitrary maximum.
649 SPVFuncImplArrayCopy = SPVFuncImplArrayCopyMultidimBase + 1,
650 SPVFuncImplArrayOfArrayCopy2Dim = SPVFuncImplArrayCopyMultidimBase + 2,
651 SPVFuncImplArrayOfArrayCopy3Dim = SPVFuncImplArrayCopyMultidimBase + 3,
652 SPVFuncImplArrayOfArrayCopy4Dim = SPVFuncImplArrayCopyMultidimBase + 4,
653 SPVFuncImplArrayOfArrayCopy5Dim = SPVFuncImplArrayCopyMultidimBase + 5,
654 SPVFuncImplArrayOfArrayCopy6Dim = SPVFuncImplArrayCopyMultidimBase + 6,
Bill Hollings4c5142b2018-06-26 17:30:21 -0400655 SPVFuncImplTexelBufferCoords,
Lukas Hermanns50ac6862019-09-18 14:03:54 -0400656 SPVFuncImplImage2DAtomicCoords, // Emulate texture2D atomic operations
Lukas Hermanns51be6012019-09-17 15:10:39 -0400657 SPVFuncImplFMul,
658 SPVFuncImplFAdd,
Hans-Kristian Arntzene47a30e2021-05-07 12:28:08 +0200659 SPVFuncImplFSub,
Bill Hollings57420472021-09-23 16:26:02 -0400660 SPVFuncImplQuantizeToF16,
Lukas Hermanns51be6012019-09-17 15:10:39 -0400661 SPVFuncImplCubemapTo2DArrayFace,
Lukas Hermanns50ac6862019-09-18 14:03:54 -0400662 SPVFuncImplUnsafeArray, // Allow Metal to use the array<T> template to make arrays a value type
Bill Hollings8f6df772017-05-19 18:14:08 -0400663 SPVFuncImplInverse4x4,
Hans-Kristian Arntzen6a12ff72018-02-23 16:48:16 +0100664 SPVFuncImplInverse3x3,
665 SPVFuncImplInverse2x2,
Chip Davis39dce882019-08-02 15:11:19 -0500666 // It is very important that this come before *Swizzle and ChromaReconstruct*, to ensure it's
667 // emitted before them.
668 SPVFuncImplForwardArgs,
669 // Likewise, this must come before *Swizzle.
670 SPVFuncImplGetSwizzle,
Chip Davis25833212018-09-19 20:36:33 -0500671 SPVFuncImplTextureSwizzle,
Chip Davis39dce882019-08-02 15:11:19 -0500672 SPVFuncImplGatherSwizzle,
673 SPVFuncImplGatherCompareSwizzle,
Chip Davis1264e272020-10-21 01:51:48 -0500674 SPVFuncImplSubgroupBroadcast,
675 SPVFuncImplSubgroupBroadcastFirst,
Chip Davis9d941572019-05-15 16:03:30 -0500676 SPVFuncImplSubgroupBallot,
677 SPVFuncImplSubgroupBallotBitExtract,
678 SPVFuncImplSubgroupBallotFindLSB,
679 SPVFuncImplSubgroupBallotFindMSB,
680 SPVFuncImplSubgroupBallotBitCount,
681 SPVFuncImplSubgroupAllEqual,
Chip Davis1264e272020-10-21 01:51:48 -0500682 SPVFuncImplSubgroupShuffle,
683 SPVFuncImplSubgroupShuffleXor,
684 SPVFuncImplSubgroupShuffleUp,
685 SPVFuncImplSubgroupShuffleDown,
686 SPVFuncImplQuadBroadcast,
687 SPVFuncImplQuadSwap,
Hans-Kristian Arntzen041f1032019-07-03 12:24:58 +0200688 SPVFuncImplReflectScalar,
689 SPVFuncImplRefractScalar,
Hans-Kristian Arntzenc7eda1b2019-07-17 11:24:31 +0200690 SPVFuncImplFaceForwardScalar,
Chip Davis39dce882019-08-02 15:11:19 -0500691 SPVFuncImplChromaReconstructNearest2Plane,
692 SPVFuncImplChromaReconstructNearest3Plane,
693 SPVFuncImplChromaReconstructLinear422CositedEven2Plane,
694 SPVFuncImplChromaReconstructLinear422CositedEven3Plane,
695 SPVFuncImplChromaReconstructLinear422Midpoint2Plane,
696 SPVFuncImplChromaReconstructLinear422Midpoint3Plane,
697 SPVFuncImplChromaReconstructLinear420XCositedEvenYCositedEven2Plane,
698 SPVFuncImplChromaReconstructLinear420XCositedEvenYCositedEven3Plane,
699 SPVFuncImplChromaReconstructLinear420XMidpointYCositedEven2Plane,
700 SPVFuncImplChromaReconstructLinear420XMidpointYCositedEven3Plane,
701 SPVFuncImplChromaReconstructLinear420XCositedEvenYMidpoint2Plane,
702 SPVFuncImplChromaReconstructLinear420XCositedEvenYMidpoint3Plane,
703 SPVFuncImplChromaReconstructLinear420XMidpointYMidpoint2Plane,
704 SPVFuncImplChromaReconstructLinear420XMidpointYMidpoint3Plane,
705 SPVFuncImplExpandITUFullRange,
706 SPVFuncImplExpandITUNarrowRange,
707 SPVFuncImplConvertYCbCrBT709,
708 SPVFuncImplConvertYCbCrBT601,
709 SPVFuncImplConvertYCbCrBT2020,
710 SPVFuncImplDynamicImageSampler,
Bill Hollings8f6df772017-05-19 18:14:08 -0400711 };
712
Lukas Hermanns7ad0a842019-09-23 18:05:04 -0400713 // If the underlying resource has been used for comparison then duplicate loads of that resource must be too
714 // Use Metal's native frame-buffer fetch API for subpass inputs.
Hans-Kristian Arntzen275974e2020-06-04 15:50:28 +0200715 void emit_texture_op(const Instruction &i, bool sparse) override;
Chip Davisd3233692018-08-31 13:46:02 -0500716 void emit_binary_unord_op(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, const char *op);
Bill Hollingsf5f91042016-10-27 18:47:17 -0400717 void emit_instruction(const Instruction &instr) override;
Hans-Kristian Arntzen67aad482016-11-12 10:04:50 +0100718 void emit_glsl_op(uint32_t result_type, uint32_t result_id, uint32_t op, const uint32_t *args,
719 uint32_t count) override;
Chip Davisca91fcf2019-07-11 11:49:34 -0500720 void emit_spv_amd_shader_trinary_minmax_op(uint32_t result_type, uint32_t result_id, uint32_t op,
721 const uint32_t *args, uint32_t count) override;
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200722 void emit_header() override;
Hans-Kristian Arntzene8e58842018-03-12 13:09:25 +0100723 void emit_function_prototype(SPIRFunction &func, const Bitset &return_flags) override;
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200724 void emit_sampled_image_op(uint32_t result_type, uint32_t result_id, uint32_t image_id, uint32_t samp_id) override;
Chip Davis9d941572019-05-15 16:03:30 -0500725 void emit_subgroup_op(const Instruction &i) override;
Hans-Kristian Arntzen275974e2020-06-04 15:50:28 +0200726 std::string to_texture_op(const Instruction &i, bool sparse, bool *forward,
Chip Davis39dce882019-08-02 15:11:19 -0500727 SmallVector<uint32_t> &inherited_expressions) override;
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200728 void emit_fixup() override;
Chip Davisc51e5b72019-01-08 16:33:32 -0600729 std::string to_struct_member(const SPIRType &type, uint32_t member_type_id, uint32_t index,
730 const std::string &qualifier = "");
Bill Hollingsdc694272017-03-11 12:17:22 -0500731 void emit_struct_member(const SPIRType &type, uint32_t member_type_id, uint32_t index,
msiglreithd096f5c2017-11-27 16:00:56 +0100732 const std::string &qualifier = "", uint32_t base_offset = 0) override;
Hans-Kristian Arntzenbe2fccd2019-07-22 10:23:39 +0200733 void emit_struct_padding_target(const SPIRType &type) override;
Bill Hollingsb41e1482017-05-29 20:45:05 -0400734 std::string type_to_glsl(const SPIRType &type, uint32_t id = 0) override;
Hans-Kristian Arntzend62b3c22021-06-03 12:00:29 +0200735 void emit_block_hints(const SPIRBlock &block) override;
Lukas Hermannsf3a6d282019-09-27 15:49:54 -0400736
737 // Allow Metal to use the array<T> template to make arrays a value type
738 std::string type_to_array_glsl(const SPIRType &type) override;
Bill Hollings5fb1ca42021-09-03 18:20:49 -0400739 std::string constant_op_expression(const SPIRConstantOp &cop) override;
Lukas Hermannsf3a6d282019-09-27 15:49:54 -0400740
741 // Threadgroup arrays can't have a wrapper type
742 std::string variable_decl(const SPIRVariable &variable) override;
743
Hans-Kristian Arntzenae7bb412021-04-06 15:50:02 +0200744 bool variable_decl_is_remapped_storage(const SPIRVariable &variable, spv::StorageClass storage) const override;
Hans-Kristian Arntzenf2b5fb32021-03-26 17:23:44 +0100745
Lukas Hermannsf3a6d282019-09-27 15:49:54 -0400746 // GCC workaround of lambdas calling protected functions (for older GCC versions)
747 std::string variable_decl(const SPIRType &type, const std::string &name, uint32_t id = 0) override;
748
Bill Hollingsb41e1482017-05-29 20:45:05 -0400749 std::string image_type_glsl(const SPIRType &type, uint32_t id = 0) override;
Bill Hollingsb7b0e802020-10-29 18:50:42 -0400750 std::string sampler_type(const SPIRType &type, uint32_t id);
Hans-Kristian Arntzenc8d60912017-07-24 10:07:02 +0200751 std::string builtin_to_glsl(spv::BuiltIn builtin, spv::StorageClass storage) override;
Chip Davis39dce882019-08-02 15:11:19 -0500752 std::string to_func_call_arg(const SPIRFunction::Parameter &arg, uint32_t id) override;
Hans-Kristian Arntzen61c31c62017-03-07 13:27:04 +0100753 std::string to_name(uint32_t id, bool allow_alias = true) const override;
Hans-Kristian Arntzencbe0cca2020-06-05 15:49:17 +0200754 std::string to_function_name(const TextureFunctionNameArguments &args) override;
755 std::string to_function_args(const TextureFunctionArguments &args, bool *p_forward) override;
Hans-Kristian Arntzen2bf57d62018-07-05 15:29:49 +0200756 std::string to_initializer_expression(const SPIRVariable &var) override;
Hans-Kristian Arntzenb8905bb2020-03-26 11:21:23 +0100757 std::string to_zero_initialized_expression(uint32_t type_id) override;
Lukas Hermanns7ad0a842019-09-23 18:05:04 -0400758
Hans-Kristian Arntzen3fa2b142019-07-23 12:23:41 +0200759 std::string unpack_expression_type(std::string expr_str, const SPIRType &type, uint32_t physical_type_id,
760 bool is_packed, bool row_major) override;
Hans-Kristian Arntzen14afb962019-07-22 12:03:12 +0200761
Lukas Hermanns6673a672019-10-22 11:06:16 -0400762 // Returns true for BuiltInSampleMask because gl_SampleMask[] is an array in SPIR-V, but [[sample_mask]] is a scalar in Metal.
763 bool builtin_translates_to_nonarray(spv::BuiltIn builtin) const override;
764
Bill Hollings8f6df772017-05-19 18:14:08 -0400765 std::string bitcast_glsl_op(const SPIRType &result_type, const SPIRType &argument_type) override;
Hans-Kristian Arntzen5e5d1c22020-04-21 23:27:33 +0200766 bool emit_complex_bitcast(uint32_t result_id, uint32_t id, uint32_t op0) override;
Bill Hollingsb41e1482017-05-29 20:45:05 -0400767 bool skip_argument(uint32_t id) const override;
Chip Davis3bfb2f92018-12-03 02:06:33 -0600768 std::string to_member_reference(uint32_t base, const SPIRType &type, uint32_t index, bool ptr_chain) override;
Bill Hollings1c180782017-11-05 21:34:42 -0500769 std::string to_qualifiers_glsl(uint32_t id) override;
770 void replace_illegal_names() override;
Bill Hollingse83e2b22017-11-15 22:44:42 -0500771 void declare_undefined_values() override;
Hans-Kristian Arntzen1a9c9602018-02-08 13:06:29 +0100772 void declare_constant_arrays();
Lukas Hermanns7ad0a842019-09-23 18:05:04 -0400773
Hans-Kristian Arntzenc4ff1292021-01-04 09:40:11 +0100774 void replace_illegal_entry_point_names();
775 void sync_entry_point_aliases_and_names();
776
777 static const std::unordered_set<std::string> &get_reserved_keyword_set();
778 static const std::unordered_set<std::string> &get_illegal_func_names();
779
Lukas Hermanns50ac6862019-09-18 14:03:54 -0400780 // Constant arrays of non-primitive types (i.e. matrices) won't link properly into Metal libraries
Mark Satterthwaite8596bf52019-08-13 18:20:02 -0400781 void declare_complex_constant_arrays();
Lukas Hermanns7ad0a842019-09-23 18:05:04 -0400782
Chip Davis6b798802019-02-15 17:21:38 -0600783 bool is_patch_block(const SPIRType &type);
Bill Hollings88905782018-01-04 16:33:45 -0500784 bool is_non_native_row_major_matrix(uint32_t id) override;
785 bool member_is_non_native_row_major_matrix(const SPIRType &type, uint32_t index) override;
Hans-Kristian Arntzen3fa2b142019-07-23 12:23:41 +0200786 std::string convert_row_major_matrix(std::string exp_str, const SPIRType &exp_type, uint32_t physical_type_id,
787 bool is_packed) override;
Bill Hollings103aabf2016-04-06 17:42:27 -0400788
Bill Hollings4c198bb2017-01-20 11:24:44 -0500789 void preprocess_op_codes();
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200790 void localize_global_variables();
Bill Hollingsac00c602016-10-24 09:24:24 -0400791 void extract_global_variables_from_functions();
Bill Hollings1c180782017-11-05 21:34:42 -0500792 void mark_packable_structs();
793 void mark_as_packable(SPIRType &type);
Robert Konrada778c362017-01-15 16:39:03 +0100794
Bill Hollingse4f0dde2017-01-31 11:02:44 -0500795 std::unordered_map<uint32_t, std::set<uint32_t>> function_global_vars;
796 void extract_global_variables_from_function(uint32_t func_id, std::set<uint32_t> &added_arg_ids,
Bill Hollings32ae2ec2016-12-18 18:48:15 -0500797 std::unordered_set<uint32_t> &global_var_ids,
798 std::unordered_set<uint32_t> &processed_func_ids);
Chip Daviseb89c3a2019-02-03 23:58:46 -0600799 uint32_t add_interface_block(spv::StorageClass storage, bool patch = false);
800 uint32_t add_interface_block_pointer(uint32_t ib_var_id, spv::StorageClass storage);
Hans-Kristian Arntzen53457562019-01-08 11:03:59 +0100801
Hans-Kristian Arntzen93f32652020-01-07 14:05:55 +0100802 struct InterfaceBlockMeta
803 {
804 struct LocationMeta
805 {
Hans-Kristian Arntzen99ae0d32021-05-21 13:03:05 +0200806 uint32_t base_type_id = 0;
Hans-Kristian Arntzen93f32652020-01-07 14:05:55 +0100807 uint32_t num_components = 0;
Hans-Kristian Arntzen99ae0d32021-05-21 13:03:05 +0200808 bool flat = false;
809 bool noperspective = false;
810 bool centroid = false;
811 bool sample = false;
Hans-Kristian Arntzen93f32652020-01-07 14:05:55 +0100812 };
813 std::unordered_map<uint32_t, LocationMeta> location_meta;
814 bool strip_array = false;
Hans-Kristian Arntzen425e9682021-04-07 17:02:30 +0200815 bool allow_local_declaration = false;
Hans-Kristian Arntzen93f32652020-01-07 14:05:55 +0100816 };
817
Hans-Kristian Arntzen7b9a5912021-04-16 11:26:47 +0200818 std::string to_tesc_invocation_id();
Hans-Kristian Arntzen23da4452021-04-14 13:13:13 +0200819 void emit_local_masked_variable(const SPIRVariable &masked_var, bool strip_array);
Hans-Kristian Arntzen53457562019-01-08 11:03:59 +0100820 void add_variable_to_interface_block(spv::StorageClass storage, const std::string &ib_var_ref, SPIRType &ib_type,
Hans-Kristian Arntzen93f32652020-01-07 14:05:55 +0100821 SPIRVariable &var, InterfaceBlockMeta &meta);
Hans-Kristian Arntzen53457562019-01-08 11:03:59 +0100822 void add_composite_variable_to_interface_block(spv::StorageClass storage, const std::string &ib_var_ref,
Hans-Kristian Arntzen93f32652020-01-07 14:05:55 +0100823 SPIRType &ib_type, SPIRVariable &var, InterfaceBlockMeta &meta);
Hans-Kristian Arntzen53457562019-01-08 11:03:59 +0100824 void add_plain_variable_to_interface_block(spv::StorageClass storage, const std::string &ib_var_ref,
Hans-Kristian Arntzen93f32652020-01-07 14:05:55 +0100825 SPIRType &ib_type, SPIRVariable &var, InterfaceBlockMeta &meta);
Hans-Kristian Arntzen99ae0d32021-05-21 13:03:05 +0200826 bool add_component_variable_to_interface_block(spv::StorageClass storage, const std::string &ib_var_ref,
827 SPIRVariable &var, const SPIRType &type,
828 InterfaceBlockMeta &meta);
Hans-Kristian Arntzen53457562019-01-08 11:03:59 +0100829 void add_plain_member_variable_to_interface_block(spv::StorageClass storage, const std::string &ib_var_ref,
Chip Daviseb89c3a2019-02-03 23:58:46 -0600830 SPIRType &ib_type, SPIRVariable &var, uint32_t index,
Hans-Kristian Arntzen93f32652020-01-07 14:05:55 +0100831 InterfaceBlockMeta &meta);
Hans-Kristian Arntzen53457562019-01-08 11:03:59 +0100832 void add_composite_member_variable_to_interface_block(spv::StorageClass storage, const std::string &ib_var_ref,
Chip Daviseb89c3a2019-02-03 23:58:46 -0600833 SPIRType &ib_type, SPIRVariable &var, uint32_t index,
Hans-Kristian Arntzen93f32652020-01-07 14:05:55 +0100834 InterfaceBlockMeta &meta);
Chip Davisf3c09422019-02-22 12:11:17 -0600835 void add_tess_level_input_to_interface_block(const std::string &ib_var_ref, SPIRType &ib_type, SPIRVariable &var);
Chip Daviseb89c3a2019-02-03 23:58:46 -0600836
837 void fix_up_interface_member_indices(spv::StorageClass storage, uint32_t ib_type_id);
Hans-Kristian Arntzen53457562019-01-08 11:03:59 +0100838
Hans-Kristian Arntzenfaf80b02021-04-09 18:55:10 +0200839 void mark_location_as_used_by_shader(uint32_t location, const SPIRType &type,
840 spv::StorageClass storage, bool fallback = false);
Bill Hollings2964e322018-02-13 14:44:40 -0500841 uint32_t ensure_correct_builtin_type(uint32_t type_id, spv::BuiltIn builtin);
Bill Hollings548a23d2021-09-20 17:57:11 -0400842 uint32_t ensure_correct_input_type(uint32_t type_id, uint32_t location, uint32_t component,
Hans-Kristian Arntzen40f628f2021-04-09 10:45:05 +0200843 uint32_t num_components, bool strip_array);
Robert Konrada778c362017-01-15 16:39:03 +0100844
Lukas Hermanns51be6012019-09-17 15:10:39 -0400845 void emit_custom_templates();
Bill Hollings1f838562017-06-15 15:24:22 -0400846 void emit_custom_functions();
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200847 void emit_resources();
Hans-Kristian Arntzend92de002019-01-10 09:49:33 +0100848 void emit_specialization_constants_and_structs();
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200849 void emit_interface_block(uint32_t ib_var_id);
Bill Hollings1c180782017-11-05 21:34:42 -0500850 bool maybe_emit_array_assignment(uint32_t id_lhs, uint32_t id_rhs);
Bill Hollings4bdd49d2020-11-02 22:15:20 -0500851 uint32_t get_resource_array_size(uint32_t id) const;
Hans-Kristian Arntzen27b75c22019-07-19 12:53:10 +0200852
Chip Davisf500d2f2019-01-16 17:52:53 -0600853 void fix_up_shader_inputs_outputs();
Bill Hollings8f30f072016-04-07 21:25:51 -0400854
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200855 std::string func_type_decl(SPIRType &type);
Hans-Kristian Arntzene47a77d2019-03-14 10:29:34 +0100856 std::string entry_point_args_classic(bool append_comma);
857 std::string entry_point_args_argument_buffer(bool append_comma);
858 std::string entry_point_arg_stage_in();
859 void entry_point_args_builtin(std::string &args);
Hans-Kristian Arntzene2aadf82019-03-15 21:53:21 +0100860 void entry_point_args_discrete_descriptors(std::string &args);
Bill Hollingsac00c602016-10-24 09:24:24 -0400861 std::string to_qualified_member_name(const SPIRType &type, uint32_t index);
Bill Hollingsc2e60132016-11-27 15:00:06 -0500862 std::string ensure_valid_name(std::string name, std::string pfx);
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200863 std::string to_sampler_expression(uint32_t id);
Chip Davis664df222019-01-13 17:31:50 -0600864 std::string to_swizzle_expression(uint32_t id);
Hans-Kristian Arntzen7b9e0fb2019-05-27 11:59:29 +0200865 std::string to_buffer_size_expression(uint32_t id);
Chip Davisfd738e32020-11-20 15:41:46 -0600866 bool is_sample_rate() const;
丛越d52ec1e2021-10-21 17:46:45 +0800867 bool is_intersection_query() const;
Chip Davis5e13f7f2020-07-22 15:25:10 -0600868 bool is_direct_input_builtin(spv::BuiltIn builtin);
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200869 std::string builtin_qualifier(spv::BuiltIn builtin);
Hans-Kristian Arntzen2e1cee52019-06-13 11:33:40 +0200870 std::string builtin_type_decl(spv::BuiltIn builtin, uint32_t id = 0);
Bill Hollings81757502017-01-29 13:28:20 -0500871 std::string built_in_func_arg(spv::BuiltIn builtin, bool prefix_comma);
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200872 std::string member_attribute_qualifier(const SPIRType &type, uint32_t index);
Bill Hollings86dfac12021-09-18 18:55:12 -0400873 std::string member_location_attribute_qualifier(const SPIRType &type, uint32_t index);
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200874 std::string argument_decl(const SPIRFunction::Parameter &arg);
Bill Hollings561dc032017-04-25 16:32:16 -0400875 std::string round_fp_tex_coords(std::string tex_coords, bool coord_is_fp);
Chip Davis39dce882019-08-02 15:11:19 -0500876 uint32_t get_metal_resource_index(SPIRVariable &var, SPIRType::BaseType basetype, uint32_t plane = 0);
Hans-Kristian Arntzence552f42021-02-17 12:21:21 +0100877 uint32_t get_member_location(uint32_t type_id, uint32_t index, uint32_t *comp = nullptr) const;
878 uint32_t get_or_allocate_builtin_input_member_location(spv::BuiltIn builtin,
879 uint32_t type_id, uint32_t index, uint32_t *comp = nullptr);
Hans-Kristian Arntzena86308b2019-07-18 13:34:47 +0200880
Hans-Kristian Arntzen85704f72021-02-17 13:18:47 +0100881 uint32_t get_physical_tess_level_array_size(spv::BuiltIn builtin) const;
882
Hans-Kristian Arntzena86308b2019-07-18 13:34:47 +0200883 // MSL packing rules. These compute the effective packing rules as observed by the MSL compiler in the MSL output.
884 // These values can change depending on various extended decorations which control packing rules.
885 // We need to make these rules match up with SPIR-V declared rules.
Hans-Kristian Arntzenb09b8d32019-07-18 16:39:25 +0200886 uint32_t get_declared_type_size_msl(const SPIRType &type, bool packed, bool row_major) const;
887 uint32_t get_declared_type_array_stride_msl(const SPIRType &type, bool packed, bool row_major) const;
888 uint32_t get_declared_type_matrix_stride_msl(const SPIRType &type, bool packed, bool row_major) const;
889 uint32_t get_declared_type_alignment_msl(const SPIRType &type, bool packed, bool row_major) const;
Hans-Kristian Arntzenc160d522019-07-18 13:48:27 +0200890
891 uint32_t get_declared_struct_member_size_msl(const SPIRType &struct_type, uint32_t index) const;
892 uint32_t get_declared_struct_member_array_stride_msl(const SPIRType &struct_type, uint32_t index) const;
893 uint32_t get_declared_struct_member_matrix_stride_msl(const SPIRType &struct_type, uint32_t index) const;
894 uint32_t get_declared_struct_member_alignment_msl(const SPIRType &struct_type, uint32_t index) const;
895
Chip Davis688c5fc2020-02-20 21:38:28 -0600896 uint32_t get_declared_input_size_msl(const SPIRType &struct_type, uint32_t index) const;
897 uint32_t get_declared_input_array_stride_msl(const SPIRType &struct_type, uint32_t index) const;
898 uint32_t get_declared_input_matrix_stride_msl(const SPIRType &struct_type, uint32_t index) const;
899 uint32_t get_declared_input_alignment_msl(const SPIRType &struct_type, uint32_t index) const;
900
Hans-Kristian Arntzenc160d522019-07-18 13:48:27 +0200901 const SPIRType &get_physical_member_type(const SPIRType &struct_type, uint32_t index) const;
Chip Davis688c5fc2020-02-20 21:38:28 -0600902 SPIRType get_presumed_input_type(const SPIRType &struct_type, uint32_t index) const;
Hans-Kristian Arntzenc160d522019-07-18 13:48:27 +0200903
Hans-Kristian Arntzen3fa2b142019-07-23 12:23:41 +0200904 uint32_t get_declared_struct_size_msl(const SPIRType &struct_type, bool ignore_alignment = false,
905 bool ignore_padding = false) const;
Hans-Kristian Arntzena86308b2019-07-18 13:34:47 +0200906
Bill Hollingsa2b8a0e2016-12-28 18:36:42 -0500907 std::string to_component_argument(uint32_t id);
Hans-Kristian Arntzena86308b2019-07-18 13:34:47 +0200908 void align_struct(SPIRType &ib_type, std::unordered_set<uint32_t> &aligned_structs);
Hans-Kristian Arntzene90d8162019-07-19 14:18:14 +0200909 void mark_scalar_layout_structs(const SPIRType &ib_type);
Hans-Kristian Arntzen5c1cb7a2019-07-23 15:24:53 +0200910 void mark_struct_members_packed(const SPIRType &type);
Hans-Kristian Arntzenb09b8d32019-07-18 16:39:25 +0200911 void ensure_member_packing_rules_msl(SPIRType &ib_type, uint32_t index);
912 bool validate_member_packing_rules_msl(const SPIRType &type, uint32_t index) const;
Bill Hollings8f6df772017-05-19 18:14:08 -0400913 std::string get_argument_address_space(const SPIRVariable &argument);
Chip Davisdf18d982019-07-26 01:06:35 -0500914 std::string get_type_address_space(const SPIRType &type, uint32_t id, bool argument = false);
Chip Davis058f1a02019-07-10 11:17:40 -0500915 const char *to_restrict(uint32_t id, bool space = true);
Chip Daviseb89c3a2019-02-03 23:58:46 -0600916 SPIRType &get_stage_in_struct_type();
Chip Davisc51e5b72019-01-08 16:33:32 -0600917 SPIRType &get_stage_out_struct_type();
Chip Davise75add42019-02-05 18:13:26 -0600918 SPIRType &get_patch_stage_in_struct_type();
Chip Daviseb89c3a2019-02-03 23:58:46 -0600919 SPIRType &get_patch_stage_out_struct_type();
920 std::string get_tess_factor_struct_name();
Chip Davis884bc6d2020-07-22 15:25:10 -0600921 SPIRType &get_uint_type();
922 uint32_t get_uint_type_id();
Hans-Kristian Arntzenfce88702022-01-17 15:29:13 +0100923 void emit_atomic_func_op(uint32_t result_type, uint32_t result_id, const char *op, spv::Op opcode,
924 uint32_t mem_order_1, uint32_t mem_order_2, bool has_mem_order_2, uint32_t op0, uint32_t op1 = 0,
Chip Davis06edf802018-09-13 08:56:23 -0500925 bool op1_is_pointer = false, bool op1_is_literal = false, uint32_t op2 = 0);
Bill Hollings8f6df772017-05-19 18:14:08 -0400926 const char *get_memory_order(uint32_t spv_mem_sem);
927 void add_pragma_line(const std::string &line);
Bill Hollings607b0d62018-02-11 16:52:57 -0500928 void add_typedef_line(const std::string &line);
Bill Hollings1c180782017-11-05 21:34:42 -0500929 void emit_barrier(uint32_t id_exe_scope, uint32_t id_mem_scope, uint32_t id_mem_sem);
Hans-Kristian Arntzenae9ca7d2021-04-19 11:46:30 +0200930 void emit_array_copy(const std::string &lhs, uint32_t lhs_id, uint32_t rhs_id,
931 spv::StorageClass lhs_storage, spv::StorageClass rhs_storage) override;
Hans-Kristian Arntzen09124272018-02-09 11:27:23 +0100932 void build_implicit_builtins();
Hans-Kristian Arntzen7b9e0fb2019-05-27 11:59:29 +0200933 uint32_t build_constant_uint_array_pointer();
Hans-Kristian Arntzendf58deb2018-04-17 17:43:10 +0200934 void emit_entry_point_declarations() override;
Bill Hollings248e9ae2021-11-12 14:17:00 -0500935 bool uses_explicit_early_fragment_test();
936
Hans-Kristian Arntzen702e0862018-02-09 12:13:33 +0100937 uint32_t builtin_frag_coord_id = 0;
Chip Davis39bc1012018-09-12 14:05:52 -0500938 uint32_t builtin_sample_id_id = 0;
Tomek Ponitka18f23c42020-07-22 18:37:17 +0200939 uint32_t builtin_sample_mask_id = 0;
Chip Davisc51e5b72019-01-08 16:33:32 -0600940 uint32_t builtin_vertex_idx_id = 0;
941 uint32_t builtin_base_vertex_id = 0;
942 uint32_t builtin_instance_idx_id = 0;
943 uint32_t builtin_base_instance_id = 0;
Chip Davis7eecf5a2019-05-31 12:06:20 -0500944 uint32_t builtin_view_idx_id = 0;
945 uint32_t builtin_layer_id = 0;
Chip Daviseb89c3a2019-02-03 23:58:46 -0600946 uint32_t builtin_invocation_id_id = 0;
947 uint32_t builtin_primitive_id_id = 0;
Chip Davis9d941572019-05-15 16:03:30 -0500948 uint32_t builtin_subgroup_invocation_id_id = 0;
949 uint32_t builtin_subgroup_size_id = 0;
Chip Davisfb5ee4c2019-07-22 13:08:04 -0500950 uint32_t builtin_dispatch_base_id = 0;
Chip Davis688c5fc2020-02-20 21:38:28 -0600951 uint32_t builtin_stage_input_size_id = 0;
Chip Davis68908352020-11-18 23:16:46 -0600952 uint32_t builtin_local_invocation_index_id = 0;
953 uint32_t builtin_workgroup_size_id = 0;
Hans-Kristian Arntzeneaf7afe2019-05-09 12:15:45 +0200954 uint32_t swizzle_buffer_id = 0;
Hans-Kristian Arntzen7b9e0fb2019-05-27 11:59:29 +0200955 uint32_t buffer_size_buffer_id = 0;
Chip Davis7eecf5a2019-05-31 12:06:20 -0500956 uint32_t view_mask_buffer_id = 0;
Chip Daviscb359342019-09-05 23:14:12 -0500957 uint32_t dynamic_offsets_buffer_id = 0;
Chip Davis884bc6d2020-07-22 15:25:10 -0600958 uint32_t uint_type_id = 0;
Bill Hollings17dab612021-04-13 19:01:20 -0400959 uint32_t argument_buffer_padding_buffer_type_id = 0;
960 uint32_t argument_buffer_padding_image_type_id = 0;
961 uint32_t argument_buffer_padding_sampler_type_id = 0;
Bill Hollings103aabf2016-04-06 17:42:27 -0400962
Tomek Ponitka18f23c42020-07-22 18:37:17 +0200963 bool does_shader_write_sample_mask = false;
964
Hans-Kristian Arntzenedf247f2021-10-25 10:55:11 +0200965 void cast_to_variable_store(uint32_t target_id, std::string &expr, const SPIRType &expr_type) override;
966 void cast_from_variable_load(uint32_t source_id, std::string &expr, const SPIRType &expr_type) override;
Hans-Kristian Arntzen73d9da72019-01-17 12:21:16 +0100967 void emit_store_statement(uint32_t lhs_expression, uint32_t rhs_expression) override;
Hans-Kristian Arntzend94d20f2018-06-22 11:30:13 +0200968
Chip Davisc11374c2018-09-24 12:10:27 -0500969 void analyze_sampled_image_usage();
Chip Davis4302c5a2018-09-22 19:36:11 -0500970
Hans-Kristian Arntzen75ed7382021-04-14 15:10:02 +0200971 bool access_chain_needs_stage_io_builtin_translation(uint32_t base) override;
Hans-Kristian Arntzenfa5b2062020-07-01 13:02:11 +0200972 void prepare_access_chain_for_scalar_access(std::string &expr, const SPIRType &type, spv::StorageClass storage,
973 bool &is_packed) override;
Chip Davisaca9b682020-11-02 20:56:46 -0600974 void fix_up_interpolant_access_chain(const uint32_t *ops, uint32_t length);
Chip Davise75add42019-02-05 18:13:26 -0600975 bool emit_tessellation_access_chain(const uint32_t *ops, uint32_t length);
Hans-Kristian Arntzen27d6d452019-10-25 16:41:02 +0200976 bool emit_tessellation_io_load(uint32_t result_type, uint32_t id, uint32_t ptr);
Chip Davis80954342019-02-20 00:33:46 -0600977 bool is_out_of_bounds_tessellation_level(uint32_t id_lhs);
Hans-Kristian Arntzen878c5022019-02-14 09:28:17 +0100978
Lukas Hermanns9f9276f2019-09-19 14:44:30 -0400979 void ensure_builtin(spv::StorageClass storage, spv::BuiltIn builtin);
Lukas Hermanns7ad0a842019-09-23 18:05:04 -0400980
Hans-Kristian Arntzen314efdc2019-05-31 13:19:33 +0200981 void mark_implicit_builtin(spv::StorageClass storage, spv::BuiltIn builtin, uint32_t id);
982
Hans-Kristian Arntzenc76b99b2019-06-27 15:04:22 +0200983 std::string convert_to_f32(const std::string &expr, uint32_t components);
984
Hans-Kristian Arntzena803e5a2018-03-09 15:25:25 +0100985 Options msl_options;
Bill Hollings8f6df772017-05-19 18:14:08 -0400986 std::set<SPVFuncImpl> spv_function_implementations;
Chip Davis688c5fc2020-02-20 21:38:28 -0600987 // Must be ordered to ensure declarations are in a specific order.
Bill Hollings548a23d2021-09-20 17:57:11 -0400988 std::map<LocationComponentPair, MSLShaderInput> inputs_by_location;
Chip Davis5281d992020-06-13 23:03:30 -0500989 std::unordered_map<uint32_t, MSLShaderInput> inputs_by_builtin;
Hans-Kristian Arntzenaa271c12021-02-17 11:29:33 +0100990 std::unordered_set<uint32_t> location_inputs_in_use;
Hans-Kristian Arntzenfaf80b02021-04-09 18:55:10 +0200991 std::unordered_set<uint32_t> location_inputs_in_use_fallback;
Hans-Kristian Arntzenb8033d72019-01-14 14:53:47 +0100992 std::unordered_map<uint32_t, uint32_t> fragment_output_components;
Hans-Kristian Arntzence552f42021-02-17 12:21:21 +0100993 std::unordered_map<uint32_t, uint32_t> builtin_to_automatic_input_location;
Bill Hollings6371d9e2018-01-06 00:51:25 -0500994 std::set<std::string> pragma_lines;
Bill Hollings607b0d62018-02-11 16:52:57 -0500995 std::set<std::string> typedef_lines;
Hans-Kristian Arntzena489ba72019-04-02 11:19:03 +0200996 SmallVector<uint32_t> vars_needing_early_declaration;
Hans-Kristian Arntzen9bbdccd2019-02-12 11:11:29 +0100997
Hans-Kristian Arntzen30bb1972019-06-10 15:41:36 +0200998 std::unordered_map<StageSetBinding, std::pair<MSLResourceBinding, bool>, InternalHasher> resource_bindings;
Bill Hollings9866cf42021-04-16 09:05:15 -0400999 std::unordered_map<StageSetBinding, uint32_t, InternalHasher> resource_arg_buff_idx_to_binding_number;
Hans-Kristian Arntzen909040e2019-07-09 15:31:01 +02001000
Hans-Kristian Arntzen9bbdccd2019-02-12 11:11:29 +01001001 uint32_t next_metal_resource_index_buffer = 0;
1002 uint32_t next_metal_resource_index_texture = 0;
1003 uint32_t next_metal_resource_index_sampler = 0;
Hans-Kristian Arntzen909040e2019-07-09 15:31:01 +02001004 // Intentionally uninitialized, works around MSVC 2013 bug.
1005 uint32_t next_metal_resource_ids[kMaxArgumentBuffers];
Hans-Kristian Arntzen9bbdccd2019-02-12 11:11:29 +01001006
Hans-Kristian Arntzen333980a2019-09-05 12:43:40 +02001007 VariableID stage_in_var_id = 0;
1008 VariableID stage_out_var_id = 0;
1009 VariableID patch_stage_in_var_id = 0;
1010 VariableID patch_stage_out_var_id = 0;
1011 VariableID stage_in_ptr_var_id = 0;
1012 VariableID stage_out_ptr_var_id = 0;
Hans-Kristian Arntzen5e9c2d02021-04-09 14:59:45 +02001013 VariableID stage_out_masked_builtin_type_id = 0;
Hans-Kristian Arntzen4ac12592019-10-24 12:41:37 +02001014
1015 // Handle HLSL-style 0-based vertex/instance index.
1016 enum class TriState
1017 {
Hans-Kristian Arntzen39bd5f12019-10-28 12:55:14 +01001018 Neutral,
1019 No,
1020 Yes
Hans-Kristian Arntzen4ac12592019-10-24 12:41:37 +02001021 };
1022 TriState needs_base_vertex_arg = TriState::Neutral;
1023 TriState needs_base_instance_arg = TriState::Neutral;
1024
Chip Davis4302c5a2018-09-22 19:36:11 -05001025 bool has_sampled_images = false;
Lukas Hermanns50ac6862019-09-18 14:03:54 -04001026 bool builtin_declaration = false; // Handle HLSL-style 0-based vertex/instance index.
Hans-Kristian Arntzenc9d4f9c2020-02-24 12:47:14 +01001027
1028 bool is_using_builtin_array = false; // Force the use of C style array declaration.
1029 bool using_builtin_array() const;
1030
Bill Hollings0d6202e2018-07-26 16:40:32 -04001031 bool is_rasterization_disabled = false;
Chip Davisc51e5b72019-01-08 16:33:32 -06001032 bool capture_output_to_buffer = false;
Hans-Kristian Arntzeneaf7afe2019-05-09 12:15:45 +02001033 bool needs_swizzle_buffer_def = false;
1034 bool used_swizzle_buffer = false;
Chip Davisf3c09422019-02-22 12:11:17 -06001035 bool added_builtin_tess_level = false;
Chip Davis9d941572019-05-15 16:03:30 -05001036 bool needs_subgroup_invocation_id = false;
Chip Davis065b5bd2020-10-20 23:59:30 -05001037 bool needs_subgroup_size = false;
Chip Davisaca9b682020-11-02 20:56:46 -06001038 bool needs_sample_id = false;
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +02001039 std::string qual_pos_var_name;
1040 std::string stage_in_var_name = "in";
1041 std::string stage_out_var_name = "out";
Chip Davise75add42019-02-05 18:13:26 -06001042 std::string patch_stage_in_var_name = "patchIn";
Chip Daviseb89c3a2019-02-03 23:58:46 -06001043 std::string patch_stage_out_var_name = "patchOut";
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +02001044 std::string sampler_name_suffix = "Smplr";
Chip Davis664df222019-01-13 17:31:50 -06001045 std::string swizzle_name_suffix = "Swzl";
Hans-Kristian Arntzen7b9e0fb2019-05-27 11:59:29 +02001046 std::string buffer_size_name_suffix = "BufferSize";
Chip Davis39dce882019-08-02 15:11:19 -05001047 std::string plane_name_suffix = "Plane";
Chip Daviseb89c3a2019-02-03 23:58:46 -06001048 std::string input_wg_var_name = "gl_in";
Chip Davis688c5fc2020-02-20 21:38:28 -06001049 std::string input_buffer_var_name = "spvIn";
Chip Davisc51e5b72019-01-08 16:33:32 -06001050 std::string output_buffer_var_name = "spvOut";
Chip Daviseb89c3a2019-02-03 23:58:46 -06001051 std::string patch_output_buffer_var_name = "spvPatchOut";
1052 std::string tess_factor_buffer_var_name = "spvTessLevel";
Chip Davis688c5fc2020-02-20 21:38:28 -06001053 std::string index_buffer_var_name = "spvIndices";
Bill Hollings1c180782017-11-05 21:34:42 -05001054 spv::Op previous_instruction_opcode = spv::OpNop;
Bill Hollings103aabf2016-04-06 17:42:27 -04001055
Hans-Kristian Arntzen30bb1972019-06-10 15:41:36 +02001056 // Must be ordered since declaration is in a specific order.
1057 std::map<uint32_t, MSLConstexprSampler> constexpr_samplers_by_id;
1058 std::unordered_map<SetBindingPair, MSLConstexprSampler, InternalHasher> constexpr_samplers_by_binding;
1059 const MSLConstexprSampler *find_constexpr_sampler(uint32_t id) const;
1060
Hans-Kristian Arntzen7b9e0fb2019-05-27 11:59:29 +02001061 std::unordered_set<uint32_t> buffers_requiring_array_length;
Hans-Kristian Arntzena489ba72019-04-02 11:19:03 +02001062 SmallVector<uint32_t> buffer_arrays;
Hans-Kristian Arntzen6edbf0c2019-10-24 11:30:20 +02001063 std::unordered_set<uint32_t> atomic_image_vars; // Emulate texture2D atomic operations
Chip Davisaca9b682020-11-02 20:56:46 -06001064 std::unordered_set<uint32_t> pull_model_inputs;
Hans-Kristian Arntzendf58deb2018-04-17 17:43:10 +02001065
Chip Daviscb359342019-09-05 23:14:12 -05001066 // Must be ordered since array is in a specific order.
1067 std::map<SetBindingPair, std::pair<uint32_t, uint32_t>> buffers_requiring_dynamic_offset;
1068
Chip Davisb29f83c2020-04-10 01:13:33 -05001069 SmallVector<uint32_t> disabled_frag_outputs;
1070
Chip Davisfedbc352019-12-16 22:58:16 -06001071 std::unordered_set<SetBindingPair, InternalHasher> inline_uniform_blocks;
Chip Davisfedbc352019-12-16 22:58:16 -06001072
Hans-Kristian Arntzene47a77d2019-03-14 10:29:34 +01001073 uint32_t argument_buffer_ids[kMaxArgumentBuffers];
Hans-Kristian Arntzene2aadf82019-03-15 21:53:21 +01001074 uint32_t argument_buffer_discrete_mask = 0;
Hans-Kristian Arntzen4bb673a2019-10-14 12:51:48 +02001075 uint32_t argument_buffer_device_storage_mask = 0;
1076
Hans-Kristian Arntzene47a77d2019-03-14 10:29:34 +01001077 void analyze_argument_buffers();
Hans-Kristian Arntzenb3380ec2019-03-15 14:07:03 +01001078 bool descriptor_set_is_argument_buffer(uint32_t desc_set) const;
Bill Hollings9866cf42021-04-16 09:05:15 -04001079 MSLResourceBinding &get_argument_buffer_resource(uint32_t desc_set, uint32_t arg_idx);
Bill Hollingsb3bfe222021-04-18 17:34:55 -04001080 void add_argument_buffer_padding_buffer_type(SPIRType &struct_type, uint32_t &mbr_idx, uint32_t &arg_buff_index, MSLResourceBinding &rez_bind);
1081 void add_argument_buffer_padding_image_type(SPIRType &struct_type, uint32_t &mbr_idx, uint32_t &arg_buff_index, MSLResourceBinding &rez_bind);
1082 void add_argument_buffer_padding_sampler_type(SPIRType &struct_type, uint32_t &mbr_idx, uint32_t &arg_buff_index, MSLResourceBinding &rez_bind);
Bill Hollingsdaba0df2021-04-17 15:20:53 -04001083 void add_argument_buffer_padding_type(uint32_t mbr_type_id, SPIRType &struct_type, uint32_t &mbr_idx, uint32_t &arg_buff_index, uint32_t count);
Hans-Kristian Arntzene47a77d2019-03-14 10:29:34 +01001084
Hans-Kristian Arntzenb8033d72019-01-14 14:53:47 +01001085 uint32_t get_target_components_for_fragment_location(uint32_t location) const;
Hans-Kristian Arntzend573a952020-07-01 11:42:58 +02001086 uint32_t build_extended_vector_type(uint32_t type_id, uint32_t components,
1087 SPIRType::BaseType basetype = SPIRType::Unknown);
Chip Davisaca9b682020-11-02 20:56:46 -06001088 uint32_t build_msl_interpolant_type(uint32_t type_id, bool is_noperspective);
Hans-Kristian Arntzenb8033d72019-01-14 14:53:47 +01001089
Hans-Kristian Arntzen23db7442019-04-09 12:28:46 +02001090 bool suppress_missing_prototypes = false;
1091
Chip Davis39dce882019-08-02 15:11:19 -05001092 void add_spv_func_and_recompile(SPVFuncImpl spv_func);
1093
Hans-Kristian Arntzenc3bd1362020-01-16 11:07:30 +01001094 void activate_argument_buffer_resources();
1095
Hans-Kristian Arntzen6ef47d62020-04-27 11:23:24 +02001096 bool type_is_msl_framebuffer_fetch(const SPIRType &type) const;
Hans-Kristian Arntzen97796e02021-02-26 12:50:24 +01001097 bool type_is_pointer(const SPIRType &type) const;
1098 bool type_is_pointer_to_pointer(const SPIRType &type) const;
Hans-Kristian Arntzen893a0112021-01-07 15:00:45 +01001099 bool is_supported_argument_buffer_type(const SPIRType &type) const;
Hans-Kristian Arntzen6ef47d62020-04-27 11:23:24 +02001100
Hans-Kristian Arntzen46c48ee2021-04-08 11:47:35 +02001101 bool variable_storage_requires_stage_io(spv::StorageClass storage) const;
1102
Bill Hollingsebb50982021-07-13 21:22:13 -04001103 bool has_additional_fixed_sample_mask() const { return msl_options.additional_fixed_sample_mask != 0xffffffff; }
1104 std::string additional_fixed_sample_mask_str() const;
1105
Bill Hollings4c198bb2017-01-20 11:24:44 -05001106 // OpcodeHandler that handles several MSL preprocessing operations.
Bill Hollings2d0d3282017-01-20 11:33:59 -05001107 struct OpCodePreprocessor : OpcodeHandler
Bill Hollingsaca1b552016-12-04 12:32:58 -05001108 {
Bill Hollings2d0d3282017-01-20 11:33:59 -05001109 OpCodePreprocessor(CompilerMSL &compiler_)
Bill Hollings7d38f182016-12-21 16:31:13 -05001110 : compiler(compiler_)
Bill Hollings7d38f182016-12-21 16:31:13 -05001111 {
1112 }
1113
1114 bool handle(spv::Op opcode, const uint32_t *args, uint32_t length) override;
Bill Hollings1c180782017-11-05 21:34:42 -05001115 CompilerMSL::SPVFuncImpl get_spv_func_impl(spv::Op opcode, const uint32_t *args);
Bill Hollingsc3d74e12018-07-27 16:53:36 -04001116 void check_resource_write(uint32_t var_id);
Bill Hollings7d38f182016-12-21 16:31:13 -05001117
Bill Hollings2d0d3282017-01-20 11:33:59 -05001118 CompilerMSL &compiler;
Bill Hollings1c180782017-11-05 21:34:42 -05001119 std::unordered_map<uint32_t, uint32_t> result_types;
Hans-Kristian Arntzen6edbf0c2019-10-24 11:30:20 +02001120 std::unordered_map<uint32_t, uint32_t> image_pointers; // Emulate texture2D atomic operations
Bill Hollings2d0d3282017-01-20 11:33:59 -05001121 bool suppress_missing_prototypes = false;
Bill Hollings8f6df772017-05-19 18:14:08 -04001122 bool uses_atomics = false;
Bill Hollingsc3d74e12018-07-27 16:53:36 -04001123 bool uses_resource_write = false;
Chip Davis9d941572019-05-15 16:03:30 -05001124 bool needs_subgroup_invocation_id = false;
Chip Davis065b5bd2020-10-20 23:59:30 -05001125 bool needs_subgroup_size = false;
Chip Davisaca9b682020-11-02 20:56:46 -06001126 bool needs_sample_id = false;
Bill Hollingsaca1b552016-12-04 12:32:58 -05001127 };
1128
Chip Davis4302c5a2018-09-22 19:36:11 -05001129 // OpcodeHandler that scans for uses of sampled images
1130 struct SampledImageScanner : OpcodeHandler
1131 {
1132 SampledImageScanner(CompilerMSL &compiler_)
1133 : compiler(compiler_)
1134 {
1135 }
1136
1137 bool handle(spv::Op opcode, const uint32_t *args, uint32_t) override;
Chip Davis4302c5a2018-09-22 19:36:11 -05001138
1139 CompilerMSL &compiler;
1140 };
1141
Bill Hollings7d38f182016-12-21 16:31:13 -05001142 // Sorts the members of a SPIRType and associated Meta info based on a settable sorting
1143 // aspect, which defines which aspect of the struct members will be used to sort them.
1144 // Regardless of the sorting aspect, built-in members always appear at the end of the struct.
1145 struct MemberSorter
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +02001146 {
Bill Hollings7d38f182016-12-21 16:31:13 -05001147 enum SortAspect
1148 {
Hans-Kristian Arntzen9a144bb2021-03-26 11:00:35 +01001149 LocationThenBuiltInType,
1150 Offset
Bill Hollings7d38f182016-12-21 16:31:13 -05001151 };
1152
1153 void sort();
1154 bool operator()(uint32_t mbr_idx1, uint32_t mbr_idx2);
Bill Hollings484931d2017-02-28 21:44:36 -05001155 MemberSorter(SPIRType &t, Meta &m, SortAspect sa);
1156
Bill Hollings7d38f182016-12-21 16:31:13 -05001157 SPIRType &type;
1158 Meta &meta;
1159 SortAspect sort_aspect;
1160 };
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +02001161};
Hans-Kristian Arntzena489ba72019-04-02 11:19:03 +02001162} // namespace SPIRV_CROSS_NAMESPACE
Bill Hollings103aabf2016-04-06 17:42:27 -04001163
1164#endif