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

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