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

source code of qtshadertools/src/3rdparty/SPIRV-Cross/spirv_cross_c.cpp