15 #include "flutter/fml/paths.h"
30 constexpr
const char* kEGLImageExternalExtension =
"GL_OES_EGL_image_external";
31 constexpr
const char* kEGLImageExternalExtension300 =
32 "GL_OES_EGL_image_external_essl3";
36 std::stringstream sstream(msl_version);
37 std::string version_part;
41 if (std::getline(sstream, version_part,
'.')) {
42 major = std::stoi(version_part);
43 if (std::getline(sstream, version_part,
'.')) {
44 minor = std::stoi(version_part);
45 if (std::getline(sstream, version_part,
'.')) {
46 patch = std::stoi(version_part);
50 if (major < 1 || (major == 1 && minor < 2)) {
51 std::cerr <<
"--metal-version version must be at least 1.2. Have "
52 << msl_version << std::endl;
54 return spirv_cross::CompilerMSL::Options::make_msl_version(major, minor,
59 const spirv_cross::ParsedIR& ir,
61 std::optional<uint32_t> msl_version_override = {}) {
62 auto sl_compiler = std::make_shared<spirv_cross::CompilerMSL>(ir);
63 spirv_cross::CompilerMSL::Options sl_options;
66 sl_options.msl_version = msl_version_override.value_or(
68 sl_options.ios_use_simdgroup_functions =
69 sl_options.is_ios() &&
70 sl_options.msl_version >=
71 spirv_cross::CompilerMSL::Options::make_msl_version(2, 4, 0);
72 sl_options.use_framebuffer_fetch_subpasses =
true;
73 sl_compiler->set_msl_options(sl_options);
84 SortUniforms(&ir, sl_compiler.get(), spirv_cross::SPIRType::Float);
86 SortUniforms(&ir, sl_compiler.get(), spirv_cross::SPIRType::SampledImage);
88 spv::ExecutionModel execution_model =
89 spv::ExecutionModel::ExecutionModelFragment;
91 execution_model = spv::ExecutionModel::ExecutionModelVertex;
94 uint32_t buffer_offset = 0;
95 uint32_t sampler_offset = 0;
96 for (
auto& float_id : floats) {
97 sl_compiler->add_msl_resource_binding(
98 {.stage = execution_model,
99 .basetype = spirv_cross::SPIRType::BaseType::Float,
100 .desc_set = sl_compiler->get_decoration(float_id,
101 spv::DecorationDescriptorSet),
103 sl_compiler->get_decoration(float_id, spv::DecorationBinding),
105 .msl_buffer = buffer_offset});
108 for (
auto& image_id : images) {
109 sl_compiler->add_msl_resource_binding({
110 .stage = execution_model,
111 .basetype = spirv_cross::SPIRType::BaseType::SampledImage,
113 sl_compiler->get_decoration(image_id, spv::DecorationDescriptorSet),
115 sl_compiler->get_decoration(image_id, spv::DecorationBinding),
120 .msl_texture = sampler_offset,
121 .msl_sampler = sampler_offset,
126 return CompilerBackend(sl_compiler);
130 const spirv_cross::ParsedIR& ir,
132 auto gl_compiler = std::make_shared<spirv_cross::CompilerGLSL>(ir);
133 spirv_cross::CompilerGLSL::Options sl_options;
134 sl_options.force_zero_initialized_variables =
true;
135 sl_options.vertex.fixup_clipspace =
true;
136 sl_options.vulkan_semantics =
true;
137 gl_compiler->set_common_options(sl_options);
143 auto gl_compiler = std::make_shared<spirv_cross::CompilerGLSL>(ir);
154 for (
auto&
id : ir.ids_for_constant_or_variable) {
157 gl_compiler->require_extension(kEGLImageExternalExtension300);
159 gl_compiler->require_extension(kEGLImageExternalExtension);
165 spirv_cross::CompilerGLSL::Options sl_options;
166 sl_options.force_zero_initialized_variables =
true;
167 sl_options.vertex.fixup_clipspace =
true;
174 sl_options.es =
true;
176 sl_options.version = 300;
180 gl_compiler->remap_ext_framebuffer_fetch(0, 0,
true);
182 gl_compiler->set_variable_type_remap_callback(
183 [&](
const spirv_cross::SPIRType&
type,
const std::string& var_name,
184 std::string& name_of_type) {
186 name_of_type =
"samplerExternalOES";
193 sl_options.es =
false;
195 gl_compiler->set_common_options(sl_options);
201 auto sksl_compiler = std::make_shared<CompilerSkSL>(ir);
263 : options_(source_options) {
264 if (!source_mapping || source_mapping->GetMapping() ==
nullptr) {
266 <<
"Could not read shader source or shader source was empty.";
271 COMPILER_ERROR(error_stream_) <<
"Target platform not specified.";
286 shaderc_source_language::shaderc_source_language_glsl;
288 shaderc_profile::shaderc_profile_core,
294 shaderc_source_language::shaderc_source_language_hlsl;
307 target.
env = shaderc_target_env::shaderc_target_env_opengl;
308 target.
version = shaderc_env_version::shaderc_env_version_opengl_4_5;
309 target.
spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_0;
311 target.
env = shaderc_target_env::shaderc_target_env_vulkan;
312 target.
version = shaderc_env_version::shaderc_env_version_vulkan_1_1;
313 target.
spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_3;
316 spirv_options.
target = target;
324 target.
env = shaderc_target_env::shaderc_target_env_vulkan;
325 target.
version = shaderc_env_version::shaderc_env_version_vulkan_1_1;
326 target.
spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_3;
333 spirv_options.
target = target;
340 target.
env = shaderc_target_env::shaderc_target_env_opengl;
341 target.
version = shaderc_env_version::shaderc_env_version_opengl_4_5;
342 target.
spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_0;
344 spirv_options.
target = target;
350 target.
env = shaderc_target_env::shaderc_target_env_opengl;
351 target.
version = shaderc_env_version::shaderc_env_version_opengl_4_5;
352 target.
spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_0;
359 shaderc_optimization_level::shaderc_optimization_level_zero;
360 spirv_options.
target = target;
371 for (
const auto& define : source_options.
defines) {
375 std::vector<std::string> included_file_names;
376 spirv_options.
includer = std::make_shared<Includer>(
378 [&included_file_names](
auto included_name) {
379 included_file_names.emplace_back(std::move(included_name));
388 if (!spirv_assembly_) {
391 included_file_names_ = std::move(included_file_names);
395 spirv_cross::Parser parser(
396 reinterpret_cast<const uint32_t*
>(spirv_assembly_->GetMapping()),
397 spirv_assembly_->GetSize() /
sizeof(uint32_t));
402 const auto parsed_ir =
403 std::make_shared<spirv_cross::ParsedIR>(parser.get_parsed_ir());
409 <<
"Could not create compiler for target platform.";
416 auto sl_compilation_result =
424 auto stripped_spirv_options = spirv_options;
427 error_stream_, stripped_spirv_options.BuildShadercOptions());
429 sl_mapping_ = sl_compilation_result;
433 COMPILER_ERROR(error_stream_) <<
"Could not generate SL from SPIRV";
437 reflector_ = std::make_unique<Reflector>(std::move(reflector_options),
443 if (!reflector_->IsValid()) {
445 <<
"Could not complete reflection on generated shader.";
455 return spirv_assembly_;
466 std::string Compiler::GetSourcePrefix()
const {
467 std::stringstream stream;
473 return error_stream_.str();
477 return included_file_names_;
481 const std::string& separator) {
482 std::stringstream stream;
483 for (
size_t i = 0, count = items.size(); i < count; i++) {
484 const auto is_last = (i == count - 1);
494 std::string Compiler::GetDependencyNames(
const std::string& separator)
const {
495 std::vector<std::string> dependencies = included_file_names_;
496 dependencies.push_back(options_.
file_name);
501 std::initializer_list<std::string> targets_names)
const {
503 const auto targets =
JoinStrings(targets_names,
" ");
504 const auto dependencies = GetDependencyNames(
" ");
506 std::stringstream stream;
507 stream << targets <<
": " << dependencies <<
"\n";
509 auto contents = std::make_shared<std::string>(stream.str());
510 return std::make_unique<fml::NonOwnedMapping>(
511 reinterpret_cast<const uint8_t*
>(contents->data()), contents->size(),
512 [contents](
auto,
auto) {});
516 return reflector_.get();
std::shared_ptr< fml::Mapping > GetSPIRVAssembly() const
const Reflector * GetReflector() const
Compiler(const std::shared_ptr< const fml::Mapping > &source_mapping, const SourceOptions &options, Reflector::Options reflector_options)
const std::vector< std::string > & GetIncludedFileNames() const
std::unique_ptr< fml::Mapping > CreateDepfileContents(std::initializer_list< std::string > targets) const
std::shared_ptr< fml::Mapping > GetSLShaderSource() const
std::string GetErrorMessages() const
std::shared_ptr< fml::Mapping > CompileToSPV(std::stringstream &error_stream, const shaderc::CompileOptions &spirv_options) const
#define COMPILER_ERROR(stream)
static CompilerBackend CreateSkSLCompiler(const spirv_cross::ParsedIR &ir, const SourceOptions &source_options)
static CompilerBackend CreateVulkanCompiler(const spirv_cross::ParsedIR &ir, const SourceOptions &source_options)
constexpr char kExternalTexturePrefix[]
static bool EntryPointMustBeNamedMain(TargetPlatform platform)
static CompilerBackend CreateMSLCompiler(const spirv_cross::ParsedIR &ir, const SourceOptions &source_options, std::optional< uint32_t > msl_version_override={})
static CompilerBackend CreateCompiler(const spirv_cross::ParsedIR &ir, const SourceOptions &source_options)
static std::string JoinStrings(std::vector< std::string > items, const std::string &separator)
spirv_cross::CompilerMSL::Options::Platform TargetPlatformToMSLPlatform(TargetPlatform platform)
static uint32_t ParseMSLVersion(const std::string &msl_version)
bool StringStartsWith(const std::string &target, const std::string &prefix)
static CompilerBackend CreateGLSLCompiler(const spirv_cross::ParsedIR &ir, const SourceOptions &source_options)
spv::ExecutionModel ToExecutionModel(SourceType type)
std::vector< spirv_cross::ID > SortUniforms(const spirv_cross::ParsedIR *ir, const spirv_cross::Compiler *compiler, std::optional< spirv_cross::SPIRType::BaseType > type_filter, bool include)
Sorts uniform declarations in an IR according to decoration order.
std::shared_ptr< fml::Mapping > CreateMappingWithString(std::string string)
Creates a mapping with string data.
spirv_cross::Compiler * GetCompiler()
std::optional< shaderc_source_language > source_langauge
std::vector< std::string > macro_definitions
bool relaxed_vulkan_rules
shaderc_optimization_level optimization_level
std::optional< SPIRVCompilerSourceProfile > source_profile
std::shared_ptr< Includer > includer
shaderc::CompileOptions BuildShadercOptions() const
std::optional< SPIRVCompilerTargetEnv > target
shaderc_spirv_version spirv_version
shaderc_env_version version
uint32_t gles_language_version
bool use_half_textures
Whether half-precision textures should be supported, requiring opengl semantics. Only used on metal t...
SourceLanguage source_language
std::vector< IncludeDir > include_dirs
bool require_framebuffer_fetch
Whether the GLSL framebuffer fetch extension will be required.
std::string entry_point_name
TargetPlatform target_platform
std::shared_ptr< fml::UniqueFD > working_directory
std::string metal_version
std::vector< std::string > defines