1 // Copyright 2018 The Shaderc Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <spvc/spvc.hpp>
16
17 #include "spvc_log.h"
18 #include "spvc_private.h"
19
20 // MSVC 2013 doesn't define __func__
21 #ifndef __func__
22 #define __func__ __FUNCTION__
23 #endif
24
25 #define CHECK_CONTEXT(context) \
26 do { \
27 if (!context) { \
28 shaderc_spvc::ErrorLog(nullptr) \
29 << "Invoked " << __func__ << " without an initialized context"; \
30 return shaderc_spvc_status_missing_context_error; \
31 } \
32 } while (0)
33
34 #define CHECK_CROSS_COMPILER(context, cross_compiler) \
35 do { \
36 if (!cross_compiler) { \
37 shaderc_spvc::ErrorLog(context) \
38 << "Invoked " << __func__ \
39 << " without an initialized cross compiler"; \
40 return shaderc_spvc_status_uninitialized_compiler_error; \
41 } \
42 } while (0)
43
44 #define CHECK_OPTIONS(context, options) \
45 do { \
46 if (!options) { \
47 shaderc_spvc::ErrorLog(context) \
48 << "Invoked " << __func__ << " without an initialized options"; \
49 return shaderc_spvc_status_missing_options_error; \
50 } \
51 } while (0)
52
53 #define CHECK_RESULT(context, result) \
54 do { \
55 if (!result) { \
56 shaderc_spvc::ErrorLog(context) \
57 << "Invoked " << __func__ << " without an initialized result"; \
58 return shaderc_spvc_status_missing_result_error; \
59 } \
60 } while (0)
61
62 #define CHECK_OUT_PARAM(context, param, param_str) \
63 do { \
64 if (!param) { \
65 shaderc_spvc::ErrorLog(context) \
66 << "Invoked " << __func__ << " with invalid out param, " \
67 << param_str; \
68 return shaderc_spvc_status_invalid_out_param; \
69 } \
70 } while (0)
71
72 #define CHECK_IN_PARAM(context, param, param_str) \
73 do { \
74 if (!param) { \
75 shaderc_spvc::ErrorLog(context) \
76 << "Invoked " << __func__ << " with invalid in param, " \
77 << param_str; \
78 return shaderc_spvc_status_invalid_in_param; \
79 } \
80 } while (0)
81
82 namespace {
83
spvc_model_to_spv_model(shaderc_spvc_execution_model model)84 spv::ExecutionModel spvc_model_to_spv_model(
85 shaderc_spvc_execution_model model) {
86 switch (model) {
87 case shaderc_spvc_execution_model_vertex:
88 return spv::ExecutionModel::ExecutionModelVertex;
89 case shaderc_spvc_execution_model_fragment:
90 return spv::ExecutionModel::ExecutionModelFragment;
91 case shaderc_spvc_execution_model_glcompute:
92 return spv::ExecutionModel::ExecutionModelGLCompute;
93 case shaderc_spvc_execution_model_invalid:
94 return spv::ExecutionModel::ExecutionModelMax;
95 }
96
97 // Older gcc doesn't recognize that all of the possible cases are covered
98 // above.
99 assert(false);
100 return spv::ExecutionModel::ExecutionModelMax;
101 }
102
spv_model_to_spvc_model(spv::ExecutionModel model)103 shaderc_spvc_execution_model spv_model_to_spvc_model(
104 spv::ExecutionModel model) {
105 switch (model) {
106 case spv::ExecutionModel::ExecutionModelVertex:
107 return shaderc_spvc_execution_model_vertex;
108 case spv::ExecutionModel::ExecutionModelFragment:
109 return shaderc_spvc_execution_model_fragment;
110 case spv::ExecutionModel::ExecutionModelGLCompute:
111 return shaderc_spvc_execution_model_glcompute;
112 default:
113 return shaderc_spvc_execution_model_invalid;
114 }
115 }
116
get_shader_resources(const spirv_cross::ShaderResources & resources,shaderc_spvc_shader_resource resource)117 const spirv_cross::SmallVector<spirv_cross::Resource>* get_shader_resources(
118 const spirv_cross::ShaderResources& resources,
119 shaderc_spvc_shader_resource resource) {
120 switch (resource) {
121 case shaderc_spvc_shader_resource_uniform_buffers:
122 return &(resources.uniform_buffers);
123 case shaderc_spvc_shader_resource_separate_images:
124 return &(resources.separate_images);
125 case shaderc_spvc_shader_resource_separate_samplers:
126 return &(resources.separate_samplers);
127 case shaderc_spvc_shader_resource_storage_buffers:
128 return &(resources.storage_buffers);
129 case shaderc_spvc_shader_resource_storage_images:
130 return &(resources.storage_images);
131 }
132
133 // Older gcc doesn't recognize that all of the possible cases are covered
134 // above.
135 assert(false);
136 return nullptr;
137 }
138
spirv_dim_to_texture_view_dimension(spv::Dim dim,bool arrayed)139 shaderc_spvc_texture_view_dimension spirv_dim_to_texture_view_dimension(
140 spv::Dim dim, bool arrayed) {
141 switch (dim) {
142 case spv::Dim::Dim1D:
143 return shaderc_spvc_texture_view_dimension_e1D;
144 case spv::Dim::Dim2D:
145 if (arrayed) {
146 return shaderc_spvc_texture_view_dimension_e2D_array;
147 } else {
148 return shaderc_spvc_texture_view_dimension_e2D;
149 }
150 case spv::Dim::Dim3D:
151 return shaderc_spvc_texture_view_dimension_e3D;
152 case spv::Dim::DimCube:
153 if (arrayed) {
154 return shaderc_spvc_texture_view_dimension_cube_array;
155 } else {
156 return shaderc_spvc_texture_view_dimension_cube;
157 }
158 default:
159 return shaderc_spvc_texture_view_dimension_undefined;
160 }
161 }
162
spirv_cross_base_type_to_texture_format_type(spirv_cross::SPIRType::BaseType type)163 shaderc_spvc_texture_format_type spirv_cross_base_type_to_texture_format_type(
164 spirv_cross::SPIRType::BaseType type) {
165 switch (type) {
166 case spirv_cross::SPIRType::Float:
167 return shaderc_spvc_texture_format_type_float;
168 case spirv_cross::SPIRType::Int:
169 return shaderc_spvc_texture_format_type_sint;
170 case spirv_cross::SPIRType::UInt:
171 return shaderc_spvc_texture_format_type_uint;
172 default:
173 return shaderc_spvc_texture_format_type_other;
174 }
175 }
176
spv_image_format_to_storage_texture_format(spv::ImageFormat format)177 shaderc_spvc_storage_texture_format spv_image_format_to_storage_texture_format(
178 spv::ImageFormat format) {
179 switch (format) {
180 case spv::ImageFormatR8:
181 return shaderc_spvc_storage_texture_format_r8unorm;
182 case spv::ImageFormatR8Snorm:
183 return shaderc_spvc_storage_texture_format_r8snorm;
184 case spv::ImageFormatR8ui:
185 return shaderc_spvc_storage_texture_format_r8uint;
186 case spv::ImageFormatR8i:
187 return shaderc_spvc_storage_texture_format_r8sint;
188 case spv::ImageFormatR16ui:
189 return shaderc_spvc_storage_texture_format_r16uint;
190 case spv::ImageFormatR16i:
191 return shaderc_spvc_storage_texture_format_r16sint;
192 case spv::ImageFormatR16f:
193 return shaderc_spvc_storage_texture_format_r16float;
194 case spv::ImageFormatRg8:
195 return shaderc_spvc_storage_texture_format_rg8unorm;
196 case spv::ImageFormatRg8Snorm:
197 return shaderc_spvc_storage_texture_format_rg8snorm;
198 case spv::ImageFormatRg8ui:
199 return shaderc_spvc_storage_texture_format_rg8uint;
200 case spv::ImageFormatRg8i:
201 return shaderc_spvc_storage_texture_format_rg8sint;
202 case spv::ImageFormatR32f:
203 return shaderc_spvc_storage_texture_format_r32float;
204 case spv::ImageFormatR32ui:
205 return shaderc_spvc_storage_texture_format_r32uint;
206 case spv::ImageFormatR32i:
207 return shaderc_spvc_storage_texture_format_r32sint;
208 case spv::ImageFormatRg16ui:
209 return shaderc_spvc_storage_texture_format_rg16uint;
210 case spv::ImageFormatRg16i:
211 return shaderc_spvc_storage_texture_format_rg16sint;
212 case spv::ImageFormatRg16f:
213 return shaderc_spvc_storage_texture_format_rg16float;
214 case spv::ImageFormatRgba8:
215 return shaderc_spvc_storage_texture_format_rgba8unorm;
216 case spv::ImageFormatRgba8Snorm:
217 return shaderc_spvc_storage_texture_format_rgba8snorm;
218 case spv::ImageFormatRgba8ui:
219 return shaderc_spvc_storage_texture_format_rgba8uint;
220 case spv::ImageFormatRgba8i:
221 return shaderc_spvc_storage_texture_format_rgba8sint;
222 case spv::ImageFormatRgb10A2:
223 return shaderc_spvc_storage_texture_format_rgb10a2unorm;
224 case spv::ImageFormatR11fG11fB10f:
225 return shaderc_spvc_storage_texture_format_rg11b10float;
226 case spv::ImageFormatRg32f:
227 return shaderc_spvc_storage_texture_format_rg32float;
228 case spv::ImageFormatRg32ui:
229 return shaderc_spvc_storage_texture_format_rg32uint;
230 case spv::ImageFormatRg32i:
231 return shaderc_spvc_storage_texture_format_rg32sint;
232 case spv::ImageFormatRgba16ui:
233 return shaderc_spvc_storage_texture_format_rgba16uint;
234 case spv::ImageFormatRgba16i:
235 return shaderc_spvc_storage_texture_format_rgba16sint;
236 case spv::ImageFormatRgba16f:
237 return shaderc_spvc_storage_texture_format_rgba16float;
238 case spv::ImageFormatRgba32f:
239 return shaderc_spvc_storage_texture_format_rgba32float;
240 case spv::ImageFormatRgba32ui:
241 return shaderc_spvc_storage_texture_format_rgba32uint;
242 case spv::ImageFormatRgba32i:
243 return shaderc_spvc_storage_texture_format_rgba32sint;
244 default:
245 return shaderc_spvc_storage_texture_format_undefined;
246 }
247 }
248
shaderc_spvc_spv_env_to_spv_target_env(shaderc_spvc_spv_env env)249 spv_target_env shaderc_spvc_spv_env_to_spv_target_env(
250 shaderc_spvc_spv_env env) {
251 switch (env) {
252 case shaderc_spvc_spv_env_universal_1_0:
253 return SPV_ENV_UNIVERSAL_1_0;
254 case shaderc_spvc_spv_env_vulkan_1_0:
255 return SPV_ENV_VULKAN_1_0;
256 case shaderc_spvc_spv_env_universal_1_1:
257 return SPV_ENV_UNIVERSAL_1_1;
258 case shaderc_spvc_spv_env_opencl_2_1:
259 return SPV_ENV_OPENCL_2_1;
260 case shaderc_spvc_spv_env_opencl_2_2:
261 return SPV_ENV_OPENCL_2_2;
262 case shaderc_spvc_spv_env_opengl_4_0:
263 return SPV_ENV_OPENGL_4_0;
264 case shaderc_spvc_spv_env_opengl_4_1:
265 return SPV_ENV_OPENGL_4_1;
266 case shaderc_spvc_spv_env_opengl_4_2:
267 return SPV_ENV_OPENGL_4_2;
268 case shaderc_spvc_spv_env_opengl_4_3:
269 return SPV_ENV_OPENGL_4_3;
270 case shaderc_spvc_spv_env_opengl_4_5:
271 return SPV_ENV_OPENGL_4_5;
272 case shaderc_spvc_spv_env_universal_1_2:
273 return SPV_ENV_UNIVERSAL_1_2;
274 case shaderc_spvc_spv_env_opencl_1_2:
275 return SPV_ENV_OPENCL_1_2;
276 case shaderc_spvc_spv_env_opencl_embedded_1_2:
277 return SPV_ENV_OPENCL_EMBEDDED_1_2;
278 case shaderc_spvc_spv_env_opencl_2_0:
279 return SPV_ENV_OPENCL_2_0;
280 case shaderc_spvc_spv_env_opencl_embedded_2_0:
281 return SPV_ENV_OPENCL_EMBEDDED_2_0;
282 case shaderc_spvc_spv_env_opencl_embedded_2_1:
283 return SPV_ENV_OPENCL_EMBEDDED_2_1;
284 case shaderc_spvc_spv_env_opencl_embedded_2_2:
285 return SPV_ENV_OPENCL_EMBEDDED_2_2;
286 case shaderc_spvc_spv_env_universal_1_3:
287 return SPV_ENV_UNIVERSAL_1_3;
288 case shaderc_spvc_spv_env_vulkan_1_1:
289 return SPV_ENV_VULKAN_1_1;
290 case shaderc_spvc_spv_env_webgpu_0:
291 return SPV_ENV_WEBGPU_0;
292 case shaderc_spvc_spv_env_universal_1_4:
293 return SPV_ENV_UNIVERSAL_1_4;
294 case shaderc_spvc_spv_env_vulkan_1_1_spirv_1_4:
295 return SPV_ENV_VULKAN_1_1_SPIRV_1_4;
296 case shaderc_spvc_spv_env_universal_1_5:
297 return SPV_ENV_UNIVERSAL_1_5;
298 case shaderc_spvc_spv_env_vulkan_1_2:
299 return SPV_ENV_VULKAN_1_2;
300 }
301 shaderc_spvc::ErrorLog(nullptr)
302 << "Attempted to convert unknown shaderc_spvc_spv_env value, " << env;
303 assert(false);
304 return SPV_ENV_UNIVERSAL_1_0;
305 }
306
get_location_info_impl(spirv_cross::Compiler * compiler,const spirv_cross::SmallVector<spirv_cross::Resource> & resources,shaderc_spvc_resource_location_info * locations,size_t * location_count)307 shaderc_spvc_status get_location_info_impl(
308 spirv_cross::Compiler* compiler,
309 const spirv_cross::SmallVector<spirv_cross::Resource>& resources,
310 shaderc_spvc_resource_location_info* locations, size_t* location_count) {
311 *location_count = resources.size();
312 if (!locations) return shaderc_spvc_status_success;
313
314 for (const auto& resource : resources) {
315 if (!compiler->get_decoration_bitset(resource.id)
316 .get(spv::DecorationLocation)) {
317 return shaderc_spvc_status_internal_error;
318 }
319 locations->id = resource.id;
320 if (compiler->get_decoration_bitset(resource.id)
321 .get(spv::DecorationLocation)) {
322 locations->location =
323 compiler->get_decoration(resource.id, spv::DecorationLocation);
324 locations->has_location = true;
325 } else {
326 locations->has_location = false;
327 }
328 locations++;
329 }
330 return shaderc_spvc_status_success;
331 }
332
333 } // namespace
334
shaderc_spvc_context_create()335 shaderc_spvc_context_t shaderc_spvc_context_create() {
336 return new (std::nothrow) shaderc_spvc_context;
337 }
338
shaderc_spvc_context_destroy(shaderc_spvc_context_t context)339 void shaderc_spvc_context_destroy(shaderc_spvc_context_t context) {
340 if (context) delete context;
341 }
342
shaderc_spvc_context_get_messages(const shaderc_spvc_context_t context)343 const char* shaderc_spvc_context_get_messages(
344 const shaderc_spvc_context_t context) {
345 for (const auto& message : context->messages) {
346 context->messages_string += message;
347 }
348 context->messages.clear();
349 return context->messages_string.c_str();
350 }
351
shaderc_spvc_context_get_compiler(const shaderc_spvc_context_t context,void ** compiler)352 shaderc_spvc_status shaderc_spvc_context_get_compiler(
353 const shaderc_spvc_context_t context, void** compiler) {
354 CHECK_CONTEXT(context);
355 CHECK_CROSS_COMPILER(context, context->cross_compiler);
356 CHECK_OUT_PARAM(context, compiler, "compiler");
357
358 *compiler = context->cross_compiler.get();
359 return shaderc_spvc_status_success;
360 }
361
shaderc_spvc_context_set_use_spvc_parser(shaderc_spvc_context_t context,bool b)362 shaderc_spvc_status shaderc_spvc_context_set_use_spvc_parser(
363 shaderc_spvc_context_t context, bool b) {
364 CHECK_CONTEXT(context);
365
366 context->use_spvc_parser = b;
367 return shaderc_spvc_status_success;
368 }
369
shaderc_spvc_compile_options_create(shaderc_spvc_spv_env source_env,shaderc_spvc_spv_env target_env)370 shaderc_spvc_compile_options_t shaderc_spvc_compile_options_create(
371 shaderc_spvc_spv_env source_env, shaderc_spvc_spv_env target_env) {
372 shaderc_spvc_compile_options_t options =
373 new (std::nothrow) shaderc_spvc_compile_options;
374 if (options) {
375 options->glsl.version = 0;
376 options->source_env = shaderc_spvc_spv_env_to_spv_target_env(source_env);
377 options->target_env = shaderc_spvc_spv_env_to_spv_target_env(target_env);
378 }
379 return options;
380 }
381
shaderc_spvc_compile_options_clone(shaderc_spvc_compile_options_t options)382 shaderc_spvc_compile_options_t shaderc_spvc_compile_options_clone(
383 shaderc_spvc_compile_options_t options) {
384 if (options) return new (std::nothrow) shaderc_spvc_compile_options(*options);
385 return nullptr;
386 }
387
shaderc_spvc_compile_options_destroy(shaderc_spvc_compile_options_t options)388 void shaderc_spvc_compile_options_destroy(
389 shaderc_spvc_compile_options_t options) {
390 if (options) delete options;
391 }
392
393 // DEPRECATED
shaderc_spvc_compile_options_set_source_env(shaderc_spvc_compile_options_t options,shaderc_target_env env,shaderc_env_version version)394 shaderc_spvc_status shaderc_spvc_compile_options_set_source_env(
395 shaderc_spvc_compile_options_t options, shaderc_target_env env,
396 shaderc_env_version version) {
397 CHECK_OPTIONS(nullptr, options);
398
399 options->source_env = spvc_private::get_spv_target_env(env, version);
400 return shaderc_spvc_status_success;
401 }
402
403 // DEPRECATED
shaderc_spvc_compile_options_set_target_env(shaderc_spvc_compile_options_t options,shaderc_target_env env,shaderc_env_version version)404 shaderc_spvc_status shaderc_spvc_compile_options_set_target_env(
405 shaderc_spvc_compile_options_t options, shaderc_target_env env,
406 shaderc_env_version version) {
407 CHECK_OPTIONS(nullptr, options);
408
409 options->target_env = spvc_private::get_spv_target_env(env, version);
410 return shaderc_spvc_status_success;
411 }
412
shaderc_spvc_compile_options_set_entry_point(shaderc_spvc_compile_options_t options,const char * entry_point)413 shaderc_spvc_status shaderc_spvc_compile_options_set_entry_point(
414 shaderc_spvc_compile_options_t options, const char* entry_point) {
415 CHECK_OPTIONS(nullptr, options);
416 CHECK_IN_PARAM(nullptr, entry_point, "entry_point");
417
418 options->entry_point = entry_point;
419 return shaderc_spvc_status_success;
420 }
421
shaderc_spvc_compile_options_set_remove_unused_variables(shaderc_spvc_compile_options_t options,bool b)422 shaderc_spvc_status shaderc_spvc_compile_options_set_remove_unused_variables(
423 shaderc_spvc_compile_options_t options, bool b) {
424 CHECK_OPTIONS(nullptr, options);
425
426 options->remove_unused_variables = b;
427 return shaderc_spvc_status_success;
428 }
429
shaderc_spvc_compile_options_set_robust_buffer_access_pass(shaderc_spvc_compile_options_t options,bool b)430 shaderc_spvc_status shaderc_spvc_compile_options_set_robust_buffer_access_pass(
431 shaderc_spvc_compile_options_t options, bool b) {
432 CHECK_OPTIONS(nullptr, options);
433
434 options->robust_buffer_access_pass = b;
435 return shaderc_spvc_status_success;
436 }
437
shaderc_spvc_compile_options_set_emit_line_directives(shaderc_spvc_compile_options_t options,bool b)438 shaderc_spvc_status shaderc_spvc_compile_options_set_emit_line_directives(
439 shaderc_spvc_compile_options_t options, bool b) {
440 CHECK_OPTIONS(nullptr, options);
441
442 options->glsl.emit_line_directives = b;
443 return shaderc_spvc_status_success;
444 }
445
shaderc_spvc_compile_options_set_vulkan_semantics(shaderc_spvc_compile_options_t options,bool b)446 shaderc_spvc_status shaderc_spvc_compile_options_set_vulkan_semantics(
447 shaderc_spvc_compile_options_t options, bool b) {
448 CHECK_OPTIONS(nullptr, options);
449
450 options->glsl.vulkan_semantics = b;
451 return shaderc_spvc_status_success;
452 }
453
shaderc_spvc_compile_options_set_separate_shader_objects(shaderc_spvc_compile_options_t options,bool b)454 shaderc_spvc_status shaderc_spvc_compile_options_set_separate_shader_objects(
455 shaderc_spvc_compile_options_t options, bool b) {
456 CHECK_OPTIONS(nullptr, options);
457
458 options->glsl.separate_shader_objects = b;
459 return shaderc_spvc_status_success;
460 }
461
shaderc_spvc_compile_options_set_flatten_ubo(shaderc_spvc_compile_options_t options,bool b)462 shaderc_spvc_status shaderc_spvc_compile_options_set_flatten_ubo(
463 shaderc_spvc_compile_options_t options, bool b) {
464 CHECK_OPTIONS(nullptr, options);
465
466 options->flatten_ubo = b;
467 return shaderc_spvc_status_success;
468 }
469
shaderc_spvc_compile_options_set_glsl_language_version(shaderc_spvc_compile_options_t options,uint32_t version)470 shaderc_spvc_status shaderc_spvc_compile_options_set_glsl_language_version(
471 shaderc_spvc_compile_options_t options, uint32_t version) {
472 CHECK_OPTIONS(nullptr, options);
473
474 options->glsl.version = version;
475 return shaderc_spvc_status_success;
476 }
477
478 shaderc_spvc_status
shaderc_spvc_compile_options_set_flatten_multidimensional_arrays(shaderc_spvc_compile_options_t options,bool b)479 shaderc_spvc_compile_options_set_flatten_multidimensional_arrays(
480 shaderc_spvc_compile_options_t options, bool b) {
481 CHECK_OPTIONS(nullptr, options);
482
483 options->glsl.flatten_multidimensional_arrays = b;
484 return shaderc_spvc_status_success;
485 }
486
487 shaderc_spvc_status
shaderc_spvc_compile_options_set_force_zero_initialized_variables(shaderc_spvc_compile_options_t options,bool b)488 shaderc_spvc_compile_options_set_force_zero_initialized_variables(
489 shaderc_spvc_compile_options_t options, bool b) {
490 CHECK_OPTIONS(nullptr, options);
491
492 options->glsl.force_zero_initialized_variables = b;
493 return shaderc_spvc_status_success;
494 }
495
shaderc_spvc_compile_options_set_es(shaderc_spvc_compile_options_t options,bool b)496 shaderc_spvc_status shaderc_spvc_compile_options_set_es(
497 shaderc_spvc_compile_options_t options, bool b) {
498 CHECK_OPTIONS(nullptr, options);
499
500 options->forced_es_setting = b;
501 options->force_es = true;
502 return shaderc_spvc_status_success;
503 }
504
505 shaderc_spvc_status
shaderc_spvc_compile_options_set_glsl_emit_push_constant_as_ubo(shaderc_spvc_compile_options_t options,bool b)506 shaderc_spvc_compile_options_set_glsl_emit_push_constant_as_ubo(
507 shaderc_spvc_compile_options_t options, bool b) {
508 CHECK_OPTIONS(nullptr, options);
509
510 options->glsl.emit_push_constant_as_uniform_buffer = b;
511 return shaderc_spvc_status_success;
512 }
513
shaderc_spvc_compile_options_set_msl_language_version(shaderc_spvc_compile_options_t options,uint32_t version)514 shaderc_spvc_status shaderc_spvc_compile_options_set_msl_language_version(
515 shaderc_spvc_compile_options_t options, uint32_t version) {
516 CHECK_OPTIONS(nullptr, options);
517
518 options->msl.msl_version = version;
519 return shaderc_spvc_status_success;
520 }
521
522 shaderc_spvc_status
shaderc_spvc_compile_options_set_msl_swizzle_texture_samples(shaderc_spvc_compile_options_t options,bool b)523 shaderc_spvc_compile_options_set_msl_swizzle_texture_samples(
524 shaderc_spvc_compile_options_t options, bool b) {
525 CHECK_OPTIONS(nullptr, options);
526
527 options->msl.swizzle_texture_samples = b;
528 return shaderc_spvc_status_success;
529 }
530
shaderc_spvc_compile_options_set_msl_platform(shaderc_spvc_compile_options_t options,shaderc_spvc_msl_platform platform)531 shaderc_spvc_status shaderc_spvc_compile_options_set_msl_platform(
532 shaderc_spvc_compile_options_t options,
533 shaderc_spvc_msl_platform platform) {
534 CHECK_OPTIONS(nullptr, options);
535
536 switch (platform) {
537 case shaderc_spvc_msl_platform_ios:
538 options->msl.platform = spirv_cross::CompilerMSL::Options::iOS;
539 break;
540 case shaderc_spvc_msl_platform_macos:
541 options->msl.platform = spirv_cross::CompilerMSL::Options::macOS;
542 break;
543 }
544 return shaderc_spvc_status_success;
545 }
546
shaderc_spvc_compile_options_set_msl_pad_fragment_output(shaderc_spvc_compile_options_t options,bool b)547 shaderc_spvc_status shaderc_spvc_compile_options_set_msl_pad_fragment_output(
548 shaderc_spvc_compile_options_t options, bool b) {
549 CHECK_OPTIONS(nullptr, options);
550
551 options->msl.pad_fragment_output_components = b;
552 return shaderc_spvc_status_success;
553 }
554
shaderc_spvc_compile_options_set_msl_capture(shaderc_spvc_compile_options_t options,bool b)555 shaderc_spvc_status shaderc_spvc_compile_options_set_msl_capture(
556 shaderc_spvc_compile_options_t options, bool b) {
557 CHECK_OPTIONS(nullptr, options);
558
559 options->msl.capture_output_to_buffer = b;
560 return shaderc_spvc_status_success;
561 }
562
shaderc_spvc_compile_options_set_msl_domain_lower_left(shaderc_spvc_compile_options_t options,bool b)563 shaderc_spvc_status shaderc_spvc_compile_options_set_msl_domain_lower_left(
564 shaderc_spvc_compile_options_t options, bool b) {
565 CHECK_OPTIONS(nullptr, options);
566
567 options->msl.tess_domain_origin_lower_left = b;
568 return shaderc_spvc_status_success;
569 }
570
shaderc_spvc_compile_options_set_msl_argument_buffers(shaderc_spvc_compile_options_t options,bool b)571 shaderc_spvc_status shaderc_spvc_compile_options_set_msl_argument_buffers(
572 shaderc_spvc_compile_options_t options, bool b) {
573 CHECK_OPTIONS(nullptr, options);
574
575 options->msl.argument_buffers = b;
576 return shaderc_spvc_status_success;
577 }
578
579 shaderc_spvc_status
shaderc_spvc_compile_options_set_msl_discrete_descriptor_sets(shaderc_spvc_compile_options_t options,const uint32_t * descriptors,size_t num_descriptors)580 shaderc_spvc_compile_options_set_msl_discrete_descriptor_sets(
581 shaderc_spvc_compile_options_t options, const uint32_t* descriptors,
582 size_t num_descriptors) {
583 CHECK_OPTIONS(nullptr, options);
584
585 options->msl_discrete_descriptor_sets.resize(num_descriptors);
586 std::copy_n(descriptors, num_descriptors,
587 options->msl_discrete_descriptor_sets.begin());
588 return shaderc_spvc_status_success;
589 }
590
591 shaderc_spvc_status
shaderc_spvc_compile_options_set_msl_enable_point_size_builtin(shaderc_spvc_compile_options_t options,bool b)592 shaderc_spvc_compile_options_set_msl_enable_point_size_builtin(
593 shaderc_spvc_compile_options_t options, bool b) {
594 CHECK_OPTIONS(nullptr, options);
595
596 options->msl.enable_point_size_builtin = b;
597 return shaderc_spvc_status_success;
598 }
599
600 shaderc_spvc_status
shaderc_spvc_compile_options_set_msl_buffer_size_buffer_index(shaderc_spvc_compile_options_t options,uint32_t index)601 shaderc_spvc_compile_options_set_msl_buffer_size_buffer_index(
602 shaderc_spvc_compile_options_t options, uint32_t index) {
603 CHECK_OPTIONS(nullptr, options);
604
605 options->msl.buffer_size_buffer_index = index;
606 return shaderc_spvc_status_success;
607 }
608
shaderc_spvc_compile_options_set_hlsl_shader_model(shaderc_spvc_compile_options_t options,uint32_t model)609 shaderc_spvc_status shaderc_spvc_compile_options_set_hlsl_shader_model(
610 shaderc_spvc_compile_options_t options, uint32_t model) {
611 CHECK_OPTIONS(nullptr, options);
612
613 options->hlsl.shader_model = model;
614 return shaderc_spvc_status_success;
615 }
616
shaderc_spvc_compile_options_set_hlsl_point_size_compat(shaderc_spvc_compile_options_t options,bool b)617 shaderc_spvc_status shaderc_spvc_compile_options_set_hlsl_point_size_compat(
618 shaderc_spvc_compile_options_t options, bool b) {
619 CHECK_OPTIONS(nullptr, options);
620
621 options->hlsl.point_size_compat = b;
622 return shaderc_spvc_status_success;
623 }
624
shaderc_spvc_compile_options_set_hlsl_point_coord_compat(shaderc_spvc_compile_options_t options,bool b)625 shaderc_spvc_status shaderc_spvc_compile_options_set_hlsl_point_coord_compat(
626 shaderc_spvc_compile_options_t options, bool b) {
627 CHECK_OPTIONS(nullptr, options);
628
629 options->hlsl.point_coord_compat = b;
630 return shaderc_spvc_status_success;
631 }
632
shaderc_spvc_compile_options_set_fixup_clipspace(shaderc_spvc_compile_options_t options,bool b)633 shaderc_spvc_status shaderc_spvc_compile_options_set_fixup_clipspace(
634 shaderc_spvc_compile_options_t options, bool b) {
635 CHECK_OPTIONS(nullptr, options);
636
637 options->glsl.vertex.fixup_clipspace = b;
638 return shaderc_spvc_status_success;
639 }
640
shaderc_spvc_compile_options_set_flip_vert_y(shaderc_spvc_compile_options_t options,bool b)641 shaderc_spvc_status shaderc_spvc_compile_options_set_flip_vert_y(
642 shaderc_spvc_compile_options_t options, bool b) {
643 CHECK_OPTIONS(nullptr, options);
644
645 options->glsl.vertex.flip_vert_y = b;
646 return shaderc_spvc_status_success;
647 }
648
shaderc_spvc_compile_options_set_validate(shaderc_spvc_compile_options_t options,bool b)649 shaderc_spvc_status shaderc_spvc_compile_options_set_validate(
650 shaderc_spvc_compile_options_t options, bool b) {
651 CHECK_OPTIONS(nullptr, options);
652
653 options->validate = b;
654 return shaderc_spvc_status_success;
655 }
656
shaderc_spvc_compile_options_set_optimize(shaderc_spvc_compile_options_t options,bool b)657 shaderc_spvc_status shaderc_spvc_compile_options_set_optimize(
658 shaderc_spvc_compile_options_t options, bool b) {
659 CHECK_OPTIONS(nullptr, options);
660
661 options->optimize = b;
662 return shaderc_spvc_status_success;
663 }
664
shaderc_spvc_compile_options_set_for_fuzzing(shaderc_spvc_compile_options_t options,const uint8_t * data,size_t size)665 size_t shaderc_spvc_compile_options_set_for_fuzzing(
666 shaderc_spvc_compile_options_t options, const uint8_t* data, size_t size) {
667 if (!options || !data || size < sizeof(*options)) return 0;
668
669 memcpy(static_cast<void*>(options), data, sizeof(*options));
670 return sizeof(*options);
671 }
672
shaderc_spvc_initialize_impl(const shaderc_spvc_context_t context,const uint32_t * source,size_t source_len,shaderc_spvc_compile_options_t options,shaderc_spvc_status (* generator)(const shaderc_spvc_context_t,const uint32_t *,size_t,shaderc_spvc_compile_options_t))673 shaderc_spvc_status shaderc_spvc_initialize_impl(
674 const shaderc_spvc_context_t context, const uint32_t* source,
675 size_t source_len, shaderc_spvc_compile_options_t options,
676 shaderc_spvc_status (*generator)(const shaderc_spvc_context_t,
677 const uint32_t*, size_t,
678 shaderc_spvc_compile_options_t)) {
679 shaderc_spvc_status status = spvc_private::validate_and_translate_spirv(
680 context, source, source_len, options, &context->intermediate_shader);
681 if (status != shaderc_spvc_status_success) return status;
682
683 status = generator(context, context->intermediate_shader.data(),
684 context->intermediate_shader.size(), options);
685 if (status != shaderc_spvc_status_success) return status;
686
687 return shaderc_spvc_status_success;
688 }
689
shaderc_spvc_initialize_for_glsl(const shaderc_spvc_context_t context,const uint32_t * source,size_t source_len,shaderc_spvc_compile_options_t options)690 shaderc_spvc_status shaderc_spvc_initialize_for_glsl(
691 const shaderc_spvc_context_t context, const uint32_t* source,
692 size_t source_len, shaderc_spvc_compile_options_t options) {
693 CHECK_CONTEXT(context);
694 CHECK_OPTIONS(context, options);
695 CHECK_IN_PARAM(context, source, "source");
696
697 context->target_lang = SPVC_TARGET_LANG_GLSL;
698 return shaderc_spvc_initialize_impl(context, source, source_len, options,
699 spvc_private::generate_glsl_compiler);
700 }
701
shaderc_spvc_initialize_for_hlsl(const shaderc_spvc_context_t context,const uint32_t * source,size_t source_len,shaderc_spvc_compile_options_t options)702 shaderc_spvc_status shaderc_spvc_initialize_for_hlsl(
703 const shaderc_spvc_context_t context, const uint32_t* source,
704 size_t source_len, shaderc_spvc_compile_options_t options) {
705 CHECK_CONTEXT(context);
706 CHECK_OPTIONS(context, options);
707 CHECK_IN_PARAM(context, source, "source");
708
709 context->target_lang = SPVC_TARGET_LANG_HLSL;
710 return shaderc_spvc_initialize_impl(context, source, source_len, options,
711 spvc_private::generate_hlsl_compiler);
712 }
713
shaderc_spvc_initialize_for_msl(const shaderc_spvc_context_t context,const uint32_t * source,size_t source_len,shaderc_spvc_compile_options_t options)714 shaderc_spvc_status shaderc_spvc_initialize_for_msl(
715 const shaderc_spvc_context_t context, const uint32_t* source,
716 size_t source_len, shaderc_spvc_compile_options_t options) {
717 CHECK_CONTEXT(context);
718 CHECK_OPTIONS(context, options);
719 CHECK_IN_PARAM(context, source, "source");
720
721 context->target_lang = SPVC_TARGET_LANG_MSL;
722 return shaderc_spvc_initialize_impl(context, source, source_len, options,
723 spvc_private::generate_msl_compiler);
724 }
725
shaderc_spvc_initialize_for_vulkan(const shaderc_spvc_context_t context,const uint32_t * source,size_t source_len,shaderc_spvc_compile_options_t options)726 shaderc_spvc_status shaderc_spvc_initialize_for_vulkan(
727 const shaderc_spvc_context_t context, const uint32_t* source,
728 size_t source_len, shaderc_spvc_compile_options_t options) {
729 CHECK_CONTEXT(context);
730 CHECK_OPTIONS(context, options);
731 CHECK_IN_PARAM(context, source, "source");
732
733 context->target_lang = SPVC_TARGET_LANG_VULKAN;
734 return shaderc_spvc_initialize_impl(context, source, source_len, options,
735 spvc_private::generate_vulkan_compiler);
736 }
737
shaderc_spvc_compile_shader(const shaderc_spvc_context_t context,shaderc_spvc_compilation_result_t result)738 shaderc_spvc_status shaderc_spvc_compile_shader(
739 const shaderc_spvc_context_t context,
740 shaderc_spvc_compilation_result_t result) {
741 CHECK_CONTEXT(context);
742 CHECK_CROSS_COMPILER(context, context->cross_compiler);
743
744 if (context->target_lang == SPVC_TARGET_LANG_UNKNOWN) {
745 shaderc_spvc::ErrorLog(context)
746 << "Invoked compile_shader with unknown language";
747 return shaderc_spvc_status_configuration_error;
748 }
749
750 if (context->target_lang == SPVC_TARGET_LANG_VULKAN) {
751 // No actual cross compilation is needed, since the intermediate shader is
752 // already in Vulkan SPIR->V.
753 result->binary_output = context->intermediate_shader;
754 return shaderc_spvc_status_success;
755 } else {
756 shaderc_spvc_status status =
757 spvc_private::generate_shader(context->cross_compiler.get(), result);
758 if (status != shaderc_spvc_status_success) {
759 shaderc_spvc::ErrorLog(context) << "Compilation failed. Partial source:";
760 if (context->target_lang == SPVC_TARGET_LANG_GLSL) {
761 spirv_cross::CompilerGLSL* cast_compiler =
762 reinterpret_cast<spirv_cross::CompilerGLSL*>(
763 context->cross_compiler.get());
764 shaderc_spvc::ErrorLog(context) << cast_compiler->get_partial_source();
765 } else if (context->target_lang == SPVC_TARGET_LANG_HLSL) {
766 spirv_cross::CompilerHLSL* cast_compiler =
767 reinterpret_cast<spirv_cross::CompilerHLSL*>(
768 context->cross_compiler.get());
769 shaderc_spvc::ErrorLog(context) << cast_compiler->get_partial_source();
770 } else if (context->target_lang == SPVC_TARGET_LANG_MSL) {
771 spirv_cross::CompilerMSL* cast_compiler =
772 reinterpret_cast<spirv_cross::CompilerMSL*>(
773 context->cross_compiler.get());
774 shaderc_spvc::ErrorLog(context) << cast_compiler->get_partial_source();
775 } else {
776 shaderc_spvc::ErrorLog(context)
777 << "Unexpected target language in context";
778 }
779 context->cross_compiler.reset();
780 }
781 return status;
782 }
783 }
784
shaderc_spvc_set_decoration(const shaderc_spvc_context_t context,uint32_t id,shaderc_spvc_decoration decoration,uint32_t argument)785 shaderc_spvc_status shaderc_spvc_set_decoration(
786 const shaderc_spvc_context_t context, uint32_t id,
787 shaderc_spvc_decoration decoration, uint32_t argument) {
788 CHECK_CONTEXT(context);
789 CHECK_CROSS_COMPILER(context, context->cross_compiler);
790
791 spv::Decoration spirv_cross_decoration;
792 shaderc_spvc_status status =
793 spvc_private::shaderc_spvc_decoration_to_spirv_cross_decoration(
794 decoration, &spirv_cross_decoration);
795 if (status == shaderc_spvc_status_success) {
796 context->cross_compiler->set_decoration(static_cast<spirv_cross::ID>(id),
797 spirv_cross_decoration, argument);
798 } else {
799 shaderc_spvc::ErrorLog(context) << "Decoration Conversion failed. "
800 "shaderc_spvc_decoration not supported.";
801 }
802 return status;
803 }
804
shaderc_spvc_get_decoration(const shaderc_spvc_context_t context,uint32_t id,shaderc_spvc_decoration decoration,uint32_t * value)805 shaderc_spvc_status shaderc_spvc_get_decoration(
806 const shaderc_spvc_context_t context, uint32_t id,
807 shaderc_spvc_decoration decoration, uint32_t* value) {
808 CHECK_CONTEXT(context);
809 CHECK_CROSS_COMPILER(context, context->cross_compiler);
810 CHECK_OUT_PARAM(context, value, "value");
811
812 spv::Decoration spirv_cross_decoration;
813 shaderc_spvc_status status =
814 spvc_private::shaderc_spvc_decoration_to_spirv_cross_decoration(
815 decoration, &spirv_cross_decoration);
816 if (status != shaderc_spvc_status_success) {
817 shaderc_spvc::ErrorLog(context) << "Decoration conversion failed. "
818 "shaderc_spvc_decoration not supported.";
819
820 return status;
821 }
822
823 *value = context->cross_compiler->get_decoration(
824 static_cast<spirv_cross::ID>(id), spirv_cross_decoration);
825 if (*value == 0) {
826 shaderc_spvc::ErrorLog(context)
827 << "Getting decoration failed. id not found.";
828 return shaderc_spvc_status_compilation_error;
829 }
830
831 return shaderc_spvc_status_success;
832 }
833
shaderc_spvc_unset_decoration(const shaderc_spvc_context_t context,uint32_t id,shaderc_spvc_decoration decoration)834 shaderc_spvc_status shaderc_spvc_unset_decoration(
835 const shaderc_spvc_context_t context, uint32_t id,
836 shaderc_spvc_decoration decoration) {
837 CHECK_CONTEXT(context);
838 CHECK_CROSS_COMPILER(context, context->cross_compiler);
839
840 spv::Decoration spirv_cross_decoration;
841 shaderc_spvc_status status =
842 spvc_private::shaderc_spvc_decoration_to_spirv_cross_decoration(
843 decoration, &spirv_cross_decoration);
844 if (status == shaderc_spvc_status_success) {
845 context->cross_compiler->unset_decoration(static_cast<spirv_cross::ID>(id),
846 spirv_cross_decoration);
847 } else {
848 shaderc_spvc::ErrorLog(context) << "Decoration conversion failed. "
849 "shaderc_spvc_decoration not supported.";
850 }
851
852 return status;
853 }
854
shaderc_spvc_get_combined_image_samplers(const shaderc_spvc_context_t context,shaderc_spvc_combined_image_sampler * samplers,size_t * num_samplers)855 shaderc_spvc_status shaderc_spvc_get_combined_image_samplers(
856 const shaderc_spvc_context_t context,
857 shaderc_spvc_combined_image_sampler* samplers, size_t* num_samplers) {
858 CHECK_CONTEXT(context);
859 CHECK_CROSS_COMPILER(context, context->cross_compiler);
860 CHECK_OUT_PARAM(context, num_samplers, "num_samplers");
861
862 *num_samplers = context->cross_compiler->get_combined_image_samplers().size();
863 if (!samplers) return shaderc_spvc_status_success;
864
865 for (const auto& combined :
866 context->cross_compiler->get_combined_image_samplers()) {
867 samplers->combined_id = combined.combined_id;
868 samplers->image_id = combined.image_id;
869 samplers->sampler_id = combined.sampler_id;
870 samplers++;
871 }
872 return shaderc_spvc_status_success;
873 }
874
shaderc_spvc_set_name(const shaderc_spvc_context_t context,uint32_t id,const char * name)875 shaderc_spvc_status shaderc_spvc_set_name(const shaderc_spvc_context_t context,
876 uint32_t id, const char* name) {
877 CHECK_CONTEXT(context);
878 CHECK_CROSS_COMPILER(context, context->cross_compiler);
879 CHECK_IN_PARAM(context, name, "name");
880
881 context->cross_compiler->set_name(id, name);
882 return shaderc_spvc_status_success;
883 }
884
shaderc_spvc_add_msl_resource_binding(const shaderc_spvc_context_t context,const shaderc_spvc_msl_resource_binding binding)885 shaderc_spvc_status shaderc_spvc_add_msl_resource_binding(
886 const shaderc_spvc_context_t context,
887 const shaderc_spvc_msl_resource_binding binding) {
888 CHECK_CONTEXT(context);
889 CHECK_CROSS_COMPILER(context, context->cross_compiler);
890 if (context->target_lang != SPVC_TARGET_LANG_MSL) {
891 shaderc_spvc::ErrorLog(context)
892 << "Invoked add_msl_resource_binding when target language was not MSL";
893 return shaderc_spvc_status_configuration_error;
894 }
895
896 spirv_cross::MSLResourceBinding cross_binding;
897 cross_binding.stage = spvc_model_to_spv_model(binding.stage);
898 cross_binding.binding = binding.binding;
899 cross_binding.desc_set = binding.desc_set;
900 cross_binding.msl_buffer = binding.msl_buffer;
901 cross_binding.msl_texture = binding.msl_texture;
902 cross_binding.msl_sampler = binding.msl_sampler;
903 reinterpret_cast<spirv_cross::CompilerMSL*>(context->cross_compiler.get())
904 ->add_msl_resource_binding(cross_binding);
905
906 return shaderc_spvc_status_success;
907 }
908
shaderc_spvc_get_workgroup_size(const shaderc_spvc_context_t context,const char * function_name,shaderc_spvc_execution_model execution_model,shaderc_spvc_workgroup_size * workgroup_size)909 shaderc_spvc_status shaderc_spvc_get_workgroup_size(
910 const shaderc_spvc_context_t context, const char* function_name,
911 shaderc_spvc_execution_model execution_model,
912 shaderc_spvc_workgroup_size* workgroup_size) {
913 CHECK_CONTEXT(context);
914 CHECK_CROSS_COMPILER(context, context->cross_compiler);
915 CHECK_IN_PARAM(context, function_name, "function_name");
916 CHECK_OUT_PARAM(context, workgroup_size, "workgroup_size");
917
918 const auto& cross_size =
919 context->cross_compiler
920 ->get_entry_point(function_name,
921 spvc_model_to_spv_model(execution_model))
922 .workgroup_size;
923 workgroup_size->x = cross_size.x;
924 workgroup_size->y = cross_size.y;
925 workgroup_size->z = cross_size.z;
926 workgroup_size->constant = cross_size.constant;
927
928 return shaderc_spvc_status_success;
929 }
930
shaderc_spvc_needs_buffer_size_buffer(const shaderc_spvc_context_t context,bool * b)931 shaderc_spvc_status shaderc_spvc_needs_buffer_size_buffer(
932 const shaderc_spvc_context_t context, bool* b) {
933 CHECK_CONTEXT(context);
934 CHECK_CROSS_COMPILER(context, context->cross_compiler);
935 CHECK_OUT_PARAM(context, b, "b");
936 if (context->target_lang != SPVC_TARGET_LANG_MSL) {
937 shaderc_spvc::ErrorLog(context)
938 << "Invoked needs_buffer_size_buffer when target language was not MSL";
939 return shaderc_spvc_status_configuration_error;
940 }
941
942 *b =
943 reinterpret_cast<spirv_cross::CompilerMSL*>(context->cross_compiler.get())
944 ->needs_buffer_size_buffer();
945 return shaderc_spvc_status_success;
946 }
947
shaderc_spvc_build_combined_image_samplers(const shaderc_spvc_context_t context)948 shaderc_spvc_status shaderc_spvc_build_combined_image_samplers(
949 const shaderc_spvc_context_t context) {
950 CHECK_CONTEXT(context);
951 CHECK_CROSS_COMPILER(context, context->cross_compiler);
952
953 context->cross_compiler->build_combined_image_samplers();
954 return shaderc_spvc_status_success;
955 }
956
shaderc_spvc_get_execution_model(const shaderc_spvc_context_t context,shaderc_spvc_execution_model * execution_model)957 shaderc_spvc_status shaderc_spvc_get_execution_model(
958 const shaderc_spvc_context_t context,
959 shaderc_spvc_execution_model* execution_model) {
960 CHECK_CONTEXT(context);
961 CHECK_CROSS_COMPILER(context, context->cross_compiler);
962 CHECK_OUT_PARAM(context, execution_model, "execution_model");
963
964 auto spirv_model = context->cross_compiler->get_execution_model();
965 *execution_model = spv_model_to_spvc_model(spirv_model);
966 if (*execution_model == shaderc_spvc_execution_model_invalid) {
967 shaderc_spvc::ErrorLog(context)
968 << "Shader execution model appears to be of an unsupported type";
969 return shaderc_spvc_status_internal_error;
970 }
971
972 return shaderc_spvc_status_success;
973 }
974
shaderc_spvc_get_push_constant_buffer_count(const shaderc_spvc_context_t context,size_t * count)975 shaderc_spvc_status shaderc_spvc_get_push_constant_buffer_count(
976 const shaderc_spvc_context_t context, size_t* count) {
977 CHECK_CONTEXT(context);
978 CHECK_CROSS_COMPILER(context, context->cross_compiler);
979 CHECK_OUT_PARAM(context, count, "count");
980
981 *count = context->cross_compiler->get_shader_resources()
982 .push_constant_buffers.size();
983 return shaderc_spvc_status_success;
984 }
985
shaderc_spvc_get_binding_info(const shaderc_spvc_context_t context,shaderc_spvc_shader_resource resource,shaderc_spvc_binding_type binding_type,shaderc_spvc_binding_info * bindings,size_t * binding_count)986 shaderc_spvc_status shaderc_spvc_get_binding_info(
987 const shaderc_spvc_context_t context, shaderc_spvc_shader_resource resource,
988 shaderc_spvc_binding_type binding_type, shaderc_spvc_binding_info* bindings,
989 size_t* binding_count) {
990 CHECK_CONTEXT(context);
991 CHECK_CROSS_COMPILER(context, context->cross_compiler);
992 CHECK_OUT_PARAM(context, binding_count, "binding_count");
993
994 auto* compiler = context->cross_compiler.get();
995 const auto& resources = compiler->get_shader_resources();
996 const auto* shader_resources = get_shader_resources(resources, resource);
997 *binding_count = shader_resources->size();
998 if (!bindings) return shaderc_spvc_status_success;
999
1000 for (const auto& shader_resource : *shader_resources) {
1001 bindings->texture_dimension = shaderc_spvc_texture_view_dimension_undefined;
1002 bindings->texture_component_type = shaderc_spvc_texture_format_type_float;
1003
1004 if (!compiler->get_decoration_bitset(shader_resource.id)
1005 .get(spv::DecorationBinding)) {
1006 shaderc_spvc::ErrorLog(context)
1007 << "Unable to get binding decoration for shader resource";
1008 return shaderc_spvc_status_internal_error;
1009 }
1010 uint32_t binding_decoration =
1011 compiler->get_decoration(shader_resource.id, spv::DecorationBinding);
1012 bindings->binding = binding_decoration;
1013
1014 if (!compiler->get_decoration_bitset(shader_resource.id)
1015 .get(spv::DecorationDescriptorSet)) {
1016 shaderc_spvc::ErrorLog(context)
1017 << "Unable to get descriptor set decoration for shader resource";
1018 return shaderc_spvc_status_internal_error;
1019 }
1020 uint32_t descriptor_set_decoration = compiler->get_decoration(
1021 shader_resource.id, spv::DecorationDescriptorSet);
1022 bindings->set = descriptor_set_decoration;
1023
1024 bindings->id = shader_resource.id;
1025 bindings->base_type_id = shader_resource.base_type_id;
1026
1027 switch (binding_type) {
1028 case shaderc_spvc_binding_type_sampled_texture: {
1029 spirv_cross::SPIRType::ImageType imageType =
1030 compiler->get_type(bindings->base_type_id).image;
1031 spirv_cross::SPIRType::BaseType textureComponentType =
1032 compiler->get_type(imageType.type).basetype;
1033 bindings->multisampled = imageType.ms;
1034 bindings->texture_dimension = spirv_dim_to_texture_view_dimension(
1035 imageType.dim, imageType.arrayed);
1036 bindings->texture_component_type =
1037 spirv_cross_base_type_to_texture_format_type(textureComponentType);
1038 bindings->binding_type = binding_type;
1039 } break;
1040 case shaderc_spvc_binding_type_storage_buffer: {
1041 // Differentiate between readonly storage bindings and writable ones
1042 // based on the NonWritable decoration
1043 spirv_cross::Bitset flags =
1044 compiler->get_buffer_block_flags(shader_resource.id);
1045 if (flags.get(spv::DecorationNonWritable)) {
1046 bindings->binding_type =
1047 shaderc_spvc_binding_type_readonly_storage_buffer;
1048 } else {
1049 bindings->binding_type = shaderc_spvc_binding_type_storage_buffer;
1050 }
1051 } break;
1052 case shaderc_spvc_binding_type_storage_texture: {
1053 spirv_cross::Bitset flags = compiler->get_decoration_bitset(shader_resource.id);
1054 if (flags.get(spv::DecorationNonReadable)) {
1055 bindings->binding_type = shaderc_spvc_binding_type_writeonly_storage_texture;
1056 } else if (flags.get(spv::DecorationNonWritable)) {
1057 bindings->binding_type = shaderc_spvc_binding_type_readonly_storage_texture;
1058 } else {
1059 bindings->binding_type = shaderc_spvc_binding_type_storage_texture;
1060 }
1061 spirv_cross::SPIRType::ImageType imageType =
1062 compiler->get_type(bindings->base_type_id).image;
1063 bindings->storage_texture_format =
1064 spv_image_format_to_storage_texture_format(imageType.format);
1065 bindings->texture_dimension = spirv_dim_to_texture_view_dimension(
1066 imageType.dim, imageType.arrayed);
1067 bindings->multisampled = imageType.ms;
1068 } break;
1069 default:
1070 bindings->binding_type = binding_type;
1071 }
1072 bindings++;
1073 }
1074
1075 return shaderc_spvc_status_success;
1076 }
1077
shaderc_spvc_get_input_stage_location_info(const shaderc_spvc_context_t context,shaderc_spvc_resource_location_info * locations,size_t * location_count)1078 shaderc_spvc_status shaderc_spvc_get_input_stage_location_info(
1079 const shaderc_spvc_context_t context,
1080 shaderc_spvc_resource_location_info* locations, size_t* location_count) {
1081 CHECK_CONTEXT(context);
1082 CHECK_CROSS_COMPILER(context, context->cross_compiler);
1083 CHECK_OUT_PARAM(context, location_count, "location_count");
1084
1085 auto* compiler = context->cross_compiler.get();
1086 shaderc_spvc_status status = get_location_info_impl(
1087 compiler, compiler->get_shader_resources().stage_inputs, locations,
1088 location_count);
1089 if (status != shaderc_spvc_status_success) {
1090 shaderc_spvc::ErrorLog(context)
1091 << "Unable to get location decoration for stage input";
1092 }
1093
1094 return status;
1095 }
1096
shaderc_spvc_get_output_stage_location_info(const shaderc_spvc_context_t context,shaderc_spvc_resource_location_info * locations,size_t * location_count)1097 shaderc_spvc_status shaderc_spvc_get_output_stage_location_info(
1098 const shaderc_spvc_context_t context,
1099 shaderc_spvc_resource_location_info* locations, size_t* location_count) {
1100 CHECK_CONTEXT(context);
1101 CHECK_CROSS_COMPILER(context, context->cross_compiler);
1102 CHECK_OUT_PARAM(context, location_count, "location_count");
1103
1104 auto* compiler = context->cross_compiler.get();
1105 shaderc_spvc_status status = get_location_info_impl(
1106 compiler, compiler->get_shader_resources().stage_outputs, locations,
1107 location_count);
1108 if (status != shaderc_spvc_status_success) {
1109 shaderc_spvc::ErrorLog(context)
1110 << "Unable to get location decoration for stage output";
1111 }
1112
1113 return status;
1114 }
1115
shaderc_spvc_get_output_stage_type_info(const shaderc_spvc_context_t context,shaderc_spvc_resource_type_info * types,size_t * type_count)1116 shaderc_spvc_status shaderc_spvc_get_output_stage_type_info(
1117 const shaderc_spvc_context_t context,
1118 shaderc_spvc_resource_type_info* types, size_t* type_count) {
1119 CHECK_CONTEXT(context);
1120 CHECK_CROSS_COMPILER(context, context->cross_compiler);
1121 CHECK_OUT_PARAM(context, type_count, "type_count");
1122
1123 auto* compiler = context->cross_compiler.get();
1124 const auto& resources = compiler->get_shader_resources().stage_outputs;
1125
1126 *type_count = resources.size();
1127 if (!types) return shaderc_spvc_status_success;
1128
1129 for (const auto& resource : resources) {
1130 if (!compiler->get_decoration_bitset(resource.id)
1131 .get(spv::DecorationLocation)) {
1132 shaderc_spvc::ErrorLog(context)
1133 << "Unable to get location decoration for stage output";
1134 return shaderc_spvc_status_internal_error;
1135 }
1136
1137 types->location =
1138 compiler->get_decoration(resource.id, spv::DecorationLocation);
1139 spirv_cross::SPIRType::BaseType base_type =
1140 compiler->get_type(resource.base_type_id).basetype;
1141 types->type = spirv_cross_base_type_to_texture_format_type(base_type);
1142 types++;
1143 }
1144
1145 return shaderc_spvc_status_success;
1146 }
1147
shaderc_spvc_result_create()1148 shaderc_spvc_compilation_result_t shaderc_spvc_result_create() {
1149 return new (std::nothrow) shaderc_spvc_compilation_result;
1150 }
1151
shaderc_spvc_result_destroy(shaderc_spvc_compilation_result_t result)1152 void shaderc_spvc_result_destroy(shaderc_spvc_compilation_result_t result) {
1153 if (result) delete result;
1154 }
1155
shaderc_spvc_result_get_string_output(const shaderc_spvc_compilation_result_t result,const char ** str)1156 shaderc_spvc_status shaderc_spvc_result_get_string_output(
1157 const shaderc_spvc_compilation_result_t result, const char** str) {
1158 CHECK_RESULT(nullptr, result);
1159 CHECK_OUT_PARAM(nullptr, str, "str");
1160
1161 *str = result->string_output.c_str();
1162 return shaderc_spvc_status_success;
1163 }
1164
shaderc_spvc_result_get_binary_output(const shaderc_spvc_compilation_result_t result,const uint32_t ** binary_output)1165 shaderc_spvc_status shaderc_spvc_result_get_binary_output(
1166 const shaderc_spvc_compilation_result_t result,
1167 const uint32_t** binary_output) {
1168 CHECK_RESULT(nullptr, result);
1169 CHECK_OUT_PARAM(nullptr, binary_output, "binary_output");
1170
1171 *binary_output = result->binary_output.data();
1172 return shaderc_spvc_status_success;
1173 }
1174
shaderc_spvc_result_get_binary_length(const shaderc_spvc_compilation_result_t result,uint32_t * len)1175 shaderc_spvc_status shaderc_spvc_result_get_binary_length(
1176 const shaderc_spvc_compilation_result_t result, uint32_t* len) {
1177 CHECK_RESULT(nullptr, result);
1178 CHECK_OUT_PARAM(nullptr, len, "len");
1179
1180 *len = result->binary_output.size();
1181 return shaderc_spvc_status_success;
1182 }
1183