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

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