Coverage Report

Created: 2025-06-13 06:41

/src/shaderc/libshaderc/src/shaderc.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2015 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 "shaderc/shaderc.h"
16
17
#include <algorithm>
18
#include <cassert>
19
#include <cstdint>
20
#include <memory>
21
#include <sstream>
22
#include <vector>
23
24
#include "libshaderc_util/compiler.h"
25
#include "libshaderc_util/counting_includer.h"
26
#include "libshaderc_util/resources.h"
27
#include "libshaderc_util/spirv_tools_wrapper.h"
28
#include "libshaderc_util/version_profile.h"
29
#include "shaderc_private.h"
30
#include "spirv/unified1/spirv.hpp"
31
32
#if (defined(_MSC_VER) && !defined(_CPPUNWIND)) || !defined(__EXCEPTIONS)
33
#define TRY_IF_EXCEPTIONS_ENABLED
34
#define CATCH_IF_EXCEPTIONS_ENABLED(X) if (0)
35
#else
36
17.2k
#define TRY_IF_EXCEPTIONS_ENABLED try
37
#define CATCH_IF_EXCEPTIONS_ENABLED(X) catch (X)
38
#endif
39
40
namespace {
41
42
// Returns shader stage (ie: vertex, fragment, etc.) in response to forced
43
// shader kinds. If the shader kind is not a forced kind, returns EshLangCount
44
// to let #pragma annotation or shader stage deducer determine the stage to
45
// use.
46
17.2k
EShLanguage GetForcedStage(shaderc_shader_kind kind) {
47
17.2k
  switch (kind) {
48
0
    case shaderc_glsl_vertex_shader:
49
0
      return EShLangVertex;
50
17.2k
    case shaderc_glsl_fragment_shader:
51
17.2k
      return EShLangFragment;
52
0
    case shaderc_glsl_compute_shader:
53
0
      return EShLangCompute;
54
0
    case shaderc_glsl_geometry_shader:
55
0
      return EShLangGeometry;
56
0
    case shaderc_glsl_tess_control_shader:
57
0
      return EShLangTessControl;
58
0
    case shaderc_glsl_tess_evaluation_shader:
59
0
      return EShLangTessEvaluation;
60
61
0
    case shaderc_glsl_raygen_shader:
62
0
      return EShLangRayGenNV;
63
0
    case shaderc_glsl_anyhit_shader:
64
0
      return EShLangAnyHitNV;
65
0
    case shaderc_glsl_closesthit_shader:
66
0
      return EShLangClosestHitNV;
67
0
    case shaderc_glsl_miss_shader:
68
0
      return EShLangMissNV;
69
0
    case shaderc_glsl_intersection_shader:
70
0
      return EShLangIntersectNV;
71
0
    case shaderc_glsl_callable_shader:
72
0
      return EShLangCallableNV;
73
0
    case shaderc_glsl_task_shader:
74
0
      return EShLangTaskNV;
75
0
    case shaderc_glsl_mesh_shader:
76
0
      return EShLangMeshNV;
77
78
0
    case shaderc_glsl_infer_from_source:
79
0
    case shaderc_glsl_default_vertex_shader:
80
0
    case shaderc_glsl_default_fragment_shader:
81
0
    case shaderc_glsl_default_compute_shader:
82
0
    case shaderc_glsl_default_geometry_shader:
83
0
    case shaderc_glsl_default_tess_control_shader:
84
0
    case shaderc_glsl_default_tess_evaluation_shader:
85
0
    case shaderc_glsl_default_raygen_shader:
86
0
    case shaderc_glsl_default_anyhit_shader:
87
0
    case shaderc_glsl_default_closesthit_shader:
88
0
    case shaderc_glsl_default_miss_shader:
89
0
    case shaderc_glsl_default_intersection_shader:
90
0
    case shaderc_glsl_default_callable_shader:
91
0
    case shaderc_glsl_default_task_shader:
92
0
    case shaderc_glsl_default_mesh_shader:
93
0
    case shaderc_spirv_assembly:
94
0
      return EShLangCount;
95
17.2k
  }
96
0
  assert(0 && "Unhandled shaderc_shader_kind");
97
0
  return EShLangCount;
98
17.2k
}
99
100
// A wrapper functor class to be used as stage deducer for libshaderc_util
101
// Compile() interface. When the given shader kind is one of the default shader
102
// kinds, this functor will be called if #pragma is not found in the source
103
// code. And it returns the corresponding shader stage. When the shader kind is
104
// a forced shader kind, this functor won't be called and it simply returns
105
// EShLangCount to make the syntax correct. When the shader kind is set to
106
// shaderc_glsl_deduce_from_pragma, this functor also returns EShLangCount, but
107
// the compiler should emit error if #pragma annotation is not found in this
108
// case.
109
class StageDeducer {
110
 public:
111
  explicit StageDeducer(
112
      shaderc_shader_kind kind = shaderc_glsl_infer_from_source)
113
17.2k
      : kind_(kind), error_(false) {}
114
  // The method that underlying glslang will call to determine the shader stage
115
  // to be used in current compilation. It is called only when there is neither
116
  // forced shader kind (or say stage, in the view of glslang), nor #pragma
117
  // annotation in the source code. This method transforms an user defined
118
  // 'default' shader kind to the corresponding shader stage. As this is the
119
  // last trial to determine the shader stage, failing to find the corresponding
120
  // shader stage will record an error.
121
  // Note that calling this method more than once during one compilation will
122
  // have the error recorded for the previous call been overwriten by the next
123
  // call.
124
  EShLanguage operator()(std::ostream* /*error_stream*/,
125
0
                         const shaderc_util::string_piece& /*error_tag*/) {
126
0
    EShLanguage stage = GetDefaultStage(kind_);
127
0
    if (stage == EShLangCount) {
128
0
      error_ = true;
129
0
    } else {
130
0
      error_ = false;
131
0
    }
132
0
    return stage;
133
0
  }
134
135
  // Returns true if there is error during shader stage deduction.
136
13.8k
  bool error() const { return error_; }
137
138
 private:
139
  // Gets the corresponding shader stage for a given 'default' shader kind. All
140
  // other kinds are mapped to EShLangCount which should not be used.
141
0
  EShLanguage GetDefaultStage(shaderc_shader_kind kind) const {
142
0
    switch (kind) {
143
0
      case shaderc_glsl_vertex_shader:
144
0
      case shaderc_glsl_fragment_shader:
145
0
      case shaderc_glsl_compute_shader:
146
0
      case shaderc_glsl_geometry_shader:
147
0
      case shaderc_glsl_tess_control_shader:
148
0
      case shaderc_glsl_tess_evaluation_shader:
149
0
      case shaderc_glsl_infer_from_source:
150
0
      case shaderc_glsl_raygen_shader:
151
0
      case shaderc_glsl_anyhit_shader:
152
0
      case shaderc_glsl_closesthit_shader:
153
0
      case shaderc_glsl_miss_shader:
154
0
      case shaderc_glsl_intersection_shader:
155
0
      case shaderc_glsl_callable_shader:
156
0
      case shaderc_glsl_task_shader:
157
0
      case shaderc_glsl_mesh_shader:
158
0
        return EShLangCount;
159
0
      case shaderc_glsl_default_vertex_shader:
160
0
        return EShLangVertex;
161
0
      case shaderc_glsl_default_fragment_shader:
162
0
        return EShLangFragment;
163
0
      case shaderc_glsl_default_compute_shader:
164
0
        return EShLangCompute;
165
0
      case shaderc_glsl_default_geometry_shader:
166
0
        return EShLangGeometry;
167
0
      case shaderc_glsl_default_tess_control_shader:
168
0
        return EShLangTessControl;
169
0
      case shaderc_glsl_default_tess_evaluation_shader:
170
0
        return EShLangTessEvaluation;
171
0
      case shaderc_glsl_default_raygen_shader:
172
0
        return EShLangRayGenNV;
173
0
      case shaderc_glsl_default_anyhit_shader:
174
0
        return EShLangAnyHitNV;
175
0
      case shaderc_glsl_default_closesthit_shader:
176
0
        return EShLangClosestHitNV;
177
0
      case shaderc_glsl_default_miss_shader:
178
0
        return EShLangMissNV;
179
0
      case shaderc_glsl_default_intersection_shader:
180
0
        return EShLangIntersectNV;
181
0
      case shaderc_glsl_default_callable_shader:
182
0
        return EShLangCallableNV;
183
0
      case shaderc_glsl_default_task_shader:
184
0
        return EShLangTaskNV;
185
0
      case shaderc_glsl_default_mesh_shader:
186
0
        return EShLangMeshNV;
187
0
      case shaderc_spirv_assembly:
188
0
        return EShLangCount;
189
0
    }
190
0
    assert(0 && "Unhandled shaderc_shader_kind");
191
0
    return EShLangCount;
192
0
  }
193
194
  shaderc_shader_kind kind_;
195
  bool error_;
196
};
197
198
// A bridge between the libshaderc includer and libshaderc_util includer.
199
class InternalFileIncluder : public shaderc_util::CountingIncluder {
200
 public:
201
  InternalFileIncluder(const shaderc_include_resolve_fn resolver,
202
                       const shaderc_include_result_release_fn result_releaser,
203
                       void* user_data)
204
17.2k
      : resolver_(resolver),
205
17.2k
        result_releaser_(result_releaser),
206
17.2k
        user_data_(user_data) {}
207
  InternalFileIncluder()
208
0
      : resolver_(nullptr), result_releaser_(nullptr), user_data_(nullptr) {}
209
210
 private:
211
  // Check the validity of the callbacks.
212
229
  bool AreValidCallbacks() const {
213
229
    return resolver_ != nullptr && result_releaser_ != nullptr;
214
229
  }
215
216
  // Maps CountingIncluder IncludeType value to a shaderc_include_type
217
  // value.
218
229
  shaderc_include_type GetIncludeType(IncludeType type) {
219
229
    switch (type) {
220
130
      case IncludeType::Local:
221
130
        return shaderc_include_type_relative;
222
99
      case IncludeType::System:
223
99
        return shaderc_include_type_standard;
224
0
      default:
225
0
        break;
226
229
    }
227
0
    assert(0 && "Unhandled IncludeType");
228
0
    return shaderc_include_type_relative;
229
229
  }
230
231
  // Resolves an include request for the requested source of the given
232
  // type in the context of the specified requesting source.  On success,
233
  // returns a newly allocated IncludeResponse containing the fully resolved
234
  // name of the requested source and the contents of that source.
235
  // On failure, returns a newly allocated IncludeResponse where the
236
  // resolved name member is an empty string, and the contents members
237
  // contains error details.
238
  virtual glslang::TShader::Includer::IncludeResult* include_delegate(
239
      const char* requested_source, const char* requesting_source,
240
229
      IncludeType type, size_t include_depth) override {
241
229
    if (!AreValidCallbacks()) {
242
0
      static const char kUnexpectedIncludeError[] =
243
0
          "#error unexpected include directive";
244
0
      return new glslang::TShader::Includer::IncludeResult{
245
0
          "", kUnexpectedIncludeError, strlen(kUnexpectedIncludeError),
246
0
          nullptr};
247
0
    }
248
229
    shaderc_include_result* include_result =
249
229
        resolver_(user_data_, requested_source, GetIncludeType(type),
250
229
                  requesting_source, include_depth);
251
    // Make a glslang IncludeResult from a shaderc_include_result.  The
252
    // user_data member of the IncludeResult is a pointer to the
253
    // shaderc_include_result object, so we can later release the latter.
254
229
    return new glslang::TShader::Includer::IncludeResult{
255
229
        std::string(include_result->source_name,
256
229
                    include_result->source_name_length),
257
229
        include_result->content, include_result->content_length,
258
229
        include_result};
259
229
  }
260
261
  // Releases the given IncludeResult.
262
  virtual void release_delegate(
263
229
      glslang::TShader::Includer::IncludeResult* result) override {
264
229
    if (result && result_releaser_) {
265
229
      result_releaser_(user_data_,
266
229
                       static_cast<shaderc_include_result*>(result->userData));
267
229
    }
268
229
    delete result;
269
229
  }
270
271
  const shaderc_include_resolve_fn resolver_;
272
  const shaderc_include_result_release_fn result_releaser_;
273
  void* user_data_;
274
};
275
276
// Converts the target env to the corresponding one in shaderc_util::Compiler.
277
0
shaderc_util::Compiler::TargetEnv GetCompilerTargetEnv(shaderc_target_env env) {
278
0
  switch (env) {
279
0
    case shaderc_target_env_opengl:
280
0
      return shaderc_util::Compiler::TargetEnv::OpenGL;
281
0
    case shaderc_target_env_opengl_compat:
282
0
      return shaderc_util::Compiler::TargetEnv::OpenGLCompat;
283
0
    case shaderc_target_env_webgpu:
284
0
      assert(false);
285
0
      break;
286
0
    case shaderc_target_env_vulkan:
287
0
    default:
288
0
      break;
289
0
  }
290
291
0
  return shaderc_util::Compiler::TargetEnv::Vulkan;
292
0
}
293
294
shaderc_util::Compiler::TargetEnvVersion GetCompilerTargetEnvVersion(
295
0
    uint32_t version_number) {
296
0
  using namespace shaderc_util;
297
298
0
  if (static_cast<uint32_t>(Compiler::TargetEnvVersion::Vulkan_1_0) ==
299
0
      version_number) {
300
0
    return Compiler::TargetEnvVersion::Vulkan_1_0;
301
0
  }
302
0
  if (static_cast<uint32_t>(Compiler::TargetEnvVersion::Vulkan_1_1) ==
303
0
      version_number) {
304
0
    return Compiler::TargetEnvVersion::Vulkan_1_1;
305
0
  }
306
0
  if (static_cast<uint32_t>(Compiler::TargetEnvVersion::Vulkan_1_2) ==
307
0
      version_number) {
308
0
    return Compiler::TargetEnvVersion::Vulkan_1_2;
309
0
  }
310
0
  if (static_cast<uint32_t>(Compiler::TargetEnvVersion::Vulkan_1_3) ==
311
0
      version_number) {
312
0
    return Compiler::TargetEnvVersion::Vulkan_1_3;
313
0
  }
314
0
  if (static_cast<uint32_t>(Compiler::TargetEnvVersion::Vulkan_1_4) ==
315
0
      version_number) {
316
0
    return Compiler::TargetEnvVersion::Vulkan_1_4;
317
0
  }
318
0
  if (static_cast<uint32_t>(Compiler::TargetEnvVersion::OpenGL_4_5) ==
319
0
      version_number) {
320
0
    return Compiler::TargetEnvVersion::OpenGL_4_5;
321
0
  }
322
323
0
  return Compiler::TargetEnvVersion::Default;
324
0
}
325
326
// Returns the Compiler::Limit enum for the given shaderc_limit enum.
327
0
shaderc_util::Compiler::Limit CompilerLimit(shaderc_limit limit) {
328
0
  switch (limit) {
329
0
#define RESOURCE(NAME, FIELD, CNAME) \
330
0
  case shaderc_limit_##CNAME:        \
331
0
    return shaderc_util::Compiler::Limit::NAME;
332
0
#include "libshaderc_util/resources.inc"
333
0
#undef RESOURCE
334
0
    default:
335
0
      break;
336
0
  }
337
0
  assert(0 && "Should not have reached here");
338
0
  return static_cast<shaderc_util::Compiler::Limit>(0);
339
0
}
340
341
// Returns the Compiler::UniformKind for the given shaderc_uniform_kind.
342
0
shaderc_util::Compiler::UniformKind GetUniformKind(shaderc_uniform_kind kind) {
343
0
  switch (kind) {
344
0
    case shaderc_uniform_kind_texture:
345
0
      return shaderc_util::Compiler::UniformKind::Texture;
346
0
    case shaderc_uniform_kind_sampler:
347
0
      return shaderc_util::Compiler::UniformKind::Sampler;
348
0
    case shaderc_uniform_kind_image:
349
0
      return shaderc_util::Compiler::UniformKind::Image;
350
0
    case shaderc_uniform_kind_buffer:
351
0
      return shaderc_util::Compiler::UniformKind::Buffer;
352
0
    case shaderc_uniform_kind_storage_buffer:
353
0
      return shaderc_util::Compiler::UniformKind::StorageBuffer;
354
0
    case shaderc_uniform_kind_unordered_access_view:
355
0
      return shaderc_util::Compiler::UniformKind::UnorderedAccessView;
356
0
  }
357
0
  assert(0 && "Should not have reached here");
358
0
  return static_cast<shaderc_util::Compiler::UniformKind>(0);
359
0
}
360
361
// Returns the Compiler::Stage for generic stage values in shaderc_shader_kind.
362
0
shaderc_util::Compiler::Stage GetStage(shaderc_shader_kind kind) {
363
0
  switch (kind) {
364
0
    case shaderc_vertex_shader:
365
0
      return shaderc_util::Compiler::Stage::Vertex;
366
0
    case shaderc_fragment_shader:
367
0
      return shaderc_util::Compiler::Stage::Fragment;
368
0
    case shaderc_compute_shader:
369
0
      return shaderc_util::Compiler::Stage::Compute;
370
0
    case shaderc_tess_control_shader:
371
0
      return shaderc_util::Compiler::Stage::TessControl;
372
0
    case shaderc_tess_evaluation_shader:
373
0
      return shaderc_util::Compiler::Stage::TessEval;
374
0
    case shaderc_geometry_shader:
375
0
      return shaderc_util::Compiler::Stage::Geometry;
376
0
    default:
377
0
      break;
378
0
  }
379
0
  assert(0 && "Should not have reached here");
380
0
  return static_cast<shaderc_util::Compiler::Stage>(0);
381
0
}
382
383
}  // anonymous namespace
384
385
struct shaderc_compile_options {
386
  shaderc_target_env target_env = shaderc_target_env_default;
387
  uint32_t target_env_version = 0;
388
  shaderc_util::Compiler compiler;
389
  shaderc_include_resolve_fn include_resolver = nullptr;
390
  shaderc_include_result_release_fn include_result_releaser = nullptr;
391
  void* include_user_data = nullptr;
392
};
393
394
5.73k
shaderc_compile_options_t shaderc_compile_options_initialize() {
395
5.73k
  return new (std::nothrow) shaderc_compile_options;
396
5.73k
}
397
398
shaderc_compile_options_t shaderc_compile_options_clone(
399
0
    const shaderc_compile_options_t options) {
400
0
  if (!options) {
401
0
    return shaderc_compile_options_initialize();
402
0
  }
403
0
  return new (std::nothrow) shaderc_compile_options(*options);
404
0
}
405
406
5.73k
void shaderc_compile_options_release(shaderc_compile_options_t options) {
407
5.73k
  delete options;
408
5.73k
}
409
410
void shaderc_compile_options_add_macro_definition(
411
    shaderc_compile_options_t options, const char* name, size_t name_length,
412
0
    const char* value, size_t value_length) {
413
0
  options->compiler.AddMacroDefinition(name, name_length, value, value_length);
414
0
}
415
416
void shaderc_compile_options_set_source_language(
417
17.2k
    shaderc_compile_options_t options, shaderc_source_language set_lang) {
418
17.2k
  auto lang = shaderc_util::Compiler::SourceLanguage::GLSL;
419
17.2k
  if (set_lang == shaderc_source_language_hlsl)
420
0
    lang = shaderc_util::Compiler::SourceLanguage::HLSL;
421
17.2k
  options->compiler.SetSourceLanguage(lang);
422
17.2k
}
423
424
void shaderc_compile_options_set_generate_debug_info(
425
0
    shaderc_compile_options_t options) {
426
0
  options->compiler.SetGenerateDebugInfo();
427
0
}
428
429
void shaderc_compile_options_set_optimization_level(
430
0
    shaderc_compile_options_t options, shaderc_optimization_level level) {
431
0
  auto opt_level = shaderc_util::Compiler::OptimizationLevel::Zero;
432
0
  switch (level) {
433
0
    case shaderc_optimization_level_size:
434
0
      opt_level = shaderc_util::Compiler::OptimizationLevel::Size;
435
0
      break;
436
0
    case shaderc_optimization_level_performance:
437
0
      opt_level = shaderc_util::Compiler::OptimizationLevel::Performance;
438
0
      break;
439
0
    default:
440
0
      break;
441
0
  }
442
443
0
  options->compiler.SetOptimizationLevel(opt_level);
444
0
}
445
446
void shaderc_compile_options_set_forced_version_profile(
447
0
    shaderc_compile_options_t options, int version, shaderc_profile profile) {
448
  // Transfer the profile parameter from public enum type to glslang internal
449
  // enum type. No default case here so that compiler will complain if new enum
450
  // member is added later but not handled here.
451
0
  switch (profile) {
452
0
    case shaderc_profile_none:
453
0
      options->compiler.SetForcedVersionProfile(version, ENoProfile);
454
0
      break;
455
0
    case shaderc_profile_core:
456
0
      options->compiler.SetForcedVersionProfile(version, ECoreProfile);
457
0
      break;
458
0
    case shaderc_profile_compatibility:
459
0
      options->compiler.SetForcedVersionProfile(version, ECompatibilityProfile);
460
0
      break;
461
0
    case shaderc_profile_es:
462
0
      options->compiler.SetForcedVersionProfile(version, EEsProfile);
463
0
      break;
464
0
  }
465
0
}
466
467
void shaderc_compile_options_set_include_callbacks(
468
    shaderc_compile_options_t options, shaderc_include_resolve_fn resolver,
469
17.2k
    shaderc_include_result_release_fn result_releaser, void* user_data) {
470
17.2k
  options->include_resolver = resolver;
471
17.2k
  options->include_result_releaser = result_releaser;
472
17.2k
  options->include_user_data = user_data;
473
17.2k
}
474
475
void shaderc_compile_options_set_suppress_warnings(
476
5.73k
    shaderc_compile_options_t options) {
477
5.73k
  options->compiler.SetSuppressWarnings();
478
5.73k
}
479
480
void shaderc_compile_options_set_target_env(shaderc_compile_options_t options,
481
                                            shaderc_target_env target,
482
0
                                            uint32_t version) {
483
0
  options->target_env = target;
484
0
  options->compiler.SetTargetEnv(GetCompilerTargetEnv(target),
485
0
                                 GetCompilerTargetEnvVersion(version));
486
0
}
487
488
void shaderc_compile_options_set_target_spirv(shaderc_compile_options_t options,
489
0
                                              shaderc_spirv_version ver) {
490
  // We made the values match, so we can get away with a static cast.
491
0
  options->compiler.SetTargetSpirv(
492
0
      static_cast<shaderc_util::Compiler::SpirvVersion>(ver));
493
0
}
494
495
void shaderc_compile_options_set_warnings_as_errors(
496
0
    shaderc_compile_options_t options) {
497
0
  options->compiler.SetWarningsAsErrors();
498
0
}
499
500
void shaderc_compile_options_set_limit(shaderc_compile_options_t options,
501
0
                                       shaderc_limit limit, int value) {
502
0
  options->compiler.SetLimit(CompilerLimit(limit), value);
503
0
}
504
505
void shaderc_compile_options_set_auto_bind_uniforms(
506
0
    shaderc_compile_options_t options, bool auto_bind) {
507
0
  options->compiler.SetAutoBindUniforms(auto_bind);
508
0
}
509
510
void shaderc_compile_options_set_auto_combined_image_sampler(
511
0
    shaderc_compile_options_t options, bool upgrade) {
512
0
  options->compiler.SetAutoCombinedImageSampler(upgrade);
513
0
}
514
515
void shaderc_compile_options_set_hlsl_io_mapping(
516
0
    shaderc_compile_options_t options, bool hlsl_iomap) {
517
0
  options->compiler.SetHlslIoMapping(hlsl_iomap);
518
0
}
519
520
void shaderc_compile_options_set_hlsl_offsets(shaderc_compile_options_t options,
521
0
                                              bool hlsl_offsets) {
522
0
  options->compiler.SetHlslOffsets(hlsl_offsets);
523
0
}
524
525
void shaderc_compile_options_set_binding_base(shaderc_compile_options_t options,
526
                                              shaderc_uniform_kind kind,
527
0
                                              uint32_t base) {
528
0
  options->compiler.SetAutoBindingBase(GetUniformKind(kind), base);
529
0
}
530
531
void shaderc_compile_options_set_binding_base_for_stage(
532
    shaderc_compile_options_t options, shaderc_shader_kind shader_kind,
533
0
    shaderc_uniform_kind kind, uint32_t base) {
534
0
  options->compiler.SetAutoBindingBaseForStage(GetStage(shader_kind),
535
0
                                               GetUniformKind(kind), base);
536
0
}
537
538
void shaderc_compile_options_set_preserve_bindings(
539
0
    shaderc_compile_options_t options, bool preserve_bindings) {
540
0
  options->compiler.SetPreserveBindings(preserve_bindings);
541
0
}
542
543
void shaderc_compile_options_set_auto_map_locations(
544
0
    shaderc_compile_options_t options, bool auto_map) {
545
0
  options->compiler.SetAutoMapLocations(auto_map);
546
0
}
547
548
void shaderc_compile_options_set_hlsl_register_set_and_binding_for_stage(
549
    shaderc_compile_options_t options, shaderc_shader_kind shader_kind,
550
0
    const char* reg, const char* set, const char* binding) {
551
0
  options->compiler.SetHlslRegisterSetAndBindingForStage(GetStage(shader_kind),
552
0
                                                         reg, set, binding);
553
0
}
554
555
void shaderc_compile_options_set_hlsl_register_set_and_binding(
556
    shaderc_compile_options_t options, const char* reg, const char* set,
557
0
    const char* binding) {
558
0
  options->compiler.SetHlslRegisterSetAndBinding(reg, set, binding);
559
0
}
560
561
void shaderc_compile_options_set_hlsl_functionality1(
562
0
    shaderc_compile_options_t options, bool enable) {
563
0
  options->compiler.EnableHlslFunctionality1(enable);
564
0
}
565
566
void shaderc_compile_options_set_hlsl_16bit_types(
567
0
    shaderc_compile_options_t options, bool enable) {
568
0
  options->compiler.EnableHlsl16BitTypes(enable);
569
0
}
570
571
void shaderc_compile_options_set_vulkan_rules_relaxed(
572
0
    shaderc_compile_options_t options, bool enable) {
573
0
  options->compiler.SetVulkanRulesRelaxed(enable);
574
0
}
575
576
void shaderc_compile_options_set_invert_y(shaderc_compile_options_t options,
577
0
                                          bool enable) {
578
0
  options->compiler.EnableInvertY(enable);
579
0
}
580
581
void shaderc_compile_options_set_nan_clamp(shaderc_compile_options_t options,
582
0
                                           bool enable) {
583
0
  options->compiler.SetNanClamp(enable);
584
0
}
585
586
5.73k
shaderc_compiler_t shaderc_compiler_initialize() {
587
5.73k
  shaderc_compiler_t compiler = new (std::nothrow) shaderc_compiler;
588
5.73k
  if (compiler) {
589
5.73k
    compiler->initializer.reset(new shaderc_util::GlslangInitializer);
590
5.73k
  }
591
5.73k
  return compiler;
592
5.73k
}
593
594
5.73k
void shaderc_compiler_release(shaderc_compiler_t compiler) { delete compiler; }
595
596
namespace {
597
shaderc_compilation_result_t CompileToSpecifiedOutputType(
598
    const shaderc_compiler_t compiler, const char* source_text,
599
    size_t source_text_size, shaderc_shader_kind shader_kind,
600
    const char* input_file_name, const char* entry_point_name,
601
    const shaderc_compile_options_t additional_options,
602
17.2k
    shaderc_util::Compiler::OutputType output_type) {
603
17.2k
  auto* result = new (std::nothrow) shaderc_compilation_result_vector;
604
17.2k
  if (!result) return nullptr;
605
606
17.2k
  if (!input_file_name) {
607
0
    result->messages = "Input file name string was null.";
608
0
    result->num_errors = 1;
609
0
    result->compilation_status = shaderc_compilation_status_compilation_error;
610
0
    return result;
611
0
  }
612
17.2k
  result->compilation_status = shaderc_compilation_status_invalid_stage;
613
17.2k
  bool compilation_succeeded = false;  // In case we exit early.
614
17.2k
  std::vector<uint32_t> compilation_output_data;
615
17.2k
  size_t compilation_output_data_size_in_bytes = 0u;
616
17.2k
  if (!compiler->initializer) return result;
617
17.2k
  TRY_IF_EXCEPTIONS_ENABLED {
618
17.2k
    std::stringstream errors;
619
17.2k
    size_t total_warnings = 0;
620
17.2k
    size_t total_errors = 0;
621
17.2k
    std::string input_file_name_str(input_file_name);
622
17.2k
    EShLanguage forced_stage = GetForcedStage(shader_kind);
623
17.2k
    shaderc_util::string_piece source_string =
624
17.2k
        shaderc_util::string_piece(source_text, source_text + source_text_size);
625
17.2k
    StageDeducer stage_deducer(shader_kind);
626
17.2k
    if (additional_options) {
627
17.2k
      InternalFileIncluder includer(additional_options->include_resolver,
628
17.2k
                                    additional_options->include_result_releaser,
629
17.2k
                                    additional_options->include_user_data);
630
      // Depends on return value optimization to avoid extra copy.
631
17.2k
      std::tie(compilation_succeeded, compilation_output_data,
632
17.2k
               compilation_output_data_size_in_bytes) =
633
17.2k
          additional_options->compiler.Compile(
634
17.2k
              source_string, forced_stage, input_file_name_str,
635
17.2k
              entry_point_name,
636
              // stage_deducer has a flag: error_, which we need to check later.
637
              // We need to make this a reference wrapper, so that std::function
638
              // won't make a copy for this callable object.
639
17.2k
              std::ref(stage_deducer), includer, output_type, &errors,
640
17.2k
              &total_warnings, &total_errors);
641
17.2k
    } else {
642
      // Compile with default options.
643
0
      InternalFileIncluder includer;
644
0
      std::tie(compilation_succeeded, compilation_output_data,
645
0
               compilation_output_data_size_in_bytes) =
646
0
          shaderc_util::Compiler().Compile(
647
0
              source_string, forced_stage, input_file_name_str,
648
0
              entry_point_name, std::ref(stage_deducer), includer, output_type,
649
0
              &errors, &total_warnings, &total_errors);
650
0
    }
651
652
17.2k
    result->messages = errors.str();
653
17.2k
    result->SetOutputData(std::move(compilation_output_data));
654
17.2k
    result->output_data_size = compilation_output_data_size_in_bytes;
655
17.2k
    result->num_warnings = total_warnings;
656
17.2k
    result->num_errors = total_errors;
657
17.2k
    if (compilation_succeeded) {
658
3.36k
      result->compilation_status = shaderc_compilation_status_success;
659
13.8k
    } else {
660
      // Check whether the error is caused by failing to deduce the shader
661
      // stage. If it is the case, set the error type to shader kind error.
662
      // Otherwise, set it to compilation error.
663
13.8k
      result->compilation_status =
664
13.8k
          stage_deducer.error() ? shaderc_compilation_status_invalid_stage
665
13.8k
                                : shaderc_compilation_status_compilation_error;
666
13.8k
    }
667
17.2k
  }
668
17.2k
  CATCH_IF_EXCEPTIONS_ENABLED(...) {
669
0
    result->compilation_status = shaderc_compilation_status_internal_error;
670
0
  }
671
17.2k
  return result;
672
17.2k
}
673
}  // anonymous namespace
674
675
shaderc_compilation_result_t shaderc_compile_into_spv(
676
    const shaderc_compiler_t compiler, const char* source_text,
677
    size_t source_text_size, shaderc_shader_kind shader_kind,
678
    const char* input_file_name, const char* entry_point_name,
679
5.73k
    const shaderc_compile_options_t additional_options) {
680
5.73k
  return CompileToSpecifiedOutputType(
681
5.73k
      compiler, source_text, source_text_size, shader_kind, input_file_name,
682
5.73k
      entry_point_name, additional_options,
683
5.73k
      shaderc_util::Compiler::OutputType::SpirvBinary);
684
5.73k
}
685
686
shaderc_compilation_result_t shaderc_compile_into_spv_assembly(
687
    const shaderc_compiler_t compiler, const char* source_text,
688
    size_t source_text_size, shaderc_shader_kind shader_kind,
689
    const char* input_file_name, const char* entry_point_name,
690
0
    const shaderc_compile_options_t additional_options) {
691
0
  return CompileToSpecifiedOutputType(
692
0
      compiler, source_text, source_text_size, shader_kind, input_file_name,
693
0
      entry_point_name, additional_options,
694
0
      shaderc_util::Compiler::OutputType::SpirvAssemblyText);
695
0
}
696
697
shaderc_compilation_result_t shaderc_compile_into_preprocessed_text(
698
    const shaderc_compiler_t compiler, const char* source_text,
699
    size_t source_text_size, shaderc_shader_kind shader_kind,
700
    const char* input_file_name, const char* entry_point_name,
701
11.4k
    const shaderc_compile_options_t additional_options) {
702
11.4k
  return CompileToSpecifiedOutputType(
703
11.4k
      compiler, source_text, source_text_size, shader_kind, input_file_name,
704
11.4k
      entry_point_name, additional_options,
705
11.4k
      shaderc_util::Compiler::OutputType::PreprocessedText);
706
11.4k
}
707
708
shaderc_compilation_result_t shaderc_assemble_into_spv(
709
    const shaderc_compiler_t compiler, const char* source_assembly,
710
    size_t source_assembly_size,
711
0
    const shaderc_compile_options_t additional_options) {
712
0
  auto* result = new (std::nothrow) shaderc_compilation_result_spv_binary;
713
0
  if (!result) return nullptr;
714
0
  result->compilation_status = shaderc_compilation_status_invalid_assembly;
715
0
  if (!compiler->initializer) return result;
716
0
  if (source_assembly == nullptr) return result;
717
718
0
  TRY_IF_EXCEPTIONS_ENABLED {
719
0
    spv_binary assembling_output_data = nullptr;
720
0
    std::string errors;
721
0
    const auto target_env = additional_options ? additional_options->target_env
722
0
                                               : shaderc_target_env_default;
723
0
    const uint32_t target_env_version =
724
0
        additional_options ? additional_options->target_env_version : 0;
725
0
    const bool assembling_succeeded = shaderc_util::SpirvToolsAssemble(
726
0
        GetCompilerTargetEnv(target_env),
727
0
        GetCompilerTargetEnvVersion(target_env_version),
728
0
        {source_assembly, source_assembly + source_assembly_size},
729
0
        &assembling_output_data, &errors);
730
0
    result->num_errors = !assembling_succeeded;
731
0
    if (assembling_succeeded) {
732
0
      result->SetOutputData(assembling_output_data);
733
0
      result->output_data_size =
734
0
          assembling_output_data->wordCount * sizeof(uint32_t);
735
0
      result->compilation_status = shaderc_compilation_status_success;
736
0
    } else {
737
0
      result->messages = std::move(errors);
738
0
      result->compilation_status = shaderc_compilation_status_invalid_assembly;
739
0
    }
740
0
  }
741
0
  CATCH_IF_EXCEPTIONS_ENABLED(...) {
742
0
    result->compilation_status = shaderc_compilation_status_internal_error;
743
0
  }
744
745
0
  return result;
746
0
}
747
748
17.2k
size_t shaderc_result_get_length(const shaderc_compilation_result_t result) {
749
17.2k
  return result->output_data_size;
750
17.2k
}
751
752
size_t shaderc_result_get_num_warnings(
753
17.2k
    const shaderc_compilation_result_t result) {
754
17.2k
  return result->num_warnings;
755
17.2k
}
756
757
size_t shaderc_result_get_num_errors(
758
17.2k
    const shaderc_compilation_result_t result) {
759
17.2k
  return result->num_errors;
760
17.2k
}
761
762
const char* shaderc_result_get_bytes(
763
34.4k
    const shaderc_compilation_result_t result) {
764
34.4k
  return result->GetBytes();
765
34.4k
}
766
767
17.2k
void shaderc_result_release(shaderc_compilation_result_t result) {
768
17.2k
  delete result;
769
17.2k
}
770
771
const char* shaderc_result_get_error_message(
772
17.2k
    const shaderc_compilation_result_t result) {
773
17.2k
  return result->messages.c_str();
774
17.2k
}
775
776
shaderc_compilation_status shaderc_result_get_compilation_status(
777
34.4k
    const shaderc_compilation_result_t result) {
778
34.4k
  return result->compilation_status;
779
34.4k
}
780
781
0
void shaderc_get_spv_version(unsigned int* version, unsigned int* revision) {
782
0
  *version = spv::Version;
783
0
  *revision = spv::Revision;
784
0
}
785
786
bool shaderc_parse_version_profile(const char* str, int* version,
787
0
                                   shaderc_profile* profile) {
788
0
  EProfile glslang_profile;
789
0
  bool success = shaderc_util::ParseVersionProfile(
790
0
      std::string(str, strlen(str)), version, &glslang_profile);
791
0
  if (!success) return false;
792
793
0
  switch (glslang_profile) {
794
0
    case EEsProfile:
795
0
      *profile = shaderc_profile_es;
796
0
      return true;
797
0
    case ECoreProfile:
798
0
      *profile = shaderc_profile_core;
799
0
      return true;
800
0
    case ECompatibilityProfile:
801
0
      *profile = shaderc_profile_compatibility;
802
0
      return true;
803
0
    case ENoProfile:
804
0
      *profile = shaderc_profile_none;
805
0
      return true;
806
0
    case EBadProfile:
807
0
    case EProfileCount:
808
0
      return false;
809
0
  }
810
811
  // Shouldn't reach here, all profile enum should be handled above.
812
  // Be strict to return false.
813
0
  return false;
814
0
}