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