#include "shaderc/shaderc.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <memory>
#include <sstream>
#include <vector>
#include "libshaderc_util/compiler.h"
#include "libshaderc_util/counting_includer.h"
#include "libshaderc_util/resources.h"
#include "libshaderc_util/spirv_tools_wrapper.h"
#include "libshaderc_util/version_profile.h"
#include "shaderc_private.h"
#include "spirv/unified1/spirv.hpp"
#if (defined(_MSC_VER) && !defined(_CPPUNWIND)) || !defined(__EXCEPTIONS)
#define TRY_IF_EXCEPTIONS_ENABLED
#define CATCH_IF_EXCEPTIONS_ENABLED(X) if (0)
#else
#define TRY_IF_EXCEPTIONS_ENABLED try
#define CATCH_IF_EXCEPTIONS_ENABLED(X) catch (X)
#endif
namespace {
EShLanguage GetForcedStage(shaderc_shader_kind kind) {
switch (kind) {
case shaderc_glsl_vertex_shader:
return EShLangVertex;
case shaderc_glsl_fragment_shader:
return EShLangFragment;
case shaderc_glsl_compute_shader:
return EShLangCompute;
case shaderc_glsl_geometry_shader:
return EShLangGeometry;
case shaderc_glsl_tess_control_shader:
return EShLangTessControl;
case shaderc_glsl_tess_evaluation_shader:
return EShLangTessEvaluation;
case shaderc_glsl_raygen_shader:
return EShLangRayGenNV;
case shaderc_glsl_anyhit_shader:
return EShLangAnyHitNV;
case shaderc_glsl_closesthit_shader:
return EShLangClosestHitNV;
case shaderc_glsl_miss_shader:
return EShLangMissNV;
case shaderc_glsl_intersection_shader:
return EShLangIntersectNV;
case shaderc_glsl_callable_shader:
return EShLangCallableNV;
case shaderc_glsl_task_shader:
return EShLangTaskNV;
case shaderc_glsl_mesh_shader:
return EShLangMeshNV;
case shaderc_glsl_infer_from_source:
case shaderc_glsl_default_vertex_shader:
case shaderc_glsl_default_fragment_shader:
case shaderc_glsl_default_compute_shader:
case shaderc_glsl_default_geometry_shader:
case shaderc_glsl_default_tess_control_shader:
case shaderc_glsl_default_tess_evaluation_shader:
case shaderc_glsl_default_raygen_shader:
case shaderc_glsl_default_anyhit_shader:
case shaderc_glsl_default_closesthit_shader:
case shaderc_glsl_default_miss_shader:
case shaderc_glsl_default_intersection_shader:
case shaderc_glsl_default_callable_shader:
case shaderc_glsl_default_task_shader:
case shaderc_glsl_default_mesh_shader:
case shaderc_spirv_assembly:
return EShLangCount;
}
assert(0 && "Unhandled shaderc_shader_kind");
return EShLangCount;
}
class StageDeducer {
public:
explicit StageDeducer(
shaderc_shader_kind kind = shaderc_glsl_infer_from_source)
: kind_(kind), error_(false){}
EShLanguage operator()(std::ostream* ,
const shaderc_util::string_piece& ) {
EShLanguage stage = GetDefaultStage(kind_);
if (stage == EShLangCount) {
error_ = true;
} else {
error_ = false;
}
return stage;
}
bool error() const { return error_; }
private:
EShLanguage GetDefaultStage(shaderc_shader_kind kind) const {
switch (kind) {
case shaderc_glsl_vertex_shader:
case shaderc_glsl_fragment_shader:
case shaderc_glsl_compute_shader:
case shaderc_glsl_geometry_shader:
case shaderc_glsl_tess_control_shader:
case shaderc_glsl_tess_evaluation_shader:
case shaderc_glsl_infer_from_source:
case shaderc_glsl_raygen_shader:
case shaderc_glsl_anyhit_shader:
case shaderc_glsl_closesthit_shader:
case shaderc_glsl_miss_shader:
case shaderc_glsl_intersection_shader:
case shaderc_glsl_callable_shader:
case shaderc_glsl_task_shader:
case shaderc_glsl_mesh_shader:
return EShLangCount;
case shaderc_glsl_default_vertex_shader:
return EShLangVertex;
case shaderc_glsl_default_fragment_shader:
return EShLangFragment;
case shaderc_glsl_default_compute_shader:
return EShLangCompute;
case shaderc_glsl_default_geometry_shader:
return EShLangGeometry;
case shaderc_glsl_default_tess_control_shader:
return EShLangTessControl;
case shaderc_glsl_default_tess_evaluation_shader:
return EShLangTessEvaluation;
case shaderc_glsl_default_raygen_shader:
return EShLangRayGenNV;
case shaderc_glsl_default_anyhit_shader:
return EShLangAnyHitNV;
case shaderc_glsl_default_closesthit_shader:
return EShLangClosestHitNV;
case shaderc_glsl_default_miss_shader:
return EShLangMissNV;
case shaderc_glsl_default_intersection_shader:
return EShLangIntersectNV;
case shaderc_glsl_default_callable_shader:
return EShLangCallableNV;
case shaderc_glsl_default_task_shader:
return EShLangTaskNV;
case shaderc_glsl_default_mesh_shader:
return EShLangMeshNV;
case shaderc_spirv_assembly:
return EShLangCount;
}
assert(0 && "Unhandled shaderc_shader_kind");
return EShLangCount;
}
shaderc_shader_kind kind_;
bool error_;
};
class InternalFileIncluder : public shaderc_util::CountingIncluder {
public:
InternalFileIncluder(const shaderc_include_resolve_fn resolver,
const shaderc_include_result_release_fn result_releaser,
void* user_data)
: resolver_(resolver),
result_releaser_(result_releaser),
user_data_(user_data){}
InternalFileIncluder()
: resolver_(nullptr), result_releaser_(nullptr), user_data_(nullptr){}
private:
bool AreValidCallbacks() const {
return resolver_ != nullptr && result_releaser_ != nullptr;
}
shaderc_include_type GetIncludeType(IncludeType type) {
switch (type) {
case IncludeType::Local:
return shaderc_include_type_relative;
case IncludeType::System:
return shaderc_include_type_standard;
default:
break;
}
assert(0 && "Unhandled IncludeType");
return shaderc_include_type_relative;
}
virtual glslang::TShader::Includer::IncludeResult* include_delegate(
const char* requested_source, const char* requesting_source,
IncludeType type, size_t include_depth) override {
if (!AreValidCallbacks()) {
static const char kUnexpectedIncludeError[] =
"#error unexpected include directive";
return new glslang::TShader::Includer::IncludeResult{
"", kUnexpectedIncludeError, strlen(kUnexpectedIncludeError),
nullptr};
}
shaderc_include_result* include_result =
resolver_(user_data_, requested_source, GetIncludeType(type),
requesting_source, include_depth);
return new glslang::TShader::Includer::IncludeResult{
std::string(include_result->source_name,
include_result->source_name_length),
include_result->content, include_result->content_length,
include_result};
}
virtual void release_delegate(
glslang::TShader::Includer::IncludeResult* result) override {
if (result && result_releaser_) {
result_releaser_(user_data_,
static_cast<shaderc_include_result*>(result->userData));
}
delete result;
}
const shaderc_include_resolve_fn resolver_;
const shaderc_include_result_release_fn result_releaser_;
void* user_data_;
};
shaderc_util::Compiler::TargetEnv GetCompilerTargetEnv(shaderc_target_env env) {
switch (env) {
case shaderc_target_env_opengl:
return shaderc_util::Compiler::TargetEnv::OpenGL;
case shaderc_target_env_opengl_compat:
return shaderc_util::Compiler::TargetEnv::OpenGLCompat;
case shaderc_target_env_webgpu:
assert(false);
break;
case shaderc_target_env_vulkan:
default:
break;
}
return shaderc_util::Compiler::TargetEnv::Vulkan;
}
shaderc_util::Compiler::TargetEnvVersion GetCompilerTargetEnvVersion(
uint32_t version_number) {
using namespace shaderc_util;
if (static_cast<uint32_t>(Compiler::TargetEnvVersion::Vulkan_1_0) ==
version_number) {
return Compiler::TargetEnvVersion::Vulkan_1_0;
}
if (static_cast<uint32_t>(Compiler::TargetEnvVersion::Vulkan_1_1) ==
version_number) {
return Compiler::TargetEnvVersion::Vulkan_1_1;
}
if (static_cast<uint32_t>(Compiler::TargetEnvVersion::Vulkan_1_2) ==
version_number) {
return Compiler::TargetEnvVersion::Vulkan_1_2;
}
if (static_cast<uint32_t>(Compiler::TargetEnvVersion::Vulkan_1_3) ==
version_number) {
return Compiler::TargetEnvVersion::Vulkan_1_3;
}
if (static_cast<uint32_t>(Compiler::TargetEnvVersion::OpenGL_4_5) ==
version_number) {
return Compiler::TargetEnvVersion::OpenGL_4_5;
}
return Compiler::TargetEnvVersion::Default;
}
shaderc_util::Compiler::Limit CompilerLimit(shaderc_limit limit) {
switch (limit) {
#define RESOURCE(NAME, FIELD, CNAME) \
case shaderc_limit_##CNAME: \
return shaderc_util::Compiler::Limit::NAME;
#include "libshaderc_util/resources.inc"
#undef RESOURCE
default:
break;
}
assert(0 && "Should not have reached here");
return static_cast<shaderc_util::Compiler::Limit>(0);
}
shaderc_util::Compiler::UniformKind GetUniformKind(shaderc_uniform_kind kind) {
switch (kind) {
case shaderc_uniform_kind_texture:
return shaderc_util::Compiler::UniformKind::Texture;
case shaderc_uniform_kind_sampler:
return shaderc_util::Compiler::UniformKind::Sampler;
case shaderc_uniform_kind_image:
return shaderc_util::Compiler::UniformKind::Image;
case shaderc_uniform_kind_buffer:
return shaderc_util::Compiler::UniformKind::Buffer;
case shaderc_uniform_kind_storage_buffer:
return shaderc_util::Compiler::UniformKind::StorageBuffer;
case shaderc_uniform_kind_unordered_access_view:
return shaderc_util::Compiler::UniformKind::UnorderedAccessView;
}
assert(0 && "Should not have reached here");
return static_cast<shaderc_util::Compiler::UniformKind>(0);
}
shaderc_util::Compiler::Stage GetStage(shaderc_shader_kind kind) {
switch (kind) {
case shaderc_vertex_shader:
return shaderc_util::Compiler::Stage::Vertex;
case shaderc_fragment_shader:
return shaderc_util::Compiler::Stage::Fragment;
case shaderc_compute_shader:
return shaderc_util::Compiler::Stage::Compute;
case shaderc_tess_control_shader:
return shaderc_util::Compiler::Stage::TessControl;
case shaderc_tess_evaluation_shader:
return shaderc_util::Compiler::Stage::TessEval;
case shaderc_geometry_shader:
return shaderc_util::Compiler::Stage::Geometry;
default:
break;
}
assert(0 && "Should not have reached here");
return static_cast<shaderc_util::Compiler::Stage>(0);
}
}
struct shaderc_compile_options {
shaderc_target_env target_env = shaderc_target_env_default;
uint32_t target_env_version = 0;
shaderc_util::Compiler compiler;
shaderc_include_resolve_fn include_resolver = nullptr;
shaderc_include_result_release_fn include_result_releaser = nullptr;
void* include_user_data = nullptr;
};
shaderc_compile_options_t shaderc_compile_options_initialize() {
return new (std::nothrow) shaderc_compile_options;
}
shaderc_compile_options_t shaderc_compile_options_clone(
const shaderc_compile_options_t options) {
if (!options) {
return shaderc_compile_options_initialize();
}
return new (std::nothrow) shaderc_compile_options(*options);
}
void shaderc_compile_options_release(shaderc_compile_options_t options) {
delete options;
}
void shaderc_compile_options_add_macro_definition(
shaderc_compile_options_t options, const char* name, size_t name_length,
const char* value, size_t value_length) {
options->compiler.AddMacroDefinition(name, name_length, value, value_length);
}
void shaderc_compile_options_set_source_language(
shaderc_compile_options_t options, shaderc_source_language set_lang) {
auto lang = shaderc_util::Compiler::SourceLanguage::GLSL;
if (set_lang == shaderc_source_language_hlsl)
lang = shaderc_util::Compiler::SourceLanguage::HLSL;
options->compiler.SetSourceLanguage(lang);
}
void shaderc_compile_options_set_generate_debug_info(
shaderc_compile_options_t options) {
options->compiler.SetGenerateDebugInfo();
}
void shaderc_compile_options_set_optimization_level(
shaderc_compile_options_t options, shaderc_optimization_level level) {
auto opt_level = shaderc_util::Compiler::OptimizationLevel::Zero;
switch (level) {
case shaderc_optimization_level_size:
opt_level = shaderc_util::Compiler::OptimizationLevel::Size;
break;
case shaderc_optimization_level_performance:
opt_level = shaderc_util::Compiler::OptimizationLevel::Performance;
break;
default:
break;
}
options->compiler.SetOptimizationLevel(opt_level);
}
void shaderc_compile_options_set_forced_version_profile(
shaderc_compile_options_t options, int version, shaderc_profile profile) {
switch (profile) {
case shaderc_profile_none:
options->compiler.SetForcedVersionProfile(version, ENoProfile);
break;
case shaderc_profile_core:
options->compiler.SetForcedVersionProfile(version, ECoreProfile);
break;
case shaderc_profile_compatibility:
options->compiler.SetForcedVersionProfile(version, ECompatibilityProfile);
break;
case shaderc_profile_es:
options->compiler.SetForcedVersionProfile(version, EEsProfile);
break;
}
}
void shaderc_compile_options_set_include_callbacks(
shaderc_compile_options_t options, shaderc_include_resolve_fn resolver,
shaderc_include_result_release_fn result_releaser, void* user_data) {
options->include_resolver = resolver;
options->include_result_releaser = result_releaser;
options->include_user_data = user_data;
}
void shaderc_compile_options_set_suppress_warnings(
shaderc_compile_options_t options) {
options->compiler.SetSuppressWarnings();
}
void shaderc_compile_options_set_target_env(shaderc_compile_options_t options,
shaderc_target_env target,
uint32_t version) {
options->target_env = target;
options->compiler.SetTargetEnv(GetCompilerTargetEnv(target),
GetCompilerTargetEnvVersion(version));
}
void shaderc_compile_options_set_target_spirv(shaderc_compile_options_t options,
shaderc_spirv_version ver) {
options->compiler.SetTargetSpirv(
static_cast<shaderc_util::Compiler::SpirvVersion>(ver));
}
void shaderc_compile_options_set_warnings_as_errors(
shaderc_compile_options_t options) {
options->compiler.SetWarningsAsErrors();
}
void shaderc_compile_options_set_limit(shaderc_compile_options_t options,
shaderc_limit limit, int value) {
options->compiler.SetLimit(CompilerLimit(limit), value);
}
void shaderc_compile_options_set_auto_bind_uniforms(
shaderc_compile_options_t options, bool auto_bind) {
options->compiler.SetAutoBindUniforms(auto_bind);
}
void shaderc_compile_options_set_auto_combined_image_sampler(
shaderc_compile_options_t options, bool upgrade) {
options->compiler.SetAutoCombinedImageSampler(upgrade);
}
void shaderc_compile_options_set_hlsl_io_mapping(
shaderc_compile_options_t options, bool hlsl_iomap) {
options->compiler.SetHlslIoMapping(hlsl_iomap);
}
void shaderc_compile_options_set_hlsl_offsets(shaderc_compile_options_t options,
bool hlsl_offsets) {
options->compiler.SetHlslOffsets(hlsl_offsets);
}
void shaderc_compile_options_set_binding_base(shaderc_compile_options_t options,
shaderc_uniform_kind kind,
uint32_t base) {
options->compiler.SetAutoBindingBase(GetUniformKind(kind), base);
}
void shaderc_compile_options_set_binding_base_for_stage(
shaderc_compile_options_t options, shaderc_shader_kind shader_kind,
shaderc_uniform_kind kind, uint32_t base) {
options->compiler.SetAutoBindingBaseForStage(GetStage(shader_kind),
GetUniformKind(kind), base);
}
void shaderc_compile_options_set_preserve_bindings(
shaderc_compile_options_t options, bool preserve_bindings) {
options->compiler.SetPreserveBindings(preserve_bindings);
}
void shaderc_compile_options_set_auto_map_locations(
shaderc_compile_options_t options, bool auto_map) {
options->compiler.SetAutoMapLocations(auto_map);
}
void shaderc_compile_options_set_hlsl_register_set_and_binding_for_stage(
shaderc_compile_options_t options, shaderc_shader_kind shader_kind,
const char* reg, const char* set, const char* binding) {
options->compiler.SetHlslRegisterSetAndBindingForStage(GetStage(shader_kind),
reg, set, binding);
}
void shaderc_compile_options_set_hlsl_register_set_and_binding(
shaderc_compile_options_t options, const char* reg, const char* set,
const char* binding) {
options->compiler.SetHlslRegisterSetAndBinding(reg, set, binding);
}
void shaderc_compile_options_set_hlsl_functionality1(
shaderc_compile_options_t options, bool enable) {
options->compiler.EnableHlslFunctionality1(enable);
}
void shaderc_compile_options_set_hlsl_16bit_types(
shaderc_compile_options_t options, bool enable) {
options->compiler.EnableHlsl16BitTypes(enable);
}
void shaderc_compile_options_set_vulkan_rules_relaxed(
shaderc_compile_options_t options, bool enable) {
options->compiler.SetVulkanRulesRelaxed(enable);
}
void shaderc_compile_options_set_invert_y(
shaderc_compile_options_t options, bool enable) {
options->compiler.EnableInvertY(enable);
}
void shaderc_compile_options_set_nan_clamp(shaderc_compile_options_t options,
bool enable) {
options->compiler.SetNanClamp(enable);
}
shaderc_compiler_t shaderc_compiler_initialize() {
shaderc_compiler_t compiler = new (std::nothrow) shaderc_compiler;
if (compiler) {
compiler->initializer.reset(new shaderc_util::GlslangInitializer);
}
return compiler;
}
void shaderc_compiler_release(shaderc_compiler_t compiler) {
delete compiler;
}
namespace {
shaderc_compilation_result_t CompileToSpecifiedOutputType(
const shaderc_compiler_t compiler, const char* source_text,
size_t source_text_size, shaderc_shader_kind shader_kind,
const char* input_file_name, const char* entry_point_name,
const shaderc_compile_options_t additional_options,
shaderc_util::Compiler::OutputType output_type) {
auto* result = new (std::nothrow) shaderc_compilation_result_vector;
if (!result) return nullptr;
if (!input_file_name) {
result->messages = "Input file name string was null.";
result->num_errors = 1;
result->compilation_status = shaderc_compilation_status_compilation_error;
return result;
}
result->compilation_status = shaderc_compilation_status_invalid_stage;
bool compilation_succeeded = false;
std::vector<uint32_t> compilation_output_data;
size_t compilation_output_data_size_in_bytes = 0u;
if (!compiler->initializer) return result;
TRY_IF_EXCEPTIONS_ENABLED {
std::stringstream errors;
size_t total_warnings = 0;
size_t total_errors = 0;
std::string input_file_name_str(input_file_name);
EShLanguage forced_stage = GetForcedStage(shader_kind);
shaderc_util::string_piece source_string =
shaderc_util::string_piece(source_text, source_text + source_text_size);
StageDeducer stage_deducer(shader_kind);
if (additional_options) {
InternalFileIncluder includer(additional_options->include_resolver,
additional_options->include_result_releaser,
additional_options->include_user_data);
std::tie(compilation_succeeded, compilation_output_data,
compilation_output_data_size_in_bytes) =
additional_options->compiler.Compile(
source_string, forced_stage, input_file_name_str, entry_point_name,
std::ref(stage_deducer), includer, output_type, &errors,
&total_warnings, &total_errors);
} else {
InternalFileIncluder includer;
std::tie(compilation_succeeded, compilation_output_data,
compilation_output_data_size_in_bytes) =
shaderc_util::Compiler().Compile(
source_string, forced_stage, input_file_name_str, entry_point_name,
std::ref(stage_deducer), includer, output_type, &errors,
&total_warnings, &total_errors);
}
result->messages = errors.str();
result->SetOutputData(std::move(compilation_output_data));
result->output_data_size = compilation_output_data_size_in_bytes;
result->num_warnings = total_warnings;
result->num_errors = total_errors;
if (compilation_succeeded) {
result->compilation_status = shaderc_compilation_status_success;
} else {
result->compilation_status =
stage_deducer.error() ? shaderc_compilation_status_invalid_stage
: shaderc_compilation_status_compilation_error;
}
}
CATCH_IF_EXCEPTIONS_ENABLED(...) {
result->compilation_status = shaderc_compilation_status_internal_error;
}
return result;
}
}
shaderc_compilation_result_t shaderc_compile_into_spv(
const shaderc_compiler_t compiler, const char* source_text,
size_t source_text_size, shaderc_shader_kind shader_kind,
const char* input_file_name, const char* entry_point_name,
const shaderc_compile_options_t additional_options) {
return CompileToSpecifiedOutputType(
compiler, source_text, source_text_size, shader_kind, input_file_name,
entry_point_name, additional_options,
shaderc_util::Compiler::OutputType::SpirvBinary);
}
shaderc_compilation_result_t shaderc_compile_into_spv_assembly(
const shaderc_compiler_t compiler, const char* source_text,
size_t source_text_size, shaderc_shader_kind shader_kind,
const char* input_file_name, const char* entry_point_name,
const shaderc_compile_options_t additional_options) {
return CompileToSpecifiedOutputType(
compiler, source_text, source_text_size, shader_kind, input_file_name,
entry_point_name, additional_options,
shaderc_util::Compiler::OutputType::SpirvAssemblyText);
}
shaderc_compilation_result_t shaderc_compile_into_preprocessed_text(
const shaderc_compiler_t compiler, const char* source_text,
size_t source_text_size, shaderc_shader_kind shader_kind,
const char* input_file_name, const char* entry_point_name,
const shaderc_compile_options_t additional_options) {
return CompileToSpecifiedOutputType(
compiler, source_text, source_text_size, shader_kind, input_file_name,
entry_point_name, additional_options,
shaderc_util::Compiler::OutputType::PreprocessedText);
}
shaderc_compilation_result_t shaderc_assemble_into_spv(
const shaderc_compiler_t compiler, const char* source_assembly,
size_t source_assembly_size,
const shaderc_compile_options_t additional_options) {
auto* result = new (std::nothrow) shaderc_compilation_result_spv_binary;
if (!result) return nullptr;
result->compilation_status = shaderc_compilation_status_invalid_assembly;
if (!compiler->initializer) return result;
if (source_assembly == nullptr) return result;
TRY_IF_EXCEPTIONS_ENABLED {
spv_binary assembling_output_data = nullptr;
std::string errors;
const auto target_env = additional_options ? additional_options->target_env
: shaderc_target_env_default;
const uint32_t target_env_version =
additional_options ? additional_options->target_env_version : 0;
const bool assembling_succeeded = shaderc_util::SpirvToolsAssemble(
GetCompilerTargetEnv(target_env),
GetCompilerTargetEnvVersion(target_env_version),
{source_assembly, source_assembly + source_assembly_size},
&assembling_output_data, &errors);
result->num_errors = !assembling_succeeded;
if (assembling_succeeded) {
result->SetOutputData(assembling_output_data);
result->output_data_size =
assembling_output_data->wordCount * sizeof(uint32_t);
result->compilation_status = shaderc_compilation_status_success;
} else {
result->messages = std::move(errors);
result->compilation_status = shaderc_compilation_status_invalid_assembly;
}
}
CATCH_IF_EXCEPTIONS_ENABLED(...) {
result->compilation_status = shaderc_compilation_status_internal_error;
}
return result;
}
size_t shaderc_result_get_length(const shaderc_compilation_result_t result) {
return result->output_data_size;
}
size_t shaderc_result_get_num_warnings(
const shaderc_compilation_result_t result) {
return result->num_warnings;
}
size_t shaderc_result_get_num_errors(
const shaderc_compilation_result_t result) {
return result->num_errors;
}
const char* shaderc_result_get_bytes(
const shaderc_compilation_result_t result) {
return result->GetBytes();
}
void shaderc_result_release(shaderc_compilation_result_t result) {
delete result;
}
const char* shaderc_result_get_error_message(
const shaderc_compilation_result_t result) {
return result->messages.c_str();
}
shaderc_compilation_status shaderc_result_get_compilation_status(
const shaderc_compilation_result_t result) {
return result->compilation_status;
}
void shaderc_get_spv_version(unsigned int* version, unsigned int* revision) {
*version = spv::Version;
*revision = spv::Revision;
}
bool shaderc_parse_version_profile(const char* str, int* version,
shaderc_profile* profile) {
EProfile glslang_profile;
bool success = shaderc_util::ParseVersionProfile(
std::string(str, strlen(str)), version, &glslang_profile);
if (!success) return false;
switch (glslang_profile) {
case EEsProfile:
*profile = shaderc_profile_es;
return true;
case ECoreProfile:
*profile = shaderc_profile_core;
return true;
case ECompatibilityProfile:
*profile = shaderc_profile_compatibility;
return true;
case ENoProfile:
*profile = shaderc_profile_none;
return true;
case EBadProfile:
case EProfileCount:
return false;
}
return false;
}