• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019-2021 Hans-Kristian Arntzen
3  * SPDX-License-Identifier: Apache-2.0 OR MIT
4  *
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 
18 /*
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>.
22  */
23 
24 #include "spirv_cross_c.h"
25 
26 #if SPIRV_CROSS_C_API_CPP
27 #include "spirv_cpp.hpp"
28 #endif
29 #if SPIRV_CROSS_C_API_GLSL
30 #include "spirv_glsl.hpp"
31 #else
32 #include "spirv_cross.hpp"
33 #endif
34 #if SPIRV_CROSS_C_API_HLSL
35 #include "spirv_hlsl.hpp"
36 #endif
37 #if SPIRV_CROSS_C_API_MSL
38 #include "spirv_msl.hpp"
39 #endif
40 #if SPIRV_CROSS_C_API_REFLECT
41 #include "spirv_reflect.hpp"
42 #endif
43 
44 #ifdef HAVE_SPIRV_CROSS_GIT_VERSION
45 #include "gitversion.h"
46 #endif
47 
48 #include "spirv_parser.hpp"
49 #include <memory>
50 #include <new>
51 #include <string.h>
52 
53 // clang-format off
54 
55 #ifdef _MSC_VER
56 #pragma warning(push)
57 #pragma warning(disable : 4996)
58 #endif
59 
60 #ifndef SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS
61 #define SPVC_BEGIN_SAFE_SCOPE try
62 #else
63 #define SPVC_BEGIN_SAFE_SCOPE
64 #endif
65 
66 #ifndef SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS
67 #define SPVC_END_SAFE_SCOPE(context, error) \
68 	catch (const std::exception &e)         \
69 	{                                       \
70 		(context)->report_error(e.what());  \
71 		return (error);                     \
72 	}
73 #else
74 #define SPVC_END_SAFE_SCOPE(context, error)
75 #endif
76 
77 using namespace std;
78 using namespace SPIRV_CROSS_NAMESPACE;
79 
80 struct ScratchMemoryAllocation
81 {
82 	virtual ~ScratchMemoryAllocation() = default;
83 };
84 
85 struct StringAllocation : ScratchMemoryAllocation
86 {
StringAllocationStringAllocation87 	explicit StringAllocation(const char *name)
88 	    : str(name)
89 	{
90 	}
91 
StringAllocationStringAllocation92 	explicit StringAllocation(std::string name)
93 	    : str(std::move(name))
94 	{
95 	}
96 
97 	std::string str;
98 };
99 
100 template <typename T>
101 struct TemporaryBuffer : ScratchMemoryAllocation
102 {
103 	SmallVector<T> buffer;
104 };
105 
106 template <typename T, typename... Ts>
spvc_allocate(Ts &&...ts)107 static inline std::unique_ptr<T> spvc_allocate(Ts &&... ts)
108 {
109 	return std::unique_ptr<T>(new T(std::forward<Ts>(ts)...));
110 }
111 
112 struct spvc_context_s
113 {
114 	string last_error;
115 	SmallVector<unique_ptr<ScratchMemoryAllocation>> allocations;
116 	const char *allocate_name(const std::string &name);
117 
118 	spvc_error_callback callback = nullptr;
119 	void *callback_userdata = nullptr;
120 	void report_error(std::string msg);
121 };
122 
report_error(std::string msg)123 void spvc_context_s::report_error(std::string msg)
124 {
125 	last_error = std::move(msg);
126 	if (callback)
127 		callback(callback_userdata, last_error.c_str());
128 }
129 
allocate_name(const std::string & name)130 const char *spvc_context_s::allocate_name(const std::string &name)
131 {
132 	SPVC_BEGIN_SAFE_SCOPE
133 	{
134 		auto alloc = spvc_allocate<StringAllocation>(name);
135 		auto *ret = alloc->str.c_str();
136 		allocations.emplace_back(std::move(alloc));
137 		return ret;
138 	}
139 	SPVC_END_SAFE_SCOPE(this, nullptr)
140 }
141 
142 struct spvc_parsed_ir_s : ScratchMemoryAllocation
143 {
144 	spvc_context context = nullptr;
145 	ParsedIR parsed;
146 };
147 
148 struct spvc_compiler_s : ScratchMemoryAllocation
149 {
150 	spvc_context context = nullptr;
151 	unique_ptr<Compiler> compiler;
152 	spvc_backend backend = SPVC_BACKEND_NONE;
153 };
154 
155 struct spvc_compiler_options_s : ScratchMemoryAllocation
156 {
157 	spvc_context context = nullptr;
158 	uint32_t backend_flags = 0;
159 #if SPIRV_CROSS_C_API_GLSL
160 	CompilerGLSL::Options glsl;
161 #endif
162 #if SPIRV_CROSS_C_API_MSL
163 	CompilerMSL::Options msl;
164 #endif
165 #if SPIRV_CROSS_C_API_HLSL
166 	CompilerHLSL::Options hlsl;
167 #endif
168 };
169 
170 struct spvc_set_s : ScratchMemoryAllocation
171 {
172 	std::unordered_set<VariableID> set;
173 };
174 
175 // Dummy-inherit to we can keep our opaque type handle type safe in C-land as well,
176 // and avoid just throwing void * around.
177 struct spvc_type_s : SPIRType
178 {
179 };
180 
181 struct spvc_constant_s : SPIRConstant
182 {
183 };
184 
185 struct spvc_resources_s : ScratchMemoryAllocation
186 {
187 	spvc_context context = nullptr;
188 	SmallVector<spvc_reflected_resource> uniform_buffers;
189 	SmallVector<spvc_reflected_resource> storage_buffers;
190 	SmallVector<spvc_reflected_resource> stage_inputs;
191 	SmallVector<spvc_reflected_resource> stage_outputs;
192 	SmallVector<spvc_reflected_resource> subpass_inputs;
193 	SmallVector<spvc_reflected_resource> storage_images;
194 	SmallVector<spvc_reflected_resource> sampled_images;
195 	SmallVector<spvc_reflected_resource> atomic_counters;
196 	SmallVector<spvc_reflected_resource> push_constant_buffers;
197 	SmallVector<spvc_reflected_resource> separate_images;
198 	SmallVector<spvc_reflected_resource> separate_samplers;
199 	SmallVector<spvc_reflected_resource> acceleration_structures;
200 	SmallVector<spvc_reflected_builtin_resource> builtin_inputs;
201 	SmallVector<spvc_reflected_builtin_resource> builtin_outputs;
202 
203 	bool copy_resources(SmallVector<spvc_reflected_resource> &outputs, const SmallVector<Resource> &inputs);
204 	bool copy_resources(SmallVector<spvc_reflected_builtin_resource> &outputs, const SmallVector<BuiltInResource> &inputs);
205 	bool copy_resources(const ShaderResources &resources);
206 };
207 
spvc_context_create(spvc_context * context)208 spvc_result spvc_context_create(spvc_context *context)
209 {
210 	auto *ctx = new (std::nothrow) spvc_context_s;
211 	if (!ctx)
212 		return SPVC_ERROR_OUT_OF_MEMORY;
213 
214 	*context = ctx;
215 	return SPVC_SUCCESS;
216 }
217 
spvc_context_destroy(spvc_context context)218 void spvc_context_destroy(spvc_context context)
219 {
220 	delete context;
221 }
222 
spvc_context_release_allocations(spvc_context context)223 void spvc_context_release_allocations(spvc_context context)
224 {
225 	context->allocations.clear();
226 }
227 
spvc_context_get_last_error_string(spvc_context context)228 const char *spvc_context_get_last_error_string(spvc_context context)
229 {
230 	return context->last_error.c_str();
231 }
232 
spvc_context_set_error_callback(spvc_context context,spvc_error_callback cb,void * userdata)233 SPVC_PUBLIC_API void spvc_context_set_error_callback(spvc_context context, spvc_error_callback cb, void *userdata)
234 {
235 	context->callback = cb;
236 	context->callback_userdata = userdata;
237 }
238 
spvc_context_parse_spirv(spvc_context context,const SpvId * spirv,size_t word_count,spvc_parsed_ir * parsed_ir)239 spvc_result spvc_context_parse_spirv(spvc_context context, const SpvId *spirv, size_t word_count,
240                                      spvc_parsed_ir *parsed_ir)
241 {
242 	SPVC_BEGIN_SAFE_SCOPE
243 	{
244 		std::unique_ptr<spvc_parsed_ir_s> pir(new (std::nothrow) spvc_parsed_ir_s);
245 		if (!pir)
246 		{
247 			context->report_error("Out of memory.");
248 			return SPVC_ERROR_OUT_OF_MEMORY;
249 		}
250 
251 		pir->context = context;
252 		Parser parser(spirv, word_count);
253 		parser.parse();
254 		pir->parsed = move(parser.get_parsed_ir());
255 		*parsed_ir = pir.get();
256 		context->allocations.push_back(std::move(pir));
257 	}
258 	SPVC_END_SAFE_SCOPE(context, SPVC_ERROR_INVALID_SPIRV)
259 	return SPVC_SUCCESS;
260 }
261 
spvc_context_create_compiler(spvc_context context,spvc_backend backend,spvc_parsed_ir parsed_ir,spvc_capture_mode mode,spvc_compiler * compiler)262 spvc_result spvc_context_create_compiler(spvc_context context, spvc_backend backend, spvc_parsed_ir parsed_ir,
263                                          spvc_capture_mode mode, spvc_compiler *compiler)
264 {
265 	SPVC_BEGIN_SAFE_SCOPE
266 	{
267 		std::unique_ptr<spvc_compiler_s> comp(new (std::nothrow) spvc_compiler_s);
268 		if (!comp)
269 		{
270 			context->report_error("Out of memory.");
271 			return SPVC_ERROR_OUT_OF_MEMORY;
272 		}
273 		comp->backend = backend;
274 		comp->context = context;
275 
276 		if (mode != SPVC_CAPTURE_MODE_COPY && mode != SPVC_CAPTURE_MODE_TAKE_OWNERSHIP)
277 		{
278 			context->report_error("Invalid argument for capture mode.");
279 			return SPVC_ERROR_INVALID_ARGUMENT;
280 		}
281 
282 		switch (backend)
283 		{
284 		case SPVC_BACKEND_NONE:
285 			if (mode == SPVC_CAPTURE_MODE_TAKE_OWNERSHIP)
286 				comp->compiler.reset(new Compiler(move(parsed_ir->parsed)));
287 			else if (mode == SPVC_CAPTURE_MODE_COPY)
288 				comp->compiler.reset(new Compiler(parsed_ir->parsed));
289 			break;
290 
291 #if SPIRV_CROSS_C_API_GLSL
292 		case SPVC_BACKEND_GLSL:
293 			if (mode == SPVC_CAPTURE_MODE_TAKE_OWNERSHIP)
294 				comp->compiler.reset(new CompilerGLSL(move(parsed_ir->parsed)));
295 			else if (mode == SPVC_CAPTURE_MODE_COPY)
296 				comp->compiler.reset(new CompilerGLSL(parsed_ir->parsed));
297 			break;
298 #endif
299 
300 #if SPIRV_CROSS_C_API_HLSL
301 		case SPVC_BACKEND_HLSL:
302 			if (mode == SPVC_CAPTURE_MODE_TAKE_OWNERSHIP)
303 				comp->compiler.reset(new CompilerHLSL(move(parsed_ir->parsed)));
304 			else if (mode == SPVC_CAPTURE_MODE_COPY)
305 				comp->compiler.reset(new CompilerHLSL(parsed_ir->parsed));
306 			break;
307 #endif
308 
309 #if SPIRV_CROSS_C_API_MSL
310 		case SPVC_BACKEND_MSL:
311 			if (mode == SPVC_CAPTURE_MODE_TAKE_OWNERSHIP)
312 				comp->compiler.reset(new CompilerMSL(move(parsed_ir->parsed)));
313 			else if (mode == SPVC_CAPTURE_MODE_COPY)
314 				comp->compiler.reset(new CompilerMSL(parsed_ir->parsed));
315 			break;
316 #endif
317 
318 #if SPIRV_CROSS_C_API_CPP
319 		case SPVC_BACKEND_CPP:
320 			if (mode == SPVC_CAPTURE_MODE_TAKE_OWNERSHIP)
321 				comp->compiler.reset(new CompilerCPP(move(parsed_ir->parsed)));
322 			else if (mode == SPVC_CAPTURE_MODE_COPY)
323 				comp->compiler.reset(new CompilerCPP(parsed_ir->parsed));
324 			break;
325 #endif
326 
327 #if SPIRV_CROSS_C_API_REFLECT
328 		case SPVC_BACKEND_JSON:
329 			if (mode == SPVC_CAPTURE_MODE_TAKE_OWNERSHIP)
330 				comp->compiler.reset(new CompilerReflection(move(parsed_ir->parsed)));
331 			else if (mode == SPVC_CAPTURE_MODE_COPY)
332 				comp->compiler.reset(new CompilerReflection(parsed_ir->parsed));
333 			break;
334 #endif
335 
336 		default:
337 			context->report_error("Invalid backend.");
338 			return SPVC_ERROR_INVALID_ARGUMENT;
339 		}
340 
341 		*compiler = comp.get();
342 		context->allocations.push_back(std::move(comp));
343 	}
344 	SPVC_END_SAFE_SCOPE(context, SPVC_ERROR_OUT_OF_MEMORY)
345 	return SPVC_SUCCESS;
346 }
347 
spvc_compiler_create_compiler_options(spvc_compiler compiler,spvc_compiler_options * options)348 spvc_result spvc_compiler_create_compiler_options(spvc_compiler compiler, spvc_compiler_options *options)
349 {
350 	SPVC_BEGIN_SAFE_SCOPE
351 	{
352 		std::unique_ptr<spvc_compiler_options_s> opt(new (std::nothrow) spvc_compiler_options_s);
353 		if (!opt)
354 		{
355 			compiler->context->report_error("Out of memory.");
356 			return SPVC_ERROR_OUT_OF_MEMORY;
357 		}
358 
359 		opt->context = compiler->context;
360 		opt->backend_flags = 0;
361 		switch (compiler->backend)
362 		{
363 #if SPIRV_CROSS_C_API_MSL
364 		case SPVC_BACKEND_MSL:
365 			opt->backend_flags |= SPVC_COMPILER_OPTION_MSL_BIT | SPVC_COMPILER_OPTION_COMMON_BIT;
366 			opt->glsl = static_cast<CompilerMSL *>(compiler->compiler.get())->get_common_options();
367 			opt->msl = static_cast<CompilerMSL *>(compiler->compiler.get())->get_msl_options();
368 			break;
369 #endif
370 
371 #if SPIRV_CROSS_C_API_HLSL
372 		case SPVC_BACKEND_HLSL:
373 			opt->backend_flags |= SPVC_COMPILER_OPTION_HLSL_BIT | SPVC_COMPILER_OPTION_COMMON_BIT;
374 			opt->glsl = static_cast<CompilerHLSL *>(compiler->compiler.get())->get_common_options();
375 			opt->hlsl = static_cast<CompilerHLSL *>(compiler->compiler.get())->get_hlsl_options();
376 			break;
377 #endif
378 
379 #if SPIRV_CROSS_C_API_GLSL
380 		case SPVC_BACKEND_GLSL:
381 			opt->backend_flags |= SPVC_COMPILER_OPTION_GLSL_BIT | SPVC_COMPILER_OPTION_COMMON_BIT;
382 			opt->glsl = static_cast<CompilerGLSL *>(compiler->compiler.get())->get_common_options();
383 			break;
384 #endif
385 
386 		default:
387 			break;
388 		}
389 
390 		*options = opt.get();
391 		compiler->context->allocations.push_back(std::move(opt));
392 	}
393 	SPVC_END_SAFE_SCOPE(compiler->context, SPVC_ERROR_OUT_OF_MEMORY)
394 	return SPVC_SUCCESS;
395 }
396 
spvc_compiler_options_set_bool(spvc_compiler_options options,spvc_compiler_option option,spvc_bool value)397 spvc_result spvc_compiler_options_set_bool(spvc_compiler_options options, spvc_compiler_option option,
398                                            spvc_bool value)
399 {
400 	return spvc_compiler_options_set_uint(options, option, value ? 1 : 0);
401 }
402 
spvc_compiler_options_set_uint(spvc_compiler_options options,spvc_compiler_option option,unsigned value)403 spvc_result spvc_compiler_options_set_uint(spvc_compiler_options options, spvc_compiler_option option, unsigned value)
404 {
405 	(void)value;
406 	(void)option;
407 	uint32_t supported_mask = options->backend_flags;
408 	uint32_t required_mask = option & SPVC_COMPILER_OPTION_LANG_BITS;
409 	if ((required_mask | supported_mask) != supported_mask)
410 	{
411 		options->context->report_error("Option is not supported by current backend.");
412 		return SPVC_ERROR_INVALID_ARGUMENT;
413 	}
414 
415 	switch (option)
416 	{
417 #if SPIRV_CROSS_C_API_GLSL
418 	case SPVC_COMPILER_OPTION_FORCE_TEMPORARY:
419 		options->glsl.force_temporary = value != 0;
420 		break;
421 	case SPVC_COMPILER_OPTION_FLATTEN_MULTIDIMENSIONAL_ARRAYS:
422 		options->glsl.flatten_multidimensional_arrays = value != 0;
423 		break;
424 	case SPVC_COMPILER_OPTION_FIXUP_DEPTH_CONVENTION:
425 		options->glsl.vertex.fixup_clipspace = value != 0;
426 		break;
427 	case SPVC_COMPILER_OPTION_FLIP_VERTEX_Y:
428 		options->glsl.vertex.flip_vert_y = value != 0;
429 		break;
430 	case SPVC_COMPILER_OPTION_EMIT_LINE_DIRECTIVES:
431 		options->glsl.emit_line_directives = value != 0;
432 		break;
433 	case SPVC_COMPILER_OPTION_ENABLE_STORAGE_IMAGE_QUALIFIER_DEDUCTION:
434 		options->glsl.enable_storage_image_qualifier_deduction = value != 0;
435 		break;
436 	case SPVC_COMPILER_OPTION_FORCE_ZERO_INITIALIZED_VARIABLES:
437 		options->glsl.force_zero_initialized_variables = value != 0;
438 		break;
439 
440 	case SPVC_COMPILER_OPTION_GLSL_SUPPORT_NONZERO_BASE_INSTANCE:
441 		options->glsl.vertex.support_nonzero_base_instance = value != 0;
442 		break;
443 	case SPVC_COMPILER_OPTION_GLSL_SEPARATE_SHADER_OBJECTS:
444 		options->glsl.separate_shader_objects = value != 0;
445 		break;
446 	case SPVC_COMPILER_OPTION_GLSL_ENABLE_420PACK_EXTENSION:
447 		options->glsl.enable_420pack_extension = value != 0;
448 		break;
449 	case SPVC_COMPILER_OPTION_GLSL_VERSION:
450 		options->glsl.version = value;
451 		break;
452 	case SPVC_COMPILER_OPTION_GLSL_ES:
453 		options->glsl.es = value != 0;
454 		break;
455 	case SPVC_COMPILER_OPTION_GLSL_VULKAN_SEMANTICS:
456 		options->glsl.vulkan_semantics = value != 0;
457 		break;
458 	case SPVC_COMPILER_OPTION_GLSL_ES_DEFAULT_FLOAT_PRECISION_HIGHP:
459 		options->glsl.fragment.default_float_precision =
460 		    value != 0 ? CompilerGLSL::Options::Precision::Highp : CompilerGLSL::Options::Precision::Mediump;
461 		break;
462 	case SPVC_COMPILER_OPTION_GLSL_ES_DEFAULT_INT_PRECISION_HIGHP:
463 		options->glsl.fragment.default_int_precision =
464 		    value != 0 ? CompilerGLSL::Options::Precision::Highp : CompilerGLSL::Options::Precision::Mediump;
465 		break;
466 	case SPVC_COMPILER_OPTION_GLSL_EMIT_PUSH_CONSTANT_AS_UNIFORM_BUFFER:
467 		options->glsl.emit_push_constant_as_uniform_buffer = value != 0;
468 		break;
469 	case SPVC_COMPILER_OPTION_GLSL_EMIT_UNIFORM_BUFFER_AS_PLAIN_UNIFORMS:
470 		options->glsl.emit_uniform_buffer_as_plain_uniforms = value != 0;
471 		break;
472 	case SPVC_COMPILER_OPTION_GLSL_FORCE_FLATTENED_IO_BLOCKS:
473 		options->glsl.force_flattened_io_blocks = value != 0;
474 		break;
475 	case SPVC_COMPILER_OPTION_GLSL_OVR_MULTIVIEW_VIEW_COUNT:
476 		options->glsl.ovr_multiview_view_count = value;
477 		break;
478 #endif
479 
480 #if SPIRV_CROSS_C_API_HLSL
481 	case SPVC_COMPILER_OPTION_HLSL_SHADER_MODEL:
482 		options->hlsl.shader_model = value;
483 		break;
484 
485 	case SPVC_COMPILER_OPTION_HLSL_POINT_SIZE_COMPAT:
486 		options->hlsl.point_size_compat = value != 0;
487 		break;
488 
489 	case SPVC_COMPILER_OPTION_HLSL_POINT_COORD_COMPAT:
490 		options->hlsl.point_coord_compat = value != 0;
491 		break;
492 
493 	case SPVC_COMPILER_OPTION_HLSL_SUPPORT_NONZERO_BASE_VERTEX_BASE_INSTANCE:
494 		options->hlsl.support_nonzero_base_vertex_base_instance = value != 0;
495 		break;
496 
497 	case SPVC_COMPILER_OPTION_HLSL_FORCE_STORAGE_BUFFER_AS_UAV:
498 		options->hlsl.force_storage_buffer_as_uav = value != 0;
499 		break;
500 
501 	case SPVC_COMPILER_OPTION_HLSL_NONWRITABLE_UAV_TEXTURE_AS_SRV:
502 		options->hlsl.nonwritable_uav_texture_as_srv = value != 0;
503 		break;
504 
505 	case SPVC_COMPILER_OPTION_HLSL_ENABLE_16BIT_TYPES:
506 		options->hlsl.enable_16bit_types = value != 0;
507 		break;
508 
509 	case SPVC_COMPILER_OPTION_HLSL_FLATTEN_MATRIX_VERTEX_INPUT_SEMANTICS:
510 		options->hlsl.flatten_matrix_vertex_input_semantics = value != 0;
511 		break;
512 #endif
513 
514 #if SPIRV_CROSS_C_API_MSL
515 	case SPVC_COMPILER_OPTION_MSL_VERSION:
516 		options->msl.msl_version = value;
517 		break;
518 
519 	case SPVC_COMPILER_OPTION_MSL_TEXEL_BUFFER_TEXTURE_WIDTH:
520 		options->msl.texel_buffer_texture_width = value;
521 		break;
522 
523 	case SPVC_COMPILER_OPTION_MSL_SWIZZLE_BUFFER_INDEX:
524 		options->msl.swizzle_buffer_index = value;
525 		break;
526 
527 	case SPVC_COMPILER_OPTION_MSL_INDIRECT_PARAMS_BUFFER_INDEX:
528 		options->msl.indirect_params_buffer_index = value;
529 		break;
530 
531 	case SPVC_COMPILER_OPTION_MSL_SHADER_OUTPUT_BUFFER_INDEX:
532 		options->msl.shader_output_buffer_index = value;
533 		break;
534 
535 	case SPVC_COMPILER_OPTION_MSL_SHADER_PATCH_OUTPUT_BUFFER_INDEX:
536 		options->msl.shader_patch_output_buffer_index = value;
537 		break;
538 
539 	case SPVC_COMPILER_OPTION_MSL_SHADER_TESS_FACTOR_OUTPUT_BUFFER_INDEX:
540 		options->msl.shader_tess_factor_buffer_index = value;
541 		break;
542 
543 	case SPVC_COMPILER_OPTION_MSL_SHADER_INPUT_WORKGROUP_INDEX:
544 		options->msl.shader_input_wg_index = value;
545 		break;
546 
547 	case SPVC_COMPILER_OPTION_MSL_ENABLE_POINT_SIZE_BUILTIN:
548 		options->msl.enable_point_size_builtin = value != 0;
549 		break;
550 
551 	case SPVC_COMPILER_OPTION_MSL_DISABLE_RASTERIZATION:
552 		options->msl.disable_rasterization = value != 0;
553 		break;
554 
555 	case SPVC_COMPILER_OPTION_MSL_CAPTURE_OUTPUT_TO_BUFFER:
556 		options->msl.capture_output_to_buffer = value != 0;
557 		break;
558 
559 	case SPVC_COMPILER_OPTION_MSL_SWIZZLE_TEXTURE_SAMPLES:
560 		options->msl.swizzle_texture_samples = value != 0;
561 		break;
562 
563 	case SPVC_COMPILER_OPTION_MSL_PAD_FRAGMENT_OUTPUT_COMPONENTS:
564 		options->msl.pad_fragment_output_components = value != 0;
565 		break;
566 
567 	case SPVC_COMPILER_OPTION_MSL_TESS_DOMAIN_ORIGIN_LOWER_LEFT:
568 		options->msl.tess_domain_origin_lower_left = value != 0;
569 		break;
570 
571 	case SPVC_COMPILER_OPTION_MSL_PLATFORM:
572 		options->msl.platform = static_cast<CompilerMSL::Options::Platform>(value);
573 		break;
574 
575 	case SPVC_COMPILER_OPTION_MSL_ARGUMENT_BUFFERS:
576 		options->msl.argument_buffers = value != 0;
577 		break;
578 
579 	case SPVC_COMPILER_OPTION_MSL_TEXTURE_BUFFER_NATIVE:
580 		options->msl.texture_buffer_native = value != 0;
581 		break;
582 
583 	case SPVC_COMPILER_OPTION_MSL_BUFFER_SIZE_BUFFER_INDEX:
584 		options->msl.buffer_size_buffer_index = value;
585 		break;
586 
587 	case SPVC_COMPILER_OPTION_MSL_MULTIVIEW:
588 		options->msl.multiview = value != 0;
589 		break;
590 
591 	case SPVC_COMPILER_OPTION_MSL_VIEW_MASK_BUFFER_INDEX:
592 		options->msl.view_mask_buffer_index = value;
593 		break;
594 
595 	case SPVC_COMPILER_OPTION_MSL_DEVICE_INDEX:
596 		options->msl.device_index = value;
597 		break;
598 
599 	case SPVC_COMPILER_OPTION_MSL_VIEW_INDEX_FROM_DEVICE_INDEX:
600 		options->msl.view_index_from_device_index = value != 0;
601 		break;
602 
603 	case SPVC_COMPILER_OPTION_MSL_DISPATCH_BASE:
604 		options->msl.dispatch_base = value != 0;
605 		break;
606 
607 	case SPVC_COMPILER_OPTION_MSL_DYNAMIC_OFFSETS_BUFFER_INDEX:
608 		options->msl.dynamic_offsets_buffer_index = value;
609 		break;
610 
611 	case SPVC_COMPILER_OPTION_MSL_TEXTURE_1D_AS_2D:
612 		options->msl.texture_1D_as_2D = value != 0;
613 		break;
614 
615 	case SPVC_COMPILER_OPTION_MSL_ENABLE_BASE_INDEX_ZERO:
616 		options->msl.enable_base_index_zero = value != 0;
617 		break;
618 
619 	case SPVC_COMPILER_OPTION_MSL_FRAMEBUFFER_FETCH_SUBPASS:
620 		options->msl.use_framebuffer_fetch_subpasses = value != 0;
621 		break;
622 
623 	case SPVC_COMPILER_OPTION_MSL_INVARIANT_FP_MATH:
624 		options->msl.invariant_float_math = value != 0;
625 		break;
626 
627 	case SPVC_COMPILER_OPTION_MSL_EMULATE_CUBEMAP_ARRAY:
628 		options->msl.emulate_cube_array = value != 0;
629 		break;
630 
631 	case SPVC_COMPILER_OPTION_MSL_ENABLE_DECORATION_BINDING:
632 		options->msl.enable_decoration_binding = value != 0;
633 		break;
634 
635 	case SPVC_COMPILER_OPTION_MSL_FORCE_ACTIVE_ARGUMENT_BUFFER_RESOURCES:
636 		options->msl.force_active_argument_buffer_resources = value != 0;
637 		break;
638 
639 	case SPVC_COMPILER_OPTION_MSL_FORCE_NATIVE_ARRAYS:
640 		options->msl.force_native_arrays = value != 0;
641 		break;
642 
643 	case SPVC_COMPILER_OPTION_MSL_ENABLE_FRAG_OUTPUT_MASK:
644 		options->msl.enable_frag_output_mask = value;
645 		break;
646 
647 	case SPVC_COMPILER_OPTION_MSL_ENABLE_FRAG_DEPTH_BUILTIN:
648 		options->msl.enable_frag_depth_builtin = value != 0;
649 		break;
650 
651 	case SPVC_COMPILER_OPTION_MSL_ENABLE_FRAG_STENCIL_REF_BUILTIN:
652 		options->msl.enable_frag_stencil_ref_builtin = value != 0;
653 		break;
654 
655 	case SPVC_COMPILER_OPTION_MSL_ENABLE_CLIP_DISTANCE_USER_VARYING:
656 		options->msl.enable_clip_distance_user_varying = value != 0;
657 		break;
658 
659 	case SPVC_COMPILER_OPTION_MSL_MULTI_PATCH_WORKGROUP:
660 		options->msl.multi_patch_workgroup = value != 0;
661 		break;
662 
663 	case SPVC_COMPILER_OPTION_MSL_SHADER_INPUT_BUFFER_INDEX:
664 		options->msl.shader_input_buffer_index = value;
665 		break;
666 
667 	case SPVC_COMPILER_OPTION_MSL_SHADER_INDEX_BUFFER_INDEX:
668 		options->msl.shader_index_buffer_index = value;
669 		break;
670 
671 	case SPVC_COMPILER_OPTION_MSL_VERTEX_FOR_TESSELLATION:
672 		options->msl.vertex_for_tessellation = value != 0;
673 		break;
674 
675 	case SPVC_COMPILER_OPTION_MSL_VERTEX_INDEX_TYPE:
676 		options->msl.vertex_index_type = static_cast<CompilerMSL::Options::IndexType>(value);
677 		break;
678 
679 	case SPVC_COMPILER_OPTION_MSL_MULTIVIEW_LAYERED_RENDERING:
680 		options->msl.multiview_layered_rendering = value != 0;
681 		break;
682 
683 	case SPVC_COMPILER_OPTION_MSL_ARRAYED_SUBPASS_INPUT:
684 		options->msl.arrayed_subpass_input = value != 0;
685 		break;
686 
687 	case SPVC_COMPILER_OPTION_MSL_R32UI_LINEAR_TEXTURE_ALIGNMENT:
688 		options->msl.r32ui_linear_texture_alignment = value;
689 		break;
690 
691 	case SPVC_COMPILER_OPTION_MSL_R32UI_ALIGNMENT_CONSTANT_ID:
692 		options->msl.r32ui_alignment_constant_id = value;
693 		break;
694 
695 	case SPVC_COMPILER_OPTION_MSL_IOS_USE_SIMDGROUP_FUNCTIONS:
696 		options->msl.ios_use_simdgroup_functions = value != 0;
697 		break;
698 
699 	case SPVC_COMPILER_OPTION_MSL_EMULATE_SUBGROUPS:
700 		options->msl.emulate_subgroups = value != 0;
701 		break;
702 
703 	case SPVC_COMPILER_OPTION_MSL_FIXED_SUBGROUP_SIZE:
704 		options->msl.fixed_subgroup_size = value;
705 		break;
706 
707 	case SPVC_COMPILER_OPTION_MSL_FORCE_SAMPLE_RATE_SHADING:
708 		options->msl.force_sample_rate_shading = value != 0;
709 		break;
710 
711 	case SPVC_COMPILER_OPTION_MSL_IOS_SUPPORT_BASE_VERTEX_INSTANCE:
712 		options->msl.ios_support_base_vertex_instance = value != 0;
713 		break;
714 #endif
715 
716 	default:
717 		options->context->report_error("Unknown option.");
718 		return SPVC_ERROR_INVALID_ARGUMENT;
719 	}
720 
721 	return SPVC_SUCCESS;
722 }
723 
spvc_compiler_install_compiler_options(spvc_compiler compiler,spvc_compiler_options options)724 spvc_result spvc_compiler_install_compiler_options(spvc_compiler compiler, spvc_compiler_options options)
725 {
726 	(void)options;
727 	switch (compiler->backend)
728 	{
729 #if SPIRV_CROSS_C_API_GLSL
730 	case SPVC_BACKEND_GLSL:
731 		static_cast<CompilerGLSL &>(*compiler->compiler).set_common_options(options->glsl);
732 		break;
733 #endif
734 
735 #if SPIRV_CROSS_C_API_HLSL
736 	case SPVC_BACKEND_HLSL:
737 		static_cast<CompilerHLSL &>(*compiler->compiler).set_common_options(options->glsl);
738 		static_cast<CompilerHLSL &>(*compiler->compiler).set_hlsl_options(options->hlsl);
739 		break;
740 #endif
741 
742 #if SPIRV_CROSS_C_API_MSL
743 	case SPVC_BACKEND_MSL:
744 		static_cast<CompilerMSL &>(*compiler->compiler).set_common_options(options->glsl);
745 		static_cast<CompilerMSL &>(*compiler->compiler).set_msl_options(options->msl);
746 		break;
747 #endif
748 
749 	default:
750 		break;
751 	}
752 
753 	return SPVC_SUCCESS;
754 }
755 
spvc_compiler_add_header_line(spvc_compiler compiler,const char * line)756 spvc_result spvc_compiler_add_header_line(spvc_compiler compiler, const char *line)
757 {
758 #if SPIRV_CROSS_C_API_GLSL
759 	if (compiler->backend == SPVC_BACKEND_NONE)
760 	{
761 		compiler->context->report_error("Cross-compilation related option used on NONE backend which only supports reflection.");
762 		return SPVC_ERROR_INVALID_ARGUMENT;
763 	}
764 
765 	static_cast<CompilerGLSL *>(compiler->compiler.get())->add_header_line(line);
766 	return SPVC_SUCCESS;
767 #else
768 	(void)line;
769 	compiler->context->report_error("Cross-compilation related option used on NONE backend which only supports reflection.");
770 	return SPVC_ERROR_INVALID_ARGUMENT;
771 #endif
772 }
773 
spvc_compiler_require_extension(spvc_compiler compiler,const char * line)774 spvc_result spvc_compiler_require_extension(spvc_compiler compiler, const char *line)
775 {
776 #if SPIRV_CROSS_C_API_GLSL
777 	if (compiler->backend == SPVC_BACKEND_NONE)
778 	{
779 		compiler->context->report_error("Cross-compilation related option used on NONE backend which only supports reflection.");
780 		return SPVC_ERROR_INVALID_ARGUMENT;
781 	}
782 
783 	static_cast<CompilerGLSL *>(compiler->compiler.get())->require_extension(line);
784 	return SPVC_SUCCESS;
785 #else
786 	(void)line;
787 	compiler->context->report_error("Cross-compilation related option used on NONE backend which only supports reflection.");
788 	return SPVC_ERROR_INVALID_ARGUMENT;
789 #endif
790 }
791 
spvc_compiler_flatten_buffer_block(spvc_compiler compiler,spvc_variable_id id)792 spvc_result spvc_compiler_flatten_buffer_block(spvc_compiler compiler, spvc_variable_id id)
793 {
794 #if SPIRV_CROSS_C_API_GLSL
795 	if (compiler->backend == SPVC_BACKEND_NONE)
796 	{
797 		compiler->context->report_error("Cross-compilation related option used on NONE backend which only supports reflection.");
798 		return SPVC_ERROR_INVALID_ARGUMENT;
799 	}
800 
801 	static_cast<CompilerGLSL *>(compiler->compiler.get())->flatten_buffer_block(id);
802 	return SPVC_SUCCESS;
803 #else
804 	(void)id;
805 	compiler->context->report_error("Cross-compilation related option used on NONE backend which only supports reflection.");
806 	return SPVC_ERROR_INVALID_ARGUMENT;
807 #endif
808 }
809 
spvc_compiler_variable_is_depth_or_compare(spvc_compiler compiler,spvc_variable_id id)810 spvc_bool spvc_compiler_variable_is_depth_or_compare(spvc_compiler compiler, spvc_variable_id id)
811 {
812 #if SPIRV_CROSS_C_API_GLSL
813 	if (compiler->backend == SPVC_BACKEND_NONE)
814 	{
815 		compiler->context->report_error("Cross-compilation related option used on NONE backend which only supports reflection.");
816 		return SPVC_ERROR_INVALID_ARGUMENT;
817 	}
818 
819 	return static_cast<CompilerGLSL *>(compiler->compiler.get())->variable_is_depth_or_compare(id) ? SPVC_TRUE : SPVC_FALSE;
820 #else
821 	(void)id;
822 	compiler->context->report_error("Cross-compilation related option used on NONE backend which only supports reflection.");
823 	return SPVC_FALSE;
824 #endif
825 }
826 
spvc_compiler_mask_stage_output_by_location(spvc_compiler compiler,unsigned location,unsigned component)827 spvc_result spvc_compiler_mask_stage_output_by_location(spvc_compiler compiler,
828                                                         unsigned location, unsigned component)
829 {
830 #if SPIRV_CROSS_C_API_GLSL
831 	if (compiler->backend == SPVC_BACKEND_NONE)
832 	{
833 		compiler->context->report_error("Cross-compilation related option used on NONE backend which only supports reflection.");
834 		return SPVC_ERROR_INVALID_ARGUMENT;
835 	}
836 
837 	static_cast<CompilerGLSL *>(compiler->compiler.get())->mask_stage_output_by_location(location, component);
838 	return SPVC_SUCCESS;
839 #else
840 	(void)location;
841 	(void)component;
842 	compiler->context->report_error("Cross-compilation related option used on NONE backend which only supports reflection.");
843 	return SPVC_ERROR_INVALID_ARGUMENT;
844 #endif
845 }
846 
spvc_compiler_mask_stage_output_by_builtin(spvc_compiler compiler,SpvBuiltIn builtin)847 spvc_result spvc_compiler_mask_stage_output_by_builtin(spvc_compiler compiler, SpvBuiltIn builtin)
848 {
849 #if SPIRV_CROSS_C_API_GLSL
850 	if (compiler->backend == SPVC_BACKEND_NONE)
851 	{
852 		compiler->context->report_error("Cross-compilation related option used on NONE backend which only supports reflection.");
853 		return SPVC_ERROR_INVALID_ARGUMENT;
854 	}
855 
856 	static_cast<CompilerGLSL *>(compiler->compiler.get())->mask_stage_output_by_builtin(spv::BuiltIn(builtin));
857 	return SPVC_SUCCESS;
858 #else
859 	(void)builtin;
860 	compiler->context->report_error("Cross-compilation related option used on NONE backend which only supports reflection.");
861 	return SPVC_ERROR_INVALID_ARGUMENT;
862 #endif
863 }
864 
spvc_compiler_hlsl_set_root_constants_layout(spvc_compiler compiler,const spvc_hlsl_root_constants * constant_info,size_t count)865 spvc_result spvc_compiler_hlsl_set_root_constants_layout(spvc_compiler compiler,
866                                                          const spvc_hlsl_root_constants *constant_info,
867                                                          size_t count)
868 {
869 #if SPIRV_CROSS_C_API_HLSL
870 	if (compiler->backend != SPVC_BACKEND_HLSL)
871 	{
872 		compiler->context->report_error("HLSL function used on a non-HLSL backend.");
873 		return SPVC_ERROR_INVALID_ARGUMENT;
874 	}
875 
876 	auto &hlsl = *static_cast<CompilerHLSL *>(compiler->compiler.get());
877 	vector<RootConstants> roots;
878 	roots.reserve(count);
879 	for (size_t i = 0; i < count; i++)
880 	{
881 		RootConstants root;
882 		root.binding = constant_info[i].binding;
883 		root.space = constant_info[i].space;
884 		root.start = constant_info[i].start;
885 		root.end = constant_info[i].end;
886 		roots.push_back(root);
887 	}
888 
889 	hlsl.set_root_constant_layouts(std::move(roots));
890 	return SPVC_SUCCESS;
891 #else
892 	(void)constant_info;
893 	(void)count;
894 	compiler->context->report_error("HLSL function used on a non-HLSL backend.");
895 	return SPVC_ERROR_INVALID_ARGUMENT;
896 #endif
897 }
898 
spvc_compiler_hlsl_add_vertex_attribute_remap(spvc_compiler compiler,const spvc_hlsl_vertex_attribute_remap * remap,size_t count)899 spvc_result spvc_compiler_hlsl_add_vertex_attribute_remap(spvc_compiler compiler,
900                                                           const spvc_hlsl_vertex_attribute_remap *remap,
901                                                           size_t count)
902 {
903 #if SPIRV_CROSS_C_API_HLSL
904 	if (compiler->backend != SPVC_BACKEND_HLSL)
905 	{
906 		compiler->context->report_error("HLSL function used on a non-HLSL backend.");
907 		return SPVC_ERROR_INVALID_ARGUMENT;
908 	}
909 
910 	HLSLVertexAttributeRemap re;
911 	auto &hlsl = *static_cast<CompilerHLSL *>(compiler->compiler.get());
912 	for (size_t i = 0; i < count; i++)
913 	{
914 		re.location = remap[i].location;
915 		re.semantic = remap[i].semantic;
916 		hlsl.add_vertex_attribute_remap(re);
917 	}
918 
919 	return SPVC_SUCCESS;
920 #else
921 	(void)remap;
922 	(void)count;
923 	compiler->context->report_error("HLSL function used on a non-HLSL backend.");
924 	return SPVC_ERROR_INVALID_ARGUMENT;
925 #endif
926 }
927 
spvc_compiler_hlsl_remap_num_workgroups_builtin(spvc_compiler compiler)928 spvc_variable_id spvc_compiler_hlsl_remap_num_workgroups_builtin(spvc_compiler compiler)
929 {
930 #if SPIRV_CROSS_C_API_HLSL
931 	if (compiler->backend != SPVC_BACKEND_HLSL)
932 	{
933 		compiler->context->report_error("HLSL function used on a non-HLSL backend.");
934 		return 0;
935 	}
936 
937 	auto &hlsl = *static_cast<CompilerHLSL *>(compiler->compiler.get());
938 	return hlsl.remap_num_workgroups_builtin();
939 #else
940 	compiler->context->report_error("HLSL function used on a non-HLSL backend.");
941 	return 0;
942 #endif
943 }
944 
spvc_compiler_hlsl_set_resource_binding_flags(spvc_compiler compiler,spvc_hlsl_binding_flags flags)945 spvc_result spvc_compiler_hlsl_set_resource_binding_flags(spvc_compiler compiler,
946                                                           spvc_hlsl_binding_flags flags)
947 {
948 #if SPIRV_CROSS_C_API_HLSL
949 	if (compiler->backend != SPVC_BACKEND_HLSL)
950 	{
951 		compiler->context->report_error("HLSL function used on a non-HLSL backend.");
952 		return SPVC_ERROR_INVALID_ARGUMENT;
953 	}
954 
955 	auto &hlsl = *static_cast<CompilerHLSL *>(compiler->compiler.get());
956 	hlsl.set_resource_binding_flags(flags);
957 	return SPVC_SUCCESS;
958 #else
959 	(void)flags;
960 	compiler->context->report_error("HLSL function used on a non-HLSL backend.");
961 	return SPVC_ERROR_INVALID_ARGUMENT;
962 #endif
963 }
964 
spvc_compiler_hlsl_add_resource_binding(spvc_compiler compiler,const spvc_hlsl_resource_binding * binding)965 spvc_result spvc_compiler_hlsl_add_resource_binding(spvc_compiler compiler,
966                                                     const spvc_hlsl_resource_binding *binding)
967 {
968 #if SPIRV_CROSS_C_API_HLSL
969 	if (compiler->backend != SPVC_BACKEND_HLSL)
970 	{
971 		compiler->context->report_error("HLSL function used on a non-HLSL backend.");
972 		return SPVC_ERROR_INVALID_ARGUMENT;
973 	}
974 
975 	auto &hlsl = *static_cast<CompilerHLSL *>(compiler->compiler.get());
976 	HLSLResourceBinding bind;
977 	bind.binding = binding->binding;
978 	bind.desc_set = binding->desc_set;
979 	bind.stage = static_cast<spv::ExecutionModel>(binding->stage);
980 	bind.cbv.register_binding = binding->cbv.register_binding;
981 	bind.cbv.register_space = binding->cbv.register_space;
982 	bind.uav.register_binding = binding->uav.register_binding;
983 	bind.uav.register_space = binding->uav.register_space;
984 	bind.srv.register_binding = binding->srv.register_binding;
985 	bind.srv.register_space = binding->srv.register_space;
986 	bind.sampler.register_binding = binding->sampler.register_binding;
987 	bind.sampler.register_space = binding->sampler.register_space;
988 	hlsl.add_hlsl_resource_binding(bind);
989 	return SPVC_SUCCESS;
990 #else
991 	(void)binding;
992 	compiler->context->report_error("HLSL function used on a non-HLSL backend.");
993 	return SPVC_ERROR_INVALID_ARGUMENT;
994 #endif
995 }
996 
spvc_compiler_hlsl_is_resource_used(spvc_compiler compiler,SpvExecutionModel model,unsigned set,unsigned binding)997 spvc_bool spvc_compiler_hlsl_is_resource_used(spvc_compiler compiler, SpvExecutionModel model, unsigned set,
998                                               unsigned binding)
999 {
1000 #if SPIRV_CROSS_C_API_HLSL
1001 	if (compiler->backend != SPVC_BACKEND_HLSL)
1002 	{
1003 		compiler->context->report_error("HLSL function used on a non-HLSL backend.");
1004 		return SPVC_FALSE;
1005 	}
1006 
1007 	auto &hlsl = *static_cast<CompilerHLSL *>(compiler->compiler.get());
1008 	return hlsl.is_hlsl_resource_binding_used(static_cast<spv::ExecutionModel>(model), set, binding) ? SPVC_TRUE :
1009 	       SPVC_FALSE;
1010 #else
1011 	(void)model;
1012 	(void)set;
1013 	(void)binding;
1014 	compiler->context->report_error("HLSL function used on a non-HLSL backend.");
1015 	return SPVC_FALSE;
1016 #endif
1017 }
1018 
spvc_compiler_msl_is_rasterization_disabled(spvc_compiler compiler)1019 spvc_bool spvc_compiler_msl_is_rasterization_disabled(spvc_compiler compiler)
1020 {
1021 #if SPIRV_CROSS_C_API_MSL
1022 	if (compiler->backend != SPVC_BACKEND_MSL)
1023 	{
1024 		compiler->context->report_error("MSL function used on a non-MSL backend.");
1025 		return SPVC_FALSE;
1026 	}
1027 
1028 	auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
1029 	return msl.get_is_rasterization_disabled() ? SPVC_TRUE : SPVC_FALSE;
1030 #else
1031 	compiler->context->report_error("MSL function used on a non-MSL backend.");
1032 	return SPVC_FALSE;
1033 #endif
1034 }
1035 
spvc_compiler_msl_needs_swizzle_buffer(spvc_compiler compiler)1036 spvc_bool spvc_compiler_msl_needs_swizzle_buffer(spvc_compiler compiler)
1037 {
1038 #if SPIRV_CROSS_C_API_MSL
1039 	if (compiler->backend != SPVC_BACKEND_MSL)
1040 	{
1041 		compiler->context->report_error("MSL function used on a non-MSL backend.");
1042 		return SPVC_FALSE;
1043 	}
1044 
1045 	auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
1046 	return msl.needs_swizzle_buffer() ? SPVC_TRUE : SPVC_FALSE;
1047 #else
1048 	compiler->context->report_error("MSL function used on a non-MSL backend.");
1049 	return SPVC_FALSE;
1050 #endif
1051 }
1052 
spvc_compiler_msl_needs_buffer_size_buffer(spvc_compiler compiler)1053 spvc_bool spvc_compiler_msl_needs_buffer_size_buffer(spvc_compiler compiler)
1054 {
1055 #if SPIRV_CROSS_C_API_MSL
1056 	if (compiler->backend != SPVC_BACKEND_MSL)
1057 	{
1058 		compiler->context->report_error("MSL function used on a non-MSL backend.");
1059 		return SPVC_FALSE;
1060 	}
1061 
1062 	auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
1063 	return msl.needs_buffer_size_buffer() ? SPVC_TRUE : SPVC_FALSE;
1064 #else
1065 	compiler->context->report_error("MSL function used on a non-MSL backend.");
1066 	return SPVC_FALSE;
1067 #endif
1068 }
1069 
spvc_compiler_msl_needs_aux_buffer(spvc_compiler compiler)1070 spvc_bool spvc_compiler_msl_needs_aux_buffer(spvc_compiler compiler)
1071 {
1072 	return spvc_compiler_msl_needs_swizzle_buffer(compiler);
1073 }
1074 
spvc_compiler_msl_needs_output_buffer(spvc_compiler compiler)1075 spvc_bool spvc_compiler_msl_needs_output_buffer(spvc_compiler compiler)
1076 {
1077 #if SPIRV_CROSS_C_API_MSL
1078 	if (compiler->backend != SPVC_BACKEND_MSL)
1079 	{
1080 		compiler->context->report_error("MSL function used on a non-MSL backend.");
1081 		return SPVC_FALSE;
1082 	}
1083 
1084 	auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
1085 	return msl.needs_output_buffer() ? SPVC_TRUE : SPVC_FALSE;
1086 #else
1087 	compiler->context->report_error("MSL function used on a non-MSL backend.");
1088 	return SPVC_FALSE;
1089 #endif
1090 }
1091 
spvc_compiler_msl_needs_patch_output_buffer(spvc_compiler compiler)1092 spvc_bool spvc_compiler_msl_needs_patch_output_buffer(spvc_compiler compiler)
1093 {
1094 #if SPIRV_CROSS_C_API_MSL
1095 	if (compiler->backend != SPVC_BACKEND_MSL)
1096 	{
1097 		compiler->context->report_error("MSL function used on a non-MSL backend.");
1098 		return SPVC_FALSE;
1099 	}
1100 
1101 	auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
1102 	return msl.needs_patch_output_buffer() ? SPVC_TRUE : SPVC_FALSE;
1103 #else
1104 	compiler->context->report_error("MSL function used on a non-MSL backend.");
1105 	return SPVC_FALSE;
1106 #endif
1107 }
1108 
spvc_compiler_msl_needs_input_threadgroup_mem(spvc_compiler compiler)1109 spvc_bool spvc_compiler_msl_needs_input_threadgroup_mem(spvc_compiler compiler)
1110 {
1111 #if SPIRV_CROSS_C_API_MSL
1112 	if (compiler->backend != SPVC_BACKEND_MSL)
1113 	{
1114 		compiler->context->report_error("MSL function used on a non-MSL backend.");
1115 		return SPVC_FALSE;
1116 	}
1117 
1118 	auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
1119 	return msl.needs_input_threadgroup_mem() ? SPVC_TRUE : SPVC_FALSE;
1120 #else
1121 	compiler->context->report_error("MSL function used on a non-MSL backend.");
1122 	return SPVC_FALSE;
1123 #endif
1124 }
1125 
spvc_compiler_msl_add_vertex_attribute(spvc_compiler compiler,const spvc_msl_vertex_attribute * va)1126 spvc_result spvc_compiler_msl_add_vertex_attribute(spvc_compiler compiler, const spvc_msl_vertex_attribute *va)
1127 {
1128 #if SPIRV_CROSS_C_API_MSL
1129 	if (compiler->backend != SPVC_BACKEND_MSL)
1130 	{
1131 		compiler->context->report_error("MSL function used on a non-MSL backend.");
1132 		return SPVC_ERROR_INVALID_ARGUMENT;
1133 	}
1134 
1135 	auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
1136 	MSLShaderInput attr;
1137 	attr.location = va->location;
1138 	attr.format = static_cast<MSLShaderInputFormat>(va->format);
1139 	attr.builtin = static_cast<spv::BuiltIn>(va->builtin);
1140 	msl.add_msl_shader_input(attr);
1141 	return SPVC_SUCCESS;
1142 #else
1143 	(void)va;
1144 	compiler->context->report_error("MSL function used on a non-MSL backend.");
1145 	return SPVC_ERROR_INVALID_ARGUMENT;
1146 #endif
1147 }
1148 
spvc_compiler_msl_add_shader_input(spvc_compiler compiler,const spvc_msl_shader_input * si)1149 spvc_result spvc_compiler_msl_add_shader_input(spvc_compiler compiler, const spvc_msl_shader_input *si)
1150 {
1151 #if SPIRV_CROSS_C_API_MSL
1152 	if (compiler->backend != SPVC_BACKEND_MSL)
1153 	{
1154 		compiler->context->report_error("MSL function used on a non-MSL backend.");
1155 		return SPVC_ERROR_INVALID_ARGUMENT;
1156 	}
1157 
1158 	auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
1159 	MSLShaderInput input;
1160 	input.location = si->location;
1161 	input.format = static_cast<MSLShaderInputFormat>(si->format);
1162 	input.builtin = static_cast<spv::BuiltIn>(si->builtin);
1163 	input.vecsize = si->vecsize;
1164 	msl.add_msl_shader_input(input);
1165 	return SPVC_SUCCESS;
1166 #else
1167 	(void)si;
1168 	compiler->context->report_error("MSL function used on a non-MSL backend.");
1169 	return SPVC_ERROR_INVALID_ARGUMENT;
1170 #endif
1171 }
1172 
spvc_compiler_msl_add_resource_binding(spvc_compiler compiler,const spvc_msl_resource_binding * binding)1173 spvc_result spvc_compiler_msl_add_resource_binding(spvc_compiler compiler,
1174                                                    const spvc_msl_resource_binding *binding)
1175 {
1176 #if SPIRV_CROSS_C_API_MSL
1177 	if (compiler->backend != SPVC_BACKEND_MSL)
1178 	{
1179 		compiler->context->report_error("MSL function used on a non-MSL backend.");
1180 		return SPVC_ERROR_INVALID_ARGUMENT;
1181 	}
1182 
1183 	auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
1184 	MSLResourceBinding bind;
1185 	bind.binding = binding->binding;
1186 	bind.desc_set = binding->desc_set;
1187 	bind.stage = static_cast<spv::ExecutionModel>(binding->stage);
1188 	bind.msl_buffer = binding->msl_buffer;
1189 	bind.msl_texture = binding->msl_texture;
1190 	bind.msl_sampler = binding->msl_sampler;
1191 	msl.add_msl_resource_binding(bind);
1192 	return SPVC_SUCCESS;
1193 #else
1194 	(void)binding;
1195 	compiler->context->report_error("MSL function used on a non-MSL backend.");
1196 	return SPVC_ERROR_INVALID_ARGUMENT;
1197 #endif
1198 }
1199 
spvc_compiler_msl_add_dynamic_buffer(spvc_compiler compiler,unsigned desc_set,unsigned binding,unsigned index)1200 spvc_result spvc_compiler_msl_add_dynamic_buffer(spvc_compiler compiler, unsigned desc_set, unsigned binding, unsigned index)
1201 {
1202 #if SPIRV_CROSS_C_API_MSL
1203 	if (compiler->backend != SPVC_BACKEND_MSL)
1204 	{
1205 		compiler->context->report_error("MSL function used on a non-MSL backend.");
1206 		return SPVC_ERROR_INVALID_ARGUMENT;
1207 	}
1208 
1209 	auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
1210 	msl.add_dynamic_buffer(desc_set, binding, index);
1211 	return SPVC_SUCCESS;
1212 #else
1213 	(void)binding;
1214 	(void)desc_set;
1215 	(void)index;
1216 	compiler->context->report_error("MSL function used on a non-MSL backend.");
1217 	return SPVC_ERROR_INVALID_ARGUMENT;
1218 #endif
1219 }
1220 
spvc_compiler_msl_add_inline_uniform_block(spvc_compiler compiler,unsigned desc_set,unsigned binding)1221 spvc_result spvc_compiler_msl_add_inline_uniform_block(spvc_compiler compiler, unsigned desc_set, unsigned binding)
1222 {
1223 #if SPIRV_CROSS_C_API_MSL
1224 	if (compiler->backend != SPVC_BACKEND_MSL)
1225 	{
1226 		compiler->context->report_error("MSL function used on a non-MSL backend.");
1227 		return SPVC_ERROR_INVALID_ARGUMENT;
1228 	}
1229 
1230 	auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
1231 	msl.add_inline_uniform_block(desc_set, binding);
1232 	return SPVC_SUCCESS;
1233 #else
1234 	(void)binding;
1235 	(void)desc_set;
1236 	compiler->context->report_error("MSL function used on a non-MSL backend.");
1237 	return SPVC_ERROR_INVALID_ARGUMENT;
1238 #endif
1239 }
1240 
spvc_compiler_msl_add_discrete_descriptor_set(spvc_compiler compiler,unsigned desc_set)1241 spvc_result spvc_compiler_msl_add_discrete_descriptor_set(spvc_compiler compiler, unsigned desc_set)
1242 {
1243 #if SPIRV_CROSS_C_API_MSL
1244 	if (compiler->backend != SPVC_BACKEND_MSL)
1245 	{
1246 		compiler->context->report_error("MSL function used on a non-MSL backend.");
1247 		return SPVC_ERROR_INVALID_ARGUMENT;
1248 	}
1249 
1250 	auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
1251 	msl.add_discrete_descriptor_set(desc_set);
1252 	return SPVC_SUCCESS;
1253 #else
1254 	(void)desc_set;
1255 	compiler->context->report_error("MSL function used on a non-MSL backend.");
1256 	return SPVC_ERROR_INVALID_ARGUMENT;
1257 #endif
1258 }
1259 
spvc_compiler_msl_set_argument_buffer_device_address_space(spvc_compiler compiler,unsigned desc_set,spvc_bool device_address)1260 spvc_result spvc_compiler_msl_set_argument_buffer_device_address_space(spvc_compiler compiler, unsigned desc_set, spvc_bool device_address)
1261 {
1262 #if SPIRV_CROSS_C_API_MSL
1263 	if (compiler->backend != SPVC_BACKEND_MSL)
1264 	{
1265 		compiler->context->report_error("MSL function used on a non-MSL backend.");
1266 		return SPVC_ERROR_INVALID_ARGUMENT;
1267 	}
1268 
1269 	auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
1270 	msl.set_argument_buffer_device_address_space(desc_set, bool(device_address));
1271 	return SPVC_SUCCESS;
1272 #else
1273 	(void)desc_set;
1274 	(void)device_address;
1275 	compiler->context->report_error("MSL function used on a non-MSL backend.");
1276 	return SPVC_ERROR_INVALID_ARGUMENT;
1277 #endif
1278 }
1279 
spvc_compiler_msl_is_shader_input_used(spvc_compiler compiler,unsigned location)1280 spvc_bool spvc_compiler_msl_is_shader_input_used(spvc_compiler compiler, unsigned location)
1281 {
1282 #if SPIRV_CROSS_C_API_MSL
1283 	if (compiler->backend != SPVC_BACKEND_MSL)
1284 	{
1285 		compiler->context->report_error("MSL function used on a non-MSL backend.");
1286 		return SPVC_FALSE;
1287 	}
1288 
1289 	auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
1290 	return msl.is_msl_shader_input_used(location) ? SPVC_TRUE : SPVC_FALSE;
1291 #else
1292 	(void)location;
1293 	compiler->context->report_error("MSL function used on a non-MSL backend.");
1294 	return SPVC_FALSE;
1295 #endif
1296 }
1297 
spvc_compiler_msl_is_vertex_attribute_used(spvc_compiler compiler,unsigned location)1298 spvc_bool spvc_compiler_msl_is_vertex_attribute_used(spvc_compiler compiler, unsigned location)
1299 {
1300 	return spvc_compiler_msl_is_shader_input_used(compiler, location);
1301 }
1302 
spvc_compiler_msl_is_resource_used(spvc_compiler compiler,SpvExecutionModel model,unsigned set,unsigned binding)1303 spvc_bool spvc_compiler_msl_is_resource_used(spvc_compiler compiler, SpvExecutionModel model, unsigned set,
1304                                              unsigned binding)
1305 {
1306 #if SPIRV_CROSS_C_API_MSL
1307 	if (compiler->backend != SPVC_BACKEND_MSL)
1308 	{
1309 		compiler->context->report_error("MSL function used on a non-MSL backend.");
1310 		return SPVC_FALSE;
1311 	}
1312 
1313 	auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
1314 	return msl.is_msl_resource_binding_used(static_cast<spv::ExecutionModel>(model), set, binding) ? SPVC_TRUE :
1315 	                                                                                                 SPVC_FALSE;
1316 #else
1317 	(void)model;
1318 	(void)set;
1319 	(void)binding;
1320 	compiler->context->report_error("MSL function used on a non-MSL backend.");
1321 	return SPVC_FALSE;
1322 #endif
1323 }
1324 
spvc_compiler_msl_set_combined_sampler_suffix(spvc_compiler compiler,const char * suffix)1325 spvc_result spvc_compiler_msl_set_combined_sampler_suffix(spvc_compiler compiler, const char *suffix)
1326 {
1327 #if SPIRV_CROSS_C_API_MSL
1328 	if (compiler->backend != SPVC_BACKEND_MSL)
1329 	{
1330 		compiler->context->report_error("MSL function used on a non-MSL backend.");
1331 		return SPVC_ERROR_INVALID_ARGUMENT;
1332 	}
1333 
1334 	auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
1335 	msl.set_combined_sampler_suffix(suffix);
1336 	return SPVC_SUCCESS;
1337 #else
1338 	(void)suffix;
1339 	compiler->context->report_error("MSL function used on a non-MSL backend.");
1340 	return SPVC_ERROR_INVALID_ARGUMENT;
1341 #endif
1342 }
1343 
spvc_compiler_msl_get_combined_sampler_suffix(spvc_compiler compiler)1344 const char *spvc_compiler_msl_get_combined_sampler_suffix(spvc_compiler compiler)
1345 {
1346 #if SPIRV_CROSS_C_API_MSL
1347 	if (compiler->backend != SPVC_BACKEND_MSL)
1348 	{
1349 		compiler->context->report_error("MSL function used on a non-MSL backend.");
1350 		return "";
1351 	}
1352 
1353 	auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
1354 	return msl.get_combined_sampler_suffix();
1355 #else
1356 	compiler->context->report_error("MSL function used on a non-MSL backend.");
1357 	return "";
1358 #endif
1359 }
1360 
1361 #if SPIRV_CROSS_C_API_MSL
spvc_convert_msl_sampler(MSLConstexprSampler & samp,const spvc_msl_constexpr_sampler * sampler)1362 static void spvc_convert_msl_sampler(MSLConstexprSampler &samp, const spvc_msl_constexpr_sampler *sampler)
1363 {
1364 	samp.s_address = static_cast<MSLSamplerAddress>(sampler->s_address);
1365 	samp.t_address = static_cast<MSLSamplerAddress>(sampler->t_address);
1366 	samp.r_address = static_cast<MSLSamplerAddress>(sampler->r_address);
1367 	samp.lod_clamp_min = sampler->lod_clamp_min;
1368 	samp.lod_clamp_max = sampler->lod_clamp_max;
1369 	samp.lod_clamp_enable = sampler->lod_clamp_enable != 0;
1370 	samp.min_filter = static_cast<MSLSamplerFilter>(sampler->min_filter);
1371 	samp.mag_filter = static_cast<MSLSamplerFilter>(sampler->mag_filter);
1372 	samp.mip_filter = static_cast<MSLSamplerMipFilter>(sampler->mip_filter);
1373 	samp.compare_enable = sampler->compare_enable != 0;
1374 	samp.anisotropy_enable = sampler->anisotropy_enable != 0;
1375 	samp.max_anisotropy = sampler->max_anisotropy;
1376 	samp.compare_func = static_cast<MSLSamplerCompareFunc>(sampler->compare_func);
1377 	samp.coord = static_cast<MSLSamplerCoord>(sampler->coord);
1378 	samp.border_color = static_cast<MSLSamplerBorderColor>(sampler->border_color);
1379 }
1380 
spvc_convert_msl_sampler_ycbcr_conversion(MSLConstexprSampler & samp,const spvc_msl_sampler_ycbcr_conversion * conv)1381 static void spvc_convert_msl_sampler_ycbcr_conversion(MSLConstexprSampler &samp, const spvc_msl_sampler_ycbcr_conversion *conv)
1382 {
1383 	samp.ycbcr_conversion_enable = conv != nullptr;
1384 	if (conv == nullptr) return;
1385 	samp.planes = conv->planes;
1386 	samp.resolution = static_cast<MSLFormatResolution>(conv->resolution);
1387 	samp.chroma_filter = static_cast<MSLSamplerFilter>(conv->chroma_filter);
1388 	samp.x_chroma_offset = static_cast<MSLChromaLocation>(conv->x_chroma_offset);
1389 	samp.y_chroma_offset = static_cast<MSLChromaLocation>(conv->y_chroma_offset);
1390 	for (int i = 0; i < 4; i++)
1391 		samp.swizzle[i] = static_cast<MSLComponentSwizzle>(conv->swizzle[i]);
1392 	samp.ycbcr_model = static_cast<MSLSamplerYCbCrModelConversion>(conv->ycbcr_model);
1393 	samp.ycbcr_range = static_cast<MSLSamplerYCbCrRange>(conv->ycbcr_range);
1394 	samp.bpc = conv->bpc;
1395 }
1396 #endif
1397 
spvc_compiler_msl_remap_constexpr_sampler(spvc_compiler compiler,spvc_variable_id id,const spvc_msl_constexpr_sampler * sampler)1398 spvc_result spvc_compiler_msl_remap_constexpr_sampler(spvc_compiler compiler, spvc_variable_id id,
1399                                                       const spvc_msl_constexpr_sampler *sampler)
1400 {
1401 #if SPIRV_CROSS_C_API_MSL
1402 	if (compiler->backend != SPVC_BACKEND_MSL)
1403 	{
1404 		compiler->context->report_error("MSL function used on a non-MSL backend.");
1405 		return SPVC_ERROR_INVALID_ARGUMENT;
1406 	}
1407 
1408 	auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
1409 	MSLConstexprSampler samp;
1410 	spvc_convert_msl_sampler(samp, sampler);
1411 	msl.remap_constexpr_sampler(id, samp);
1412 	return SPVC_SUCCESS;
1413 #else
1414 	(void)id;
1415 	(void)sampler;
1416 	compiler->context->report_error("MSL function used on a non-MSL backend.");
1417 	return SPVC_ERROR_INVALID_ARGUMENT;
1418 #endif
1419 }
1420 
spvc_compiler_msl_remap_constexpr_sampler_by_binding(spvc_compiler compiler,unsigned desc_set,unsigned binding,const spvc_msl_constexpr_sampler * sampler)1421 spvc_result spvc_compiler_msl_remap_constexpr_sampler_by_binding(spvc_compiler compiler,
1422                                                                  unsigned desc_set, unsigned binding,
1423                                                                  const spvc_msl_constexpr_sampler *sampler)
1424 {
1425 #if SPIRV_CROSS_C_API_MSL
1426 	if (compiler->backend != SPVC_BACKEND_MSL)
1427 	{
1428 		compiler->context->report_error("MSL function used on a non-MSL backend.");
1429 		return SPVC_ERROR_INVALID_ARGUMENT;
1430 	}
1431 
1432 	auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
1433 	MSLConstexprSampler samp;
1434 	spvc_convert_msl_sampler(samp, sampler);
1435 	msl.remap_constexpr_sampler_by_binding(desc_set, binding, samp);
1436 	return SPVC_SUCCESS;
1437 #else
1438 	(void)desc_set;
1439 	(void)binding;
1440 	(void)sampler;
1441 	compiler->context->report_error("MSL function used on a non-MSL backend.");
1442 	return SPVC_ERROR_INVALID_ARGUMENT;
1443 #endif
1444 }
1445 
spvc_compiler_msl_remap_constexpr_sampler_ycbcr(spvc_compiler compiler,spvc_variable_id id,const spvc_msl_constexpr_sampler * sampler,const spvc_msl_sampler_ycbcr_conversion * conv)1446 spvc_result spvc_compiler_msl_remap_constexpr_sampler_ycbcr(spvc_compiler compiler, spvc_variable_id id,
1447                                                             const spvc_msl_constexpr_sampler *sampler,
1448                                                             const spvc_msl_sampler_ycbcr_conversion *conv)
1449 {
1450 #if SPIRV_CROSS_C_API_MSL
1451 	if (compiler->backend != SPVC_BACKEND_MSL)
1452 	{
1453 		compiler->context->report_error("MSL function used on a non-MSL backend.");
1454 		return SPVC_ERROR_INVALID_ARGUMENT;
1455 	}
1456 
1457 	auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
1458 	MSLConstexprSampler samp;
1459 	spvc_convert_msl_sampler(samp, sampler);
1460 	spvc_convert_msl_sampler_ycbcr_conversion(samp, conv);
1461 	msl.remap_constexpr_sampler(id, samp);
1462 	return SPVC_SUCCESS;
1463 #else
1464 	(void)id;
1465 	(void)sampler;
1466 	(void)conv;
1467 	compiler->context->report_error("MSL function used on a non-MSL backend.");
1468 	return SPVC_ERROR_INVALID_ARGUMENT;
1469 #endif
1470 }
1471 
spvc_compiler_msl_remap_constexpr_sampler_by_binding_ycbcr(spvc_compiler compiler,unsigned desc_set,unsigned binding,const spvc_msl_constexpr_sampler * sampler,const spvc_msl_sampler_ycbcr_conversion * conv)1472 spvc_result spvc_compiler_msl_remap_constexpr_sampler_by_binding_ycbcr(spvc_compiler compiler,
1473                                                                        unsigned desc_set, unsigned binding,
1474                                                                        const spvc_msl_constexpr_sampler *sampler,
1475                                                                        const spvc_msl_sampler_ycbcr_conversion *conv)
1476 {
1477 #if SPIRV_CROSS_C_API_MSL
1478 	if (compiler->backend != SPVC_BACKEND_MSL)
1479 	{
1480 		compiler->context->report_error("MSL function used on a non-MSL backend.");
1481 		return SPVC_ERROR_INVALID_ARGUMENT;
1482 	}
1483 
1484 	auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
1485 	MSLConstexprSampler samp;
1486 	spvc_convert_msl_sampler(samp, sampler);
1487 	spvc_convert_msl_sampler_ycbcr_conversion(samp, conv);
1488 	msl.remap_constexpr_sampler_by_binding(desc_set, binding, samp);
1489 	return SPVC_SUCCESS;
1490 #else
1491 	(void)desc_set;
1492 	(void)binding;
1493 	(void)sampler;
1494 	(void)conv;
1495 	compiler->context->report_error("MSL function used on a non-MSL backend.");
1496 	return SPVC_ERROR_INVALID_ARGUMENT;
1497 #endif
1498 }
1499 
spvc_compiler_msl_set_fragment_output_components(spvc_compiler compiler,unsigned location,unsigned components)1500 spvc_result spvc_compiler_msl_set_fragment_output_components(spvc_compiler compiler, unsigned location,
1501                                                              unsigned components)
1502 {
1503 #if SPIRV_CROSS_C_API_MSL
1504 	if (compiler->backend != SPVC_BACKEND_MSL)
1505 	{
1506 		compiler->context->report_error("MSL function used on a non-MSL backend.");
1507 		return SPVC_ERROR_INVALID_ARGUMENT;
1508 	}
1509 
1510 	auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
1511 	msl.set_fragment_output_components(location, components);
1512 	return SPVC_SUCCESS;
1513 #else
1514 	(void)location;
1515 	(void)components;
1516 	compiler->context->report_error("MSL function used on a non-MSL backend.");
1517 	return SPVC_ERROR_INVALID_ARGUMENT;
1518 #endif
1519 }
1520 
spvc_compiler_msl_get_automatic_resource_binding(spvc_compiler compiler,spvc_variable_id id)1521 unsigned spvc_compiler_msl_get_automatic_resource_binding(spvc_compiler compiler, spvc_variable_id id)
1522 {
1523 #if SPIRV_CROSS_C_API_MSL
1524 	if (compiler->backend != SPVC_BACKEND_MSL)
1525 	{
1526 		compiler->context->report_error("MSL function used on a non-MSL backend.");
1527 		return uint32_t(-1);
1528 	}
1529 
1530 	auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
1531 	return msl.get_automatic_msl_resource_binding(id);
1532 #else
1533 	(void)id;
1534 	compiler->context->report_error("MSL function used on a non-MSL backend.");
1535 	return uint32_t(-1);
1536 #endif
1537 }
1538 
spvc_compiler_msl_get_automatic_resource_binding_secondary(spvc_compiler compiler,spvc_variable_id id)1539 unsigned spvc_compiler_msl_get_automatic_resource_binding_secondary(spvc_compiler compiler, spvc_variable_id id)
1540 {
1541 #if SPIRV_CROSS_C_API_MSL
1542 	if (compiler->backend != SPVC_BACKEND_MSL)
1543 	{
1544 		compiler->context->report_error("MSL function used on a non-MSL backend.");
1545 		return uint32_t(-1);
1546 	}
1547 
1548 	auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
1549 	return msl.get_automatic_msl_resource_binding_secondary(id);
1550 #else
1551 	(void)id;
1552 	compiler->context->report_error("MSL function used on a non-MSL backend.");
1553 	return uint32_t(-1);
1554 #endif
1555 }
1556 
spvc_compiler_compile(spvc_compiler compiler,const char ** source)1557 spvc_result spvc_compiler_compile(spvc_compiler compiler, const char **source)
1558 {
1559 	SPVC_BEGIN_SAFE_SCOPE
1560 	{
1561 		auto result = compiler->compiler->compile();
1562 		if (result.empty())
1563 		{
1564 			compiler->context->report_error("Unsupported SPIR-V.");
1565 			return SPVC_ERROR_UNSUPPORTED_SPIRV;
1566 		}
1567 
1568 		*source = compiler->context->allocate_name(result);
1569 		if (!*source)
1570 		{
1571 			compiler->context->report_error("Out of memory.");
1572 			return SPVC_ERROR_OUT_OF_MEMORY;
1573 		}
1574 		return SPVC_SUCCESS;
1575 	}
1576 	SPVC_END_SAFE_SCOPE(compiler->context, SPVC_ERROR_UNSUPPORTED_SPIRV)
1577 }
1578 
copy_resources(SmallVector<spvc_reflected_resource> & outputs,const SmallVector<Resource> & inputs)1579 bool spvc_resources_s::copy_resources(SmallVector<spvc_reflected_resource> &outputs,
1580                                       const SmallVector<Resource> &inputs)
1581 {
1582 	for (auto &i : inputs)
1583 	{
1584 		spvc_reflected_resource r;
1585 		r.base_type_id = i.base_type_id;
1586 		r.type_id = i.type_id;
1587 		r.id = i.id;
1588 		r.name = context->allocate_name(i.name);
1589 		if (!r.name)
1590 			return false;
1591 
1592 		outputs.push_back(r);
1593 	}
1594 
1595 	return true;
1596 }
1597 
copy_resources(SmallVector<spvc_reflected_builtin_resource> & outputs,const SmallVector<BuiltInResource> & inputs)1598 bool spvc_resources_s::copy_resources(SmallVector<spvc_reflected_builtin_resource> &outputs,
1599                                       const SmallVector<BuiltInResource> &inputs)
1600 {
1601 	for (auto &i : inputs)
1602 	{
1603 		spvc_reflected_builtin_resource br;
1604 
1605 		br.value_type_id = i.value_type_id;
1606 		br.builtin = SpvBuiltIn(i.builtin);
1607 
1608 		auto &r = br.resource;
1609 		r.base_type_id = i.resource.base_type_id;
1610 		r.type_id = i.resource.type_id;
1611 		r.id = i.resource.id;
1612 		r.name = context->allocate_name(i.resource.name);
1613 		if (!r.name)
1614 			return false;
1615 
1616 		outputs.push_back(br);
1617 	}
1618 
1619 	return true;
1620 }
1621 
copy_resources(const ShaderResources & resources)1622 bool spvc_resources_s::copy_resources(const ShaderResources &resources)
1623 {
1624 	if (!copy_resources(uniform_buffers, resources.uniform_buffers))
1625 		return false;
1626 	if (!copy_resources(storage_buffers, resources.storage_buffers))
1627 		return false;
1628 	if (!copy_resources(stage_inputs, resources.stage_inputs))
1629 		return false;
1630 	if (!copy_resources(stage_outputs, resources.stage_outputs))
1631 		return false;
1632 	if (!copy_resources(subpass_inputs, resources.subpass_inputs))
1633 		return false;
1634 	if (!copy_resources(storage_images, resources.storage_images))
1635 		return false;
1636 	if (!copy_resources(sampled_images, resources.sampled_images))
1637 		return false;
1638 	if (!copy_resources(atomic_counters, resources.atomic_counters))
1639 		return false;
1640 	if (!copy_resources(push_constant_buffers, resources.push_constant_buffers))
1641 		return false;
1642 	if (!copy_resources(separate_images, resources.separate_images))
1643 		return false;
1644 	if (!copy_resources(separate_samplers, resources.separate_samplers))
1645 		return false;
1646 	if (!copy_resources(acceleration_structures, resources.acceleration_structures))
1647 		return false;
1648 	if (!copy_resources(builtin_inputs, resources.builtin_inputs))
1649 		return false;
1650 	if (!copy_resources(builtin_outputs, resources.builtin_outputs))
1651 		return false;
1652 
1653 	return true;
1654 }
1655 
spvc_compiler_get_active_interface_variables(spvc_compiler compiler,spvc_set * set)1656 spvc_result spvc_compiler_get_active_interface_variables(spvc_compiler compiler, spvc_set *set)
1657 {
1658 	SPVC_BEGIN_SAFE_SCOPE
1659 	{
1660 		std::unique_ptr<spvc_set_s> ptr(new (std::nothrow) spvc_set_s);
1661 		if (!ptr)
1662 		{
1663 			compiler->context->report_error("Out of memory.");
1664 			return SPVC_ERROR_OUT_OF_MEMORY;
1665 		}
1666 
1667 		auto active = compiler->compiler->get_active_interface_variables();
1668 		ptr->set = std::move(active);
1669 		*set = ptr.get();
1670 		compiler->context->allocations.push_back(std::move(ptr));
1671 	}
1672 	SPVC_END_SAFE_SCOPE(compiler->context, SPVC_ERROR_INVALID_ARGUMENT)
1673 	return SPVC_SUCCESS;
1674 }
1675 
spvc_compiler_set_enabled_interface_variables(spvc_compiler compiler,spvc_set set)1676 spvc_result spvc_compiler_set_enabled_interface_variables(spvc_compiler compiler, spvc_set set)
1677 {
1678 	SPVC_BEGIN_SAFE_SCOPE
1679 	{
1680 		compiler->compiler->set_enabled_interface_variables(set->set);
1681 	}
1682 	SPVC_END_SAFE_SCOPE(compiler->context, SPVC_ERROR_INVALID_ARGUMENT)
1683 	return SPVC_SUCCESS;
1684 }
1685 
spvc_compiler_create_shader_resources_for_active_variables(spvc_compiler compiler,spvc_resources * resources,spvc_set set)1686 spvc_result spvc_compiler_create_shader_resources_for_active_variables(spvc_compiler compiler, spvc_resources *resources,
1687                                                                        spvc_set set)
1688 {
1689 	SPVC_BEGIN_SAFE_SCOPE
1690 	{
1691 		std::unique_ptr<spvc_resources_s> res(new (std::nothrow) spvc_resources_s);
1692 		if (!res)
1693 		{
1694 			compiler->context->report_error("Out of memory.");
1695 			return SPVC_ERROR_OUT_OF_MEMORY;
1696 		}
1697 
1698 		res->context = compiler->context;
1699 		auto accessed_resources = compiler->compiler->get_shader_resources(set->set);
1700 
1701 		if (!res->copy_resources(accessed_resources))
1702 		{
1703 			res->context->report_error("Out of memory.");
1704 			return SPVC_ERROR_OUT_OF_MEMORY;
1705 		}
1706 		*resources = res.get();
1707 		compiler->context->allocations.push_back(std::move(res));
1708 	}
1709 	SPVC_END_SAFE_SCOPE(compiler->context, SPVC_ERROR_OUT_OF_MEMORY)
1710 	return SPVC_SUCCESS;
1711 }
1712 
spvc_compiler_create_shader_resources(spvc_compiler compiler,spvc_resources * resources)1713 spvc_result spvc_compiler_create_shader_resources(spvc_compiler compiler, spvc_resources *resources)
1714 {
1715 	SPVC_BEGIN_SAFE_SCOPE
1716 	{
1717 		std::unique_ptr<spvc_resources_s> res(new (std::nothrow) spvc_resources_s);
1718 		if (!res)
1719 		{
1720 			compiler->context->report_error("Out of memory.");
1721 			return SPVC_ERROR_OUT_OF_MEMORY;
1722 		}
1723 
1724 		res->context = compiler->context;
1725 		auto accessed_resources = compiler->compiler->get_shader_resources();
1726 
1727 		if (!res->copy_resources(accessed_resources))
1728 		{
1729 			res->context->report_error("Out of memory.");
1730 			return SPVC_ERROR_OUT_OF_MEMORY;
1731 		}
1732 
1733 		*resources = res.get();
1734 		compiler->context->allocations.push_back(std::move(res));
1735 	}
1736 	SPVC_END_SAFE_SCOPE(compiler->context, SPVC_ERROR_OUT_OF_MEMORY)
1737 	return SPVC_SUCCESS;
1738 }
1739 
spvc_resources_get_resource_list_for_type(spvc_resources resources,spvc_resource_type type,const spvc_reflected_resource ** resource_list,size_t * resource_size)1740 spvc_result spvc_resources_get_resource_list_for_type(spvc_resources resources, spvc_resource_type type,
1741                                                       const spvc_reflected_resource **resource_list,
1742                                                       size_t *resource_size)
1743 {
1744 	const SmallVector<spvc_reflected_resource> *list = nullptr;
1745 	switch (type)
1746 	{
1747 	case SPVC_RESOURCE_TYPE_UNIFORM_BUFFER:
1748 		list = &resources->uniform_buffers;
1749 		break;
1750 
1751 	case SPVC_RESOURCE_TYPE_STORAGE_BUFFER:
1752 		list = &resources->storage_buffers;
1753 		break;
1754 
1755 	case SPVC_RESOURCE_TYPE_STAGE_INPUT:
1756 		list = &resources->stage_inputs;
1757 		break;
1758 
1759 	case SPVC_RESOURCE_TYPE_STAGE_OUTPUT:
1760 		list = &resources->stage_outputs;
1761 		break;
1762 
1763 	case SPVC_RESOURCE_TYPE_SUBPASS_INPUT:
1764 		list = &resources->subpass_inputs;
1765 		break;
1766 
1767 	case SPVC_RESOURCE_TYPE_STORAGE_IMAGE:
1768 		list = &resources->storage_images;
1769 		break;
1770 
1771 	case SPVC_RESOURCE_TYPE_SAMPLED_IMAGE:
1772 		list = &resources->sampled_images;
1773 		break;
1774 
1775 	case SPVC_RESOURCE_TYPE_ATOMIC_COUNTER:
1776 		list = &resources->atomic_counters;
1777 		break;
1778 
1779 	case SPVC_RESOURCE_TYPE_PUSH_CONSTANT:
1780 		list = &resources->push_constant_buffers;
1781 		break;
1782 
1783 	case SPVC_RESOURCE_TYPE_SEPARATE_IMAGE:
1784 		list = &resources->separate_images;
1785 		break;
1786 
1787 	case SPVC_RESOURCE_TYPE_SEPARATE_SAMPLERS:
1788 		list = &resources->separate_samplers;
1789 		break;
1790 
1791 	case SPVC_RESOURCE_TYPE_ACCELERATION_STRUCTURE:
1792 		list = &resources->acceleration_structures;
1793 		break;
1794 
1795 	default:
1796 		break;
1797 	}
1798 
1799 	if (!list)
1800 	{
1801 		resources->context->report_error("Invalid argument.");
1802 		return SPVC_ERROR_INVALID_ARGUMENT;
1803 	}
1804 
1805 	*resource_size = list->size();
1806 	*resource_list = list->data();
1807 	return SPVC_SUCCESS;
1808 }
1809 
spvc_resources_get_builtin_resource_list_for_type(spvc_resources resources,spvc_builtin_resource_type type,const spvc_reflected_builtin_resource ** resource_list,size_t * resource_size)1810 spvc_result spvc_resources_get_builtin_resource_list_for_type(
1811 		spvc_resources resources, spvc_builtin_resource_type type,
1812 		const spvc_reflected_builtin_resource **resource_list,
1813 		size_t *resource_size)
1814 {
1815 	const SmallVector<spvc_reflected_builtin_resource> *list = nullptr;
1816 	switch (type)
1817 	{
1818 	case SPVC_BUILTIN_RESOURCE_TYPE_STAGE_INPUT:
1819 		list = &resources->builtin_inputs;
1820 		break;
1821 
1822 	case SPVC_BUILTIN_RESOURCE_TYPE_STAGE_OUTPUT:
1823 		list = &resources->builtin_outputs;
1824 		break;
1825 
1826 	default:
1827 		break;
1828 	}
1829 
1830 	if (!list)
1831 	{
1832 		resources->context->report_error("Invalid argument.");
1833 		return SPVC_ERROR_INVALID_ARGUMENT;
1834 	}
1835 
1836 	*resource_size = list->size();
1837 	*resource_list = list->data();
1838 	return SPVC_SUCCESS;
1839 }
1840 
spvc_compiler_set_decoration(spvc_compiler compiler,SpvId id,SpvDecoration decoration,unsigned argument)1841 void spvc_compiler_set_decoration(spvc_compiler compiler, SpvId id, SpvDecoration decoration, unsigned argument)
1842 {
1843 	compiler->compiler->set_decoration(id, static_cast<spv::Decoration>(decoration), argument);
1844 }
1845 
spvc_compiler_set_decoration_string(spvc_compiler compiler,SpvId id,SpvDecoration decoration,const char * argument)1846 void spvc_compiler_set_decoration_string(spvc_compiler compiler, SpvId id, SpvDecoration decoration,
1847                                          const char *argument)
1848 {
1849 	compiler->compiler->set_decoration_string(id, static_cast<spv::Decoration>(decoration), argument);
1850 }
1851 
spvc_compiler_set_name(spvc_compiler compiler,SpvId id,const char * argument)1852 void spvc_compiler_set_name(spvc_compiler compiler, SpvId id, const char *argument)
1853 {
1854 	compiler->compiler->set_name(id, argument);
1855 }
1856 
spvc_compiler_set_member_decoration(spvc_compiler compiler,spvc_type_id id,unsigned member_index,SpvDecoration decoration,unsigned argument)1857 void spvc_compiler_set_member_decoration(spvc_compiler compiler, spvc_type_id id, unsigned member_index,
1858                                          SpvDecoration decoration, unsigned argument)
1859 {
1860 	compiler->compiler->set_member_decoration(id, member_index, static_cast<spv::Decoration>(decoration), argument);
1861 }
1862 
spvc_compiler_set_member_decoration_string(spvc_compiler compiler,spvc_type_id id,unsigned member_index,SpvDecoration decoration,const char * argument)1863 void spvc_compiler_set_member_decoration_string(spvc_compiler compiler, spvc_type_id id, unsigned member_index,
1864                                                 SpvDecoration decoration, const char *argument)
1865 {
1866 	compiler->compiler->set_member_decoration_string(id, member_index, static_cast<spv::Decoration>(decoration),
1867 	                                                 argument);
1868 }
1869 
spvc_compiler_set_member_name(spvc_compiler compiler,spvc_type_id id,unsigned member_index,const char * argument)1870 void spvc_compiler_set_member_name(spvc_compiler compiler, spvc_type_id id, unsigned member_index, const char *argument)
1871 {
1872 	compiler->compiler->set_member_name(id, member_index, argument);
1873 }
1874 
spvc_compiler_unset_decoration(spvc_compiler compiler,SpvId id,SpvDecoration decoration)1875 void spvc_compiler_unset_decoration(spvc_compiler compiler, SpvId id, SpvDecoration decoration)
1876 {
1877 	compiler->compiler->unset_decoration(id, static_cast<spv::Decoration>(decoration));
1878 }
1879 
spvc_compiler_unset_member_decoration(spvc_compiler compiler,spvc_type_id id,unsigned member_index,SpvDecoration decoration)1880 void spvc_compiler_unset_member_decoration(spvc_compiler compiler, spvc_type_id id, unsigned member_index,
1881                                            SpvDecoration decoration)
1882 {
1883 	compiler->compiler->unset_member_decoration(id, member_index, static_cast<spv::Decoration>(decoration));
1884 }
1885 
spvc_compiler_has_decoration(spvc_compiler compiler,SpvId id,SpvDecoration decoration)1886 spvc_bool spvc_compiler_has_decoration(spvc_compiler compiler, SpvId id, SpvDecoration decoration)
1887 {
1888 	return compiler->compiler->has_decoration(id, static_cast<spv::Decoration>(decoration)) ? SPVC_TRUE : SPVC_FALSE;
1889 }
1890 
spvc_compiler_has_member_decoration(spvc_compiler compiler,spvc_type_id id,unsigned member_index,SpvDecoration decoration)1891 spvc_bool spvc_compiler_has_member_decoration(spvc_compiler compiler, spvc_type_id id, unsigned member_index,
1892                                               SpvDecoration decoration)
1893 {
1894 	return compiler->compiler->has_member_decoration(id, member_index, static_cast<spv::Decoration>(decoration)) ?
1895 	           SPVC_TRUE :
1896 	           SPVC_FALSE;
1897 }
1898 
spvc_compiler_get_name(spvc_compiler compiler,SpvId id)1899 const char *spvc_compiler_get_name(spvc_compiler compiler, SpvId id)
1900 {
1901 	return compiler->compiler->get_name(id).c_str();
1902 }
1903 
spvc_compiler_get_decoration(spvc_compiler compiler,SpvId id,SpvDecoration decoration)1904 unsigned spvc_compiler_get_decoration(spvc_compiler compiler, SpvId id, SpvDecoration decoration)
1905 {
1906 	return compiler->compiler->get_decoration(id, static_cast<spv::Decoration>(decoration));
1907 }
1908 
spvc_compiler_get_decoration_string(spvc_compiler compiler,SpvId id,SpvDecoration decoration)1909 const char *spvc_compiler_get_decoration_string(spvc_compiler compiler, SpvId id, SpvDecoration decoration)
1910 {
1911 	return compiler->compiler->get_decoration_string(id, static_cast<spv::Decoration>(decoration)).c_str();
1912 }
1913 
spvc_compiler_get_member_decoration(spvc_compiler compiler,spvc_type_id id,unsigned member_index,SpvDecoration decoration)1914 unsigned spvc_compiler_get_member_decoration(spvc_compiler compiler, spvc_type_id id, unsigned member_index,
1915                                              SpvDecoration decoration)
1916 {
1917 	return compiler->compiler->get_member_decoration(id, member_index, static_cast<spv::Decoration>(decoration));
1918 }
1919 
spvc_compiler_get_member_decoration_string(spvc_compiler compiler,spvc_type_id id,unsigned member_index,SpvDecoration decoration)1920 const char *spvc_compiler_get_member_decoration_string(spvc_compiler compiler, spvc_type_id id, unsigned member_index,
1921                                                        SpvDecoration decoration)
1922 {
1923 	return compiler->compiler->get_member_decoration_string(id, member_index, static_cast<spv::Decoration>(decoration))
1924 	    .c_str();
1925 }
1926 
spvc_compiler_get_member_name(spvc_compiler compiler,spvc_type_id id,unsigned member_index)1927 const char *spvc_compiler_get_member_name(spvc_compiler compiler, spvc_type_id id, unsigned member_index)
1928 {
1929 	return compiler->compiler->get_member_name(id, member_index).c_str();
1930 }
1931 
spvc_compiler_get_entry_points(spvc_compiler compiler,const spvc_entry_point ** entry_points,size_t * num_entry_points)1932 spvc_result spvc_compiler_get_entry_points(spvc_compiler compiler, const spvc_entry_point **entry_points,
1933                                            size_t *num_entry_points)
1934 {
1935 	SPVC_BEGIN_SAFE_SCOPE
1936 	{
1937 		auto entries = compiler->compiler->get_entry_points_and_stages();
1938 		SmallVector<spvc_entry_point> translated;
1939 		translated.reserve(entries.size());
1940 
1941 		for (auto &entry : entries)
1942 		{
1943 			spvc_entry_point new_entry;
1944 			new_entry.execution_model = static_cast<SpvExecutionModel>(entry.execution_model);
1945 			new_entry.name = compiler->context->allocate_name(entry.name);
1946 			if (!new_entry.name)
1947 			{
1948 				compiler->context->report_error("Out of memory.");
1949 				return SPVC_ERROR_OUT_OF_MEMORY;
1950 			}
1951 			translated.push_back(new_entry);
1952 		}
1953 
1954 		auto ptr = spvc_allocate<TemporaryBuffer<spvc_entry_point>>();
1955 		ptr->buffer = std::move(translated);
1956 		*entry_points = ptr->buffer.data();
1957 		*num_entry_points = ptr->buffer.size();
1958 		compiler->context->allocations.push_back(std::move(ptr));
1959 	}
1960 	SPVC_END_SAFE_SCOPE(compiler->context, SPVC_ERROR_OUT_OF_MEMORY)
1961 	return SPVC_SUCCESS;
1962 }
1963 
spvc_compiler_set_entry_point(spvc_compiler compiler,const char * name,SpvExecutionModel model)1964 spvc_result spvc_compiler_set_entry_point(spvc_compiler compiler, const char *name, SpvExecutionModel model)
1965 {
1966 	compiler->compiler->set_entry_point(name, static_cast<spv::ExecutionModel>(model));
1967 	return SPVC_SUCCESS;
1968 }
1969 
spvc_compiler_rename_entry_point(spvc_compiler compiler,const char * old_name,const char * new_name,SpvExecutionModel model)1970 spvc_result spvc_compiler_rename_entry_point(spvc_compiler compiler, const char *old_name, const char *new_name,
1971                                              SpvExecutionModel model)
1972 {
1973 	SPVC_BEGIN_SAFE_SCOPE
1974 	{
1975 		compiler->compiler->rename_entry_point(old_name, new_name, static_cast<spv::ExecutionModel>(model));
1976 	}
1977 	SPVC_END_SAFE_SCOPE(compiler->context, SPVC_ERROR_INVALID_ARGUMENT)
1978 	return SPVC_SUCCESS;
1979 }
1980 
spvc_compiler_get_cleansed_entry_point_name(spvc_compiler compiler,const char * name,SpvExecutionModel model)1981 const char *spvc_compiler_get_cleansed_entry_point_name(spvc_compiler compiler, const char *name,
1982                                                         SpvExecutionModel model)
1983 {
1984 	SPVC_BEGIN_SAFE_SCOPE
1985 	{
1986 		auto cleansed_name =
1987 		    compiler->compiler->get_cleansed_entry_point_name(name, static_cast<spv::ExecutionModel>(model));
1988 		return compiler->context->allocate_name(cleansed_name);
1989 	}
1990 	SPVC_END_SAFE_SCOPE(compiler->context, nullptr)
1991 }
1992 
spvc_compiler_set_execution_mode(spvc_compiler compiler,SpvExecutionMode mode)1993 void spvc_compiler_set_execution_mode(spvc_compiler compiler, SpvExecutionMode mode)
1994 {
1995 	compiler->compiler->set_execution_mode(static_cast<spv::ExecutionMode>(mode));
1996 }
1997 
spvc_compiler_set_execution_mode_with_arguments(spvc_compiler compiler,SpvExecutionMode mode,unsigned arg0,unsigned arg1,unsigned arg2)1998 void spvc_compiler_set_execution_mode_with_arguments(spvc_compiler compiler, SpvExecutionMode mode, unsigned arg0,
1999                                                      unsigned arg1,
2000                                                      unsigned arg2)
2001 {
2002 	compiler->compiler->set_execution_mode(static_cast<spv::ExecutionMode>(mode), arg0, arg1, arg2);
2003 }
2004 
spvc_compiler_unset_execution_mode(spvc_compiler compiler,SpvExecutionMode mode)2005 void spvc_compiler_unset_execution_mode(spvc_compiler compiler, SpvExecutionMode mode)
2006 {
2007 	compiler->compiler->unset_execution_mode(static_cast<spv::ExecutionMode>(mode));
2008 }
2009 
spvc_compiler_get_execution_modes(spvc_compiler compiler,const SpvExecutionMode ** modes,size_t * num_modes)2010 spvc_result spvc_compiler_get_execution_modes(spvc_compiler compiler, const SpvExecutionMode **modes, size_t *num_modes)
2011 {
2012 	SPVC_BEGIN_SAFE_SCOPE
2013 	{
2014 		auto ptr = spvc_allocate<TemporaryBuffer<SpvExecutionMode>>();
2015 
2016 		compiler->compiler->get_execution_mode_bitset().for_each_bit(
2017 		    [&](uint32_t bit) { ptr->buffer.push_back(static_cast<SpvExecutionMode>(bit)); });
2018 
2019 		*modes = ptr->buffer.data();
2020 		*num_modes = ptr->buffer.size();
2021 		compiler->context->allocations.push_back(std::move(ptr));
2022 	}
2023 	SPVC_END_SAFE_SCOPE(compiler->context, SPVC_ERROR_OUT_OF_MEMORY)
2024 	return SPVC_SUCCESS;
2025 }
2026 
spvc_compiler_get_execution_mode_argument(spvc_compiler compiler,SpvExecutionMode mode)2027 unsigned spvc_compiler_get_execution_mode_argument(spvc_compiler compiler, SpvExecutionMode mode)
2028 {
2029 	return compiler->compiler->get_execution_mode_argument(static_cast<spv::ExecutionMode>(mode));
2030 }
2031 
spvc_compiler_get_execution_mode_argument_by_index(spvc_compiler compiler,SpvExecutionMode mode,unsigned index)2032 unsigned spvc_compiler_get_execution_mode_argument_by_index(spvc_compiler compiler, SpvExecutionMode mode,
2033                                                             unsigned index)
2034 {
2035 	return compiler->compiler->get_execution_mode_argument(static_cast<spv::ExecutionMode>(mode), index);
2036 }
2037 
spvc_compiler_get_execution_model(spvc_compiler compiler)2038 SpvExecutionModel spvc_compiler_get_execution_model(spvc_compiler compiler)
2039 {
2040 	return static_cast<SpvExecutionModel>(compiler->compiler->get_execution_model());
2041 }
2042 
spvc_compiler_update_active_builtins(spvc_compiler compiler)2043 void spvc_compiler_update_active_builtins(spvc_compiler compiler)
2044 {
2045        compiler->compiler->update_active_builtins();
2046 }
2047 
spvc_compiler_has_active_builtin(spvc_compiler compiler,SpvBuiltIn builtin,SpvStorageClass storage)2048 spvc_bool spvc_compiler_has_active_builtin(spvc_compiler compiler, SpvBuiltIn builtin, SpvStorageClass storage)
2049 {
2050 	return compiler->compiler->has_active_builtin(static_cast<spv::BuiltIn>(builtin), static_cast<spv::StorageClass>(storage)) ?
2051 		SPVC_TRUE :
2052 		SPVC_FALSE;
2053 }
2054 
spvc_compiler_get_type_handle(spvc_compiler compiler,spvc_type_id id)2055 spvc_type spvc_compiler_get_type_handle(spvc_compiler compiler, spvc_type_id id)
2056 {
2057 	// Should only throw if an intentionally garbage ID is passed, but the IDs are not type-safe.
2058 	SPVC_BEGIN_SAFE_SCOPE
2059 	{
2060 		return static_cast<spvc_type>(&compiler->compiler->get_type(id));
2061 	}
2062 	SPVC_END_SAFE_SCOPE(compiler->context, nullptr)
2063 }
2064 
spvc_type_get_base_type_id(spvc_type type)2065 spvc_type_id spvc_type_get_base_type_id(spvc_type type)
2066 {
2067 	return type->self;
2068 }
2069 
convert_basetype(SPIRType::BaseType type)2070 static spvc_basetype convert_basetype(SPIRType::BaseType type)
2071 {
2072 	// For now the enums match up.
2073 	return static_cast<spvc_basetype>(type);
2074 }
2075 
spvc_type_get_basetype(spvc_type type)2076 spvc_basetype spvc_type_get_basetype(spvc_type type)
2077 {
2078 	return convert_basetype(type->basetype);
2079 }
2080 
spvc_type_get_bit_width(spvc_type type)2081 unsigned spvc_type_get_bit_width(spvc_type type)
2082 {
2083 	return type->width;
2084 }
2085 
spvc_type_get_vector_size(spvc_type type)2086 unsigned spvc_type_get_vector_size(spvc_type type)
2087 {
2088 	return type->vecsize;
2089 }
2090 
spvc_type_get_columns(spvc_type type)2091 unsigned spvc_type_get_columns(spvc_type type)
2092 {
2093 	return type->columns;
2094 }
2095 
spvc_type_get_num_array_dimensions(spvc_type type)2096 unsigned spvc_type_get_num_array_dimensions(spvc_type type)
2097 {
2098 	return unsigned(type->array.size());
2099 }
2100 
spvc_type_array_dimension_is_literal(spvc_type type,unsigned dimension)2101 spvc_bool spvc_type_array_dimension_is_literal(spvc_type type, unsigned dimension)
2102 {
2103 	return type->array_size_literal[dimension] ? SPVC_TRUE : SPVC_FALSE;
2104 }
2105 
spvc_type_get_array_dimension(spvc_type type,unsigned dimension)2106 SpvId spvc_type_get_array_dimension(spvc_type type, unsigned dimension)
2107 {
2108 	return type->array[dimension];
2109 }
2110 
spvc_type_get_num_member_types(spvc_type type)2111 unsigned spvc_type_get_num_member_types(spvc_type type)
2112 {
2113 	return unsigned(type->member_types.size());
2114 }
2115 
spvc_type_get_member_type(spvc_type type,unsigned index)2116 spvc_type_id spvc_type_get_member_type(spvc_type type, unsigned index)
2117 {
2118 	return type->member_types[index];
2119 }
2120 
spvc_type_get_storage_class(spvc_type type)2121 SpvStorageClass spvc_type_get_storage_class(spvc_type type)
2122 {
2123 	return static_cast<SpvStorageClass>(type->storage);
2124 }
2125 
2126 // Image type query.
spvc_type_get_image_sampled_type(spvc_type type)2127 spvc_type_id spvc_type_get_image_sampled_type(spvc_type type)
2128 {
2129 	return type->image.type;
2130 }
2131 
spvc_type_get_image_dimension(spvc_type type)2132 SpvDim spvc_type_get_image_dimension(spvc_type type)
2133 {
2134 	return static_cast<SpvDim>(type->image.dim);
2135 }
2136 
spvc_type_get_image_is_depth(spvc_type type)2137 spvc_bool spvc_type_get_image_is_depth(spvc_type type)
2138 {
2139 	return type->image.depth ? SPVC_TRUE : SPVC_FALSE;
2140 }
2141 
spvc_type_get_image_arrayed(spvc_type type)2142 spvc_bool spvc_type_get_image_arrayed(spvc_type type)
2143 {
2144 	return type->image.arrayed ? SPVC_TRUE : SPVC_FALSE;
2145 }
2146 
spvc_type_get_image_multisampled(spvc_type type)2147 spvc_bool spvc_type_get_image_multisampled(spvc_type type)
2148 {
2149 	return type->image.ms ? SPVC_TRUE : SPVC_FALSE;
2150 }
2151 
spvc_type_get_image_is_storage(spvc_type type)2152 spvc_bool spvc_type_get_image_is_storage(spvc_type type)
2153 {
2154 	return type->image.sampled == 2 ? SPVC_TRUE : SPVC_FALSE;
2155 }
2156 
spvc_type_get_image_storage_format(spvc_type type)2157 SpvImageFormat spvc_type_get_image_storage_format(spvc_type type)
2158 {
2159 	return static_cast<SpvImageFormat>(static_cast<const SPIRType *>(type)->image.format);
2160 }
2161 
spvc_type_get_image_access_qualifier(spvc_type type)2162 SpvAccessQualifier spvc_type_get_image_access_qualifier(spvc_type type)
2163 {
2164 	return static_cast<SpvAccessQualifier>(static_cast<const SPIRType *>(type)->image.access);
2165 }
2166 
spvc_compiler_get_declared_struct_size(spvc_compiler compiler,spvc_type struct_type,size_t * size)2167 spvc_result spvc_compiler_get_declared_struct_size(spvc_compiler compiler, spvc_type struct_type, size_t *size)
2168 {
2169 	SPVC_BEGIN_SAFE_SCOPE
2170 	{
2171 		*size = compiler->compiler->get_declared_struct_size(*static_cast<const SPIRType *>(struct_type));
2172 	}
2173 	SPVC_END_SAFE_SCOPE(compiler->context, SPVC_ERROR_INVALID_ARGUMENT)
2174 	return SPVC_SUCCESS;
2175 }
2176 
spvc_compiler_get_declared_struct_size_runtime_array(spvc_compiler compiler,spvc_type struct_type,size_t array_size,size_t * size)2177 spvc_result spvc_compiler_get_declared_struct_size_runtime_array(spvc_compiler compiler, spvc_type struct_type,
2178                                                                  size_t array_size, size_t *size)
2179 {
2180 	SPVC_BEGIN_SAFE_SCOPE
2181 	{
2182 		*size = compiler->compiler->get_declared_struct_size_runtime_array(*static_cast<const SPIRType *>(struct_type),
2183 		                                                                   array_size);
2184 	}
2185 	SPVC_END_SAFE_SCOPE(compiler->context, SPVC_ERROR_INVALID_ARGUMENT)
2186 	return SPVC_SUCCESS;
2187 }
2188 
spvc_compiler_get_declared_struct_member_size(spvc_compiler compiler,spvc_type struct_type,unsigned index,size_t * size)2189 spvc_result spvc_compiler_get_declared_struct_member_size(spvc_compiler compiler, spvc_type struct_type, unsigned index, size_t *size)
2190 {
2191 	SPVC_BEGIN_SAFE_SCOPE
2192 	{
2193 		*size = compiler->compiler->get_declared_struct_member_size(*static_cast<const SPIRType *>(struct_type), index);
2194 	}
2195 	SPVC_END_SAFE_SCOPE(compiler->context, SPVC_ERROR_INVALID_ARGUMENT)
2196 	return SPVC_SUCCESS;
2197 }
2198 
spvc_compiler_type_struct_member_offset(spvc_compiler compiler,spvc_type type,unsigned index,unsigned * offset)2199 spvc_result spvc_compiler_type_struct_member_offset(spvc_compiler compiler, spvc_type type, unsigned index, unsigned *offset)
2200 {
2201 	SPVC_BEGIN_SAFE_SCOPE
2202 	{
2203 		*offset = compiler->compiler->type_struct_member_offset(*static_cast<const SPIRType *>(type), index);
2204 	}
2205 	SPVC_END_SAFE_SCOPE(compiler->context, SPVC_ERROR_INVALID_ARGUMENT)
2206 	return SPVC_SUCCESS;
2207 }
2208 
spvc_compiler_type_struct_member_array_stride(spvc_compiler compiler,spvc_type type,unsigned index,unsigned * stride)2209 spvc_result spvc_compiler_type_struct_member_array_stride(spvc_compiler compiler, spvc_type type, unsigned index, unsigned *stride)
2210 {
2211 	SPVC_BEGIN_SAFE_SCOPE
2212 	{
2213 		*stride = compiler->compiler->type_struct_member_array_stride(*static_cast<const SPIRType *>(type), index);
2214 	}
2215 	SPVC_END_SAFE_SCOPE(compiler->context, SPVC_ERROR_INVALID_ARGUMENT)
2216 	return SPVC_SUCCESS;
2217 }
2218 
spvc_compiler_type_struct_member_matrix_stride(spvc_compiler compiler,spvc_type type,unsigned index,unsigned * stride)2219 spvc_result spvc_compiler_type_struct_member_matrix_stride(spvc_compiler compiler, spvc_type type, unsigned index, unsigned *stride)
2220 {
2221 	SPVC_BEGIN_SAFE_SCOPE
2222 	{
2223 		*stride = compiler->compiler->type_struct_member_matrix_stride(*static_cast<const SPIRType *>(type), index);
2224 	}
2225 	SPVC_END_SAFE_SCOPE(compiler->context, SPVC_ERROR_INVALID_ARGUMENT)
2226 	return SPVC_SUCCESS;
2227 }
2228 
spvc_compiler_build_dummy_sampler_for_combined_images(spvc_compiler compiler,spvc_variable_id * id)2229 spvc_result spvc_compiler_build_dummy_sampler_for_combined_images(spvc_compiler compiler, spvc_variable_id *id)
2230 {
2231 	SPVC_BEGIN_SAFE_SCOPE
2232 	{
2233 		*id = compiler->compiler->build_dummy_sampler_for_combined_images();
2234 	}
2235 	SPVC_END_SAFE_SCOPE(compiler->context, SPVC_ERROR_INVALID_ARGUMENT)
2236 	return SPVC_SUCCESS;
2237 }
2238 
spvc_compiler_build_combined_image_samplers(spvc_compiler compiler)2239 spvc_result spvc_compiler_build_combined_image_samplers(spvc_compiler compiler)
2240 {
2241 	SPVC_BEGIN_SAFE_SCOPE
2242 	{
2243 		compiler->compiler->build_combined_image_samplers();
2244 	}
2245 	SPVC_END_SAFE_SCOPE(compiler->context, SPVC_ERROR_UNSUPPORTED_SPIRV)
2246 	return SPVC_SUCCESS;
2247 }
2248 
spvc_compiler_get_combined_image_samplers(spvc_compiler compiler,const spvc_combined_image_sampler ** samplers,size_t * num_samplers)2249 spvc_result spvc_compiler_get_combined_image_samplers(spvc_compiler compiler,
2250                                                       const spvc_combined_image_sampler **samplers,
2251                                                       size_t *num_samplers)
2252 {
2253 	SPVC_BEGIN_SAFE_SCOPE
2254 	{
2255 		auto combined = compiler->compiler->get_combined_image_samplers();
2256 		SmallVector<spvc_combined_image_sampler> translated;
2257 		translated.reserve(combined.size());
2258 		for (auto &c : combined)
2259 		{
2260 			spvc_combined_image_sampler trans = { c.combined_id, c.image_id, c.sampler_id };
2261 			translated.push_back(trans);
2262 		}
2263 
2264 		auto ptr = spvc_allocate<TemporaryBuffer<spvc_combined_image_sampler>>();
2265 		ptr->buffer = std::move(translated);
2266 		*samplers = ptr->buffer.data();
2267 		*num_samplers = ptr->buffer.size();
2268 		compiler->context->allocations.push_back(std::move(ptr));
2269 	}
2270 	SPVC_END_SAFE_SCOPE(compiler->context, SPVC_ERROR_OUT_OF_MEMORY)
2271 	return SPVC_SUCCESS;
2272 }
2273 
spvc_compiler_get_specialization_constants(spvc_compiler compiler,const spvc_specialization_constant ** constants,size_t * num_constants)2274 spvc_result spvc_compiler_get_specialization_constants(spvc_compiler compiler,
2275                                                        const spvc_specialization_constant **constants,
2276                                                        size_t *num_constants)
2277 {
2278 	SPVC_BEGIN_SAFE_SCOPE
2279 	{
2280 		auto spec_constants = compiler->compiler->get_specialization_constants();
2281 		SmallVector<spvc_specialization_constant> translated;
2282 		translated.reserve(spec_constants.size());
2283 		for (auto &c : spec_constants)
2284 		{
2285 			spvc_specialization_constant trans = { c.id, c.constant_id };
2286 			translated.push_back(trans);
2287 		}
2288 
2289 		auto ptr = spvc_allocate<TemporaryBuffer<spvc_specialization_constant>>();
2290 		ptr->buffer = std::move(translated);
2291 		*constants = ptr->buffer.data();
2292 		*num_constants = ptr->buffer.size();
2293 		compiler->context->allocations.push_back(std::move(ptr));
2294 	}
2295 	SPVC_END_SAFE_SCOPE(compiler->context, SPVC_ERROR_OUT_OF_MEMORY)
2296 	return SPVC_SUCCESS;
2297 }
2298 
spvc_compiler_get_constant_handle(spvc_compiler compiler,spvc_variable_id id)2299 spvc_constant spvc_compiler_get_constant_handle(spvc_compiler compiler, spvc_variable_id id)
2300 {
2301 	SPVC_BEGIN_SAFE_SCOPE
2302 	{
2303 		return static_cast<spvc_constant>(&compiler->compiler->get_constant(id));
2304 	}
2305 	SPVC_END_SAFE_SCOPE(compiler->context, nullptr)
2306 }
2307 
spvc_compiler_get_work_group_size_specialization_constants(spvc_compiler compiler,spvc_specialization_constant * x,spvc_specialization_constant * y,spvc_specialization_constant * z)2308 spvc_constant_id spvc_compiler_get_work_group_size_specialization_constants(spvc_compiler compiler,
2309                                                                             spvc_specialization_constant *x,
2310                                                                             spvc_specialization_constant *y,
2311                                                                             spvc_specialization_constant *z)
2312 {
2313 	SpecializationConstant tmpx;
2314 	SpecializationConstant tmpy;
2315 	SpecializationConstant tmpz;
2316 	spvc_constant_id ret = compiler->compiler->get_work_group_size_specialization_constants(tmpx, tmpy, tmpz);
2317 	x->id = tmpx.id;
2318 	x->constant_id = tmpx.constant_id;
2319 	y->id = tmpy.id;
2320 	y->constant_id = tmpy.constant_id;
2321 	z->id = tmpz.id;
2322 	z->constant_id = tmpz.constant_id;
2323 	return ret;
2324 }
2325 
spvc_compiler_get_active_buffer_ranges(spvc_compiler compiler,spvc_variable_id id,const spvc_buffer_range ** ranges,size_t * num_ranges)2326 spvc_result spvc_compiler_get_active_buffer_ranges(spvc_compiler compiler,
2327                                                    spvc_variable_id id,
2328                                                    const spvc_buffer_range **ranges,
2329                                                    size_t *num_ranges)
2330 {
2331 	SPVC_BEGIN_SAFE_SCOPE
2332 	{
2333 		auto active_ranges = compiler->compiler->get_active_buffer_ranges(id);
2334 		SmallVector<spvc_buffer_range> translated;
2335 		translated.reserve(active_ranges.size());
2336 		for (auto &r : active_ranges)
2337 		{
2338 			spvc_buffer_range trans = { r.index, r.offset, r.range };
2339 			translated.push_back(trans);
2340 		}
2341 
2342 		auto ptr = spvc_allocate<TemporaryBuffer<spvc_buffer_range>>();
2343 		ptr->buffer = std::move(translated);
2344 		*ranges = ptr->buffer.data();
2345 		*num_ranges = ptr->buffer.size();
2346 		compiler->context->allocations.push_back(std::move(ptr));
2347 	}
2348 	SPVC_END_SAFE_SCOPE(compiler->context, SPVC_ERROR_OUT_OF_MEMORY)
2349 	return SPVC_SUCCESS;
2350 }
2351 
spvc_constant_get_scalar_fp16(spvc_constant constant,unsigned column,unsigned row)2352 float spvc_constant_get_scalar_fp16(spvc_constant constant, unsigned column, unsigned row)
2353 {
2354 	return constant->scalar_f16(column, row);
2355 }
2356 
spvc_constant_get_scalar_fp32(spvc_constant constant,unsigned column,unsigned row)2357 float spvc_constant_get_scalar_fp32(spvc_constant constant, unsigned column, unsigned row)
2358 {
2359 	return constant->scalar_f32(column, row);
2360 }
2361 
spvc_constant_get_scalar_fp64(spvc_constant constant,unsigned column,unsigned row)2362 double spvc_constant_get_scalar_fp64(spvc_constant constant, unsigned column, unsigned row)
2363 {
2364 	return constant->scalar_f64(column, row);
2365 }
2366 
spvc_constant_get_scalar_u32(spvc_constant constant,unsigned column,unsigned row)2367 unsigned spvc_constant_get_scalar_u32(spvc_constant constant, unsigned column, unsigned row)
2368 {
2369 	return constant->scalar(column, row);
2370 }
2371 
spvc_constant_get_scalar_i32(spvc_constant constant,unsigned column,unsigned row)2372 int spvc_constant_get_scalar_i32(spvc_constant constant, unsigned column, unsigned row)
2373 {
2374 	return constant->scalar_i32(column, row);
2375 }
2376 
spvc_constant_get_scalar_u16(spvc_constant constant,unsigned column,unsigned row)2377 unsigned spvc_constant_get_scalar_u16(spvc_constant constant, unsigned column, unsigned row)
2378 {
2379 	return constant->scalar_u16(column, row);
2380 }
2381 
spvc_constant_get_scalar_i16(spvc_constant constant,unsigned column,unsigned row)2382 int spvc_constant_get_scalar_i16(spvc_constant constant, unsigned column, unsigned row)
2383 {
2384 	return constant->scalar_i16(column, row);
2385 }
2386 
spvc_constant_get_scalar_u8(spvc_constant constant,unsigned column,unsigned row)2387 unsigned spvc_constant_get_scalar_u8(spvc_constant constant, unsigned column, unsigned row)
2388 {
2389 	return constant->scalar_u8(column, row);
2390 }
2391 
spvc_constant_get_scalar_i8(spvc_constant constant,unsigned column,unsigned row)2392 int spvc_constant_get_scalar_i8(spvc_constant constant, unsigned column, unsigned row)
2393 {
2394 	return constant->scalar_i8(column, row);
2395 }
2396 
spvc_constant_get_subconstants(spvc_constant constant,const spvc_constant_id ** constituents,size_t * count)2397 void spvc_constant_get_subconstants(spvc_constant constant, const spvc_constant_id **constituents, size_t *count)
2398 {
2399 	static_assert(sizeof(spvc_constant_id) == sizeof(constant->subconstants.front()), "ID size is not consistent.");
2400 	*constituents = reinterpret_cast<spvc_constant_id *>(constant->subconstants.data());
2401 	*count = constant->subconstants.size();
2402 }
2403 
spvc_constant_get_type(spvc_constant constant)2404 spvc_type_id spvc_constant_get_type(spvc_constant constant)
2405 {
2406 	return constant->constant_type;
2407 }
2408 
spvc_compiler_get_binary_offset_for_decoration(spvc_compiler compiler,spvc_variable_id id,SpvDecoration decoration,unsigned * word_offset)2409 spvc_bool spvc_compiler_get_binary_offset_for_decoration(spvc_compiler compiler, spvc_variable_id id,
2410                                                          SpvDecoration decoration,
2411                                                          unsigned *word_offset)
2412 {
2413 	uint32_t off = 0;
2414 	bool ret = compiler->compiler->get_binary_offset_for_decoration(id, static_cast<spv::Decoration>(decoration), off);
2415 	if (ret)
2416 	{
2417 		*word_offset = off;
2418 		return SPVC_TRUE;
2419 	}
2420 	else
2421 		return SPVC_FALSE;
2422 }
2423 
spvc_compiler_buffer_is_hlsl_counter_buffer(spvc_compiler compiler,spvc_variable_id id)2424 spvc_bool spvc_compiler_buffer_is_hlsl_counter_buffer(spvc_compiler compiler, spvc_variable_id id)
2425 {
2426 	return compiler->compiler->buffer_is_hlsl_counter_buffer(id) ? SPVC_TRUE : SPVC_FALSE;
2427 }
2428 
spvc_compiler_buffer_get_hlsl_counter_buffer(spvc_compiler compiler,spvc_variable_id id,spvc_variable_id * counter_id)2429 spvc_bool spvc_compiler_buffer_get_hlsl_counter_buffer(spvc_compiler compiler, spvc_variable_id id,
2430                                                        spvc_variable_id *counter_id)
2431 {
2432 	uint32_t buffer;
2433 	bool ret = compiler->compiler->buffer_get_hlsl_counter_buffer(id, buffer);
2434 	if (ret)
2435 	{
2436 		*counter_id = buffer;
2437 		return SPVC_TRUE;
2438 	}
2439 	else
2440 		return SPVC_FALSE;
2441 }
2442 
spvc_compiler_get_declared_capabilities(spvc_compiler compiler,const SpvCapability ** capabilities,size_t * num_capabilities)2443 spvc_result spvc_compiler_get_declared_capabilities(spvc_compiler compiler, const SpvCapability **capabilities,
2444                                                     size_t *num_capabilities)
2445 {
2446 	auto &caps = compiler->compiler->get_declared_capabilities();
2447 	static_assert(sizeof(SpvCapability) == sizeof(spv::Capability), "Enum size mismatch.");
2448 	*capabilities = reinterpret_cast<const SpvCapability *>(caps.data());
2449 	*num_capabilities = caps.size();
2450 	return SPVC_SUCCESS;
2451 }
2452 
spvc_compiler_get_declared_extensions(spvc_compiler compiler,const char *** extensions,size_t * num_extensions)2453 spvc_result spvc_compiler_get_declared_extensions(spvc_compiler compiler, const char ***extensions,
2454                                                   size_t *num_extensions)
2455 {
2456 	SPVC_BEGIN_SAFE_SCOPE
2457 	{
2458 		auto &exts = compiler->compiler->get_declared_extensions();
2459 		SmallVector<const char *> duped;
2460 		duped.reserve(exts.size());
2461 		for (auto &ext : exts)
2462 			duped.push_back(compiler->context->allocate_name(ext));
2463 
2464 		auto ptr = spvc_allocate<TemporaryBuffer<const char *>>();
2465 		ptr->buffer = std::move(duped);
2466 		*extensions = ptr->buffer.data();
2467 		*num_extensions = ptr->buffer.size();
2468 		compiler->context->allocations.push_back(std::move(ptr));
2469 	}
2470 	SPVC_END_SAFE_SCOPE(compiler->context, SPVC_ERROR_OUT_OF_MEMORY)
2471 	return SPVC_SUCCESS;
2472 }
2473 
spvc_compiler_get_remapped_declared_block_name(spvc_compiler compiler,spvc_variable_id id)2474 const char *spvc_compiler_get_remapped_declared_block_name(spvc_compiler compiler, spvc_variable_id id)
2475 {
2476 	SPVC_BEGIN_SAFE_SCOPE
2477 	{
2478 		auto name = compiler->compiler->get_remapped_declared_block_name(id);
2479 		return compiler->context->allocate_name(name);
2480 	}
2481 	SPVC_END_SAFE_SCOPE(compiler->context, nullptr)
2482 }
2483 
spvc_compiler_get_buffer_block_decorations(spvc_compiler compiler,spvc_variable_id id,const SpvDecoration ** decorations,size_t * num_decorations)2484 spvc_result spvc_compiler_get_buffer_block_decorations(spvc_compiler compiler, spvc_variable_id id,
2485                                                        const SpvDecoration **decorations, size_t *num_decorations)
2486 {
2487 	SPVC_BEGIN_SAFE_SCOPE
2488 	{
2489 		auto flags = compiler->compiler->get_buffer_block_flags(id);
2490 		auto bitset = spvc_allocate<TemporaryBuffer<SpvDecoration>>();
2491 
2492 		flags.for_each_bit([&](uint32_t bit) { bitset->buffer.push_back(static_cast<SpvDecoration>(bit)); });
2493 
2494 		*decorations = bitset->buffer.data();
2495 		*num_decorations = bitset->buffer.size();
2496 		compiler->context->allocations.push_back(std::move(bitset));
2497 	}
2498 	SPVC_END_SAFE_SCOPE(compiler->context, SPVC_ERROR_INVALID_ARGUMENT)
2499 	return SPVC_SUCCESS;
2500 }
2501 
spvc_msl_get_aux_buffer_struct_version(void)2502 unsigned spvc_msl_get_aux_buffer_struct_version(void)
2503 {
2504 	return SPVC_MSL_AUX_BUFFER_STRUCT_VERSION;
2505 }
2506 
spvc_msl_vertex_attribute_init(spvc_msl_vertex_attribute * attr)2507 void spvc_msl_vertex_attribute_init(spvc_msl_vertex_attribute *attr)
2508 {
2509 #if SPIRV_CROSS_C_API_MSL
2510 	// Crude, but works.
2511 	MSLShaderInput attr_default;
2512 	attr->location = attr_default.location;
2513 	attr->format = static_cast<spvc_msl_vertex_format>(attr_default.format);
2514 	attr->builtin = static_cast<SpvBuiltIn>(attr_default.builtin);
2515 #else
2516 	memset(attr, 0, sizeof(*attr));
2517 #endif
2518 }
2519 
spvc_msl_shader_input_init(spvc_msl_shader_input * input)2520 void spvc_msl_shader_input_init(spvc_msl_shader_input *input)
2521 {
2522 #if SPIRV_CROSS_C_API_MSL
2523 	MSLShaderInput input_default;
2524 	input->location = input_default.location;
2525 	input->format = static_cast<spvc_msl_shader_input_format>(input_default.format);
2526 	input->builtin = static_cast<SpvBuiltIn>(input_default.builtin);
2527 	input->vecsize = input_default.vecsize;
2528 #else
2529 	memset(input, 0, sizeof(*input));
2530 #endif
2531 }
2532 
spvc_msl_resource_binding_init(spvc_msl_resource_binding * binding)2533 void spvc_msl_resource_binding_init(spvc_msl_resource_binding *binding)
2534 {
2535 #if SPIRV_CROSS_C_API_MSL
2536 	MSLResourceBinding binding_default;
2537 	binding->desc_set = binding_default.desc_set;
2538 	binding->binding = binding_default.binding;
2539 	binding->msl_buffer = binding_default.msl_buffer;
2540 	binding->msl_texture = binding_default.msl_texture;
2541 	binding->msl_sampler = binding_default.msl_sampler;
2542 	binding->stage = static_cast<SpvExecutionModel>(binding_default.stage);
2543 #else
2544 	memset(binding, 0, sizeof(*binding));
2545 #endif
2546 }
2547 
spvc_hlsl_resource_binding_init(spvc_hlsl_resource_binding * binding)2548 void spvc_hlsl_resource_binding_init(spvc_hlsl_resource_binding *binding)
2549 {
2550 #if SPIRV_CROSS_C_API_HLSL
2551 	HLSLResourceBinding binding_default;
2552 	binding->desc_set = binding_default.desc_set;
2553 	binding->binding = binding_default.binding;
2554 	binding->cbv.register_binding = binding_default.cbv.register_binding;
2555 	binding->cbv.register_space = binding_default.cbv.register_space;
2556 	binding->srv.register_binding = binding_default.srv.register_binding;
2557 	binding->srv.register_space = binding_default.srv.register_space;
2558 	binding->uav.register_binding = binding_default.uav.register_binding;
2559 	binding->uav.register_space = binding_default.uav.register_space;
2560 	binding->sampler.register_binding = binding_default.sampler.register_binding;
2561 	binding->sampler.register_space = binding_default.sampler.register_space;
2562 	binding->stage = static_cast<SpvExecutionModel>(binding_default.stage);
2563 #else
2564 	memset(binding, 0, sizeof(*binding));
2565 #endif
2566 }
2567 
spvc_msl_constexpr_sampler_init(spvc_msl_constexpr_sampler * sampler)2568 void spvc_msl_constexpr_sampler_init(spvc_msl_constexpr_sampler *sampler)
2569 {
2570 #if SPIRV_CROSS_C_API_MSL
2571 	MSLConstexprSampler defaults;
2572 	sampler->anisotropy_enable = defaults.anisotropy_enable ? SPVC_TRUE : SPVC_FALSE;
2573 	sampler->border_color = static_cast<spvc_msl_sampler_border_color>(defaults.border_color);
2574 	sampler->compare_enable = defaults.compare_enable ? SPVC_TRUE : SPVC_FALSE;
2575 	sampler->coord = static_cast<spvc_msl_sampler_coord>(defaults.coord);
2576 	sampler->compare_func = static_cast<spvc_msl_sampler_compare_func>(defaults.compare_func);
2577 	sampler->lod_clamp_enable = defaults.lod_clamp_enable ? SPVC_TRUE : SPVC_FALSE;
2578 	sampler->lod_clamp_max = defaults.lod_clamp_max;
2579 	sampler->lod_clamp_min = defaults.lod_clamp_min;
2580 	sampler->mag_filter = static_cast<spvc_msl_sampler_filter>(defaults.mag_filter);
2581 	sampler->min_filter = static_cast<spvc_msl_sampler_filter>(defaults.min_filter);
2582 	sampler->mip_filter = static_cast<spvc_msl_sampler_mip_filter>(defaults.mip_filter);
2583 	sampler->max_anisotropy = defaults.max_anisotropy;
2584 	sampler->s_address = static_cast<spvc_msl_sampler_address>(defaults.s_address);
2585 	sampler->t_address = static_cast<spvc_msl_sampler_address>(defaults.t_address);
2586 	sampler->r_address = static_cast<spvc_msl_sampler_address>(defaults.r_address);
2587 #else
2588 	memset(sampler, 0, sizeof(*sampler));
2589 #endif
2590 }
2591 
spvc_msl_sampler_ycbcr_conversion_init(spvc_msl_sampler_ycbcr_conversion * conv)2592 void spvc_msl_sampler_ycbcr_conversion_init(spvc_msl_sampler_ycbcr_conversion *conv)
2593 {
2594 #if SPIRV_CROSS_C_API_MSL
2595 	MSLConstexprSampler defaults;
2596 	conv->planes = defaults.planes;
2597 	conv->resolution = static_cast<spvc_msl_format_resolution>(defaults.resolution);
2598 	conv->chroma_filter = static_cast<spvc_msl_sampler_filter>(defaults.chroma_filter);
2599 	conv->x_chroma_offset = static_cast<spvc_msl_chroma_location>(defaults.x_chroma_offset);
2600 	conv->y_chroma_offset = static_cast<spvc_msl_chroma_location>(defaults.y_chroma_offset);
2601 	for (int i = 0; i < 4; i++)
2602 		conv->swizzle[i] = static_cast<spvc_msl_component_swizzle>(defaults.swizzle[i]);
2603 	conv->ycbcr_model = static_cast<spvc_msl_sampler_ycbcr_model_conversion>(defaults.ycbcr_model);
2604 	conv->ycbcr_range = static_cast<spvc_msl_sampler_ycbcr_range>(defaults.ycbcr_range);
2605 #else
2606 	memset(conv, 0, sizeof(*conv));
2607 #endif
2608 }
2609 
spvc_compiler_get_current_id_bound(spvc_compiler compiler)2610 unsigned spvc_compiler_get_current_id_bound(spvc_compiler compiler)
2611 {
2612 	return compiler->compiler->get_current_id_bound();
2613 }
2614 
spvc_get_version(unsigned * major,unsigned * minor,unsigned * patch)2615 void spvc_get_version(unsigned *major, unsigned *minor, unsigned *patch)
2616 {
2617 	*major = SPVC_C_API_VERSION_MAJOR;
2618 	*minor = SPVC_C_API_VERSION_MINOR;
2619 	*patch = SPVC_C_API_VERSION_PATCH;
2620 }
2621 
spvc_get_commit_revision_and_timestamp(void)2622 const char *spvc_get_commit_revision_and_timestamp(void)
2623 {
2624 #ifdef HAVE_SPIRV_CROSS_GIT_VERSION
2625 	return SPIRV_CROSS_GIT_REVISION;
2626 #else
2627 	return "";
2628 #endif
2629 }
2630 
2631 #ifdef _MSC_VER
2632 #pragma warning(pop)
2633 #endif
2634