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