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