15 #include "flutter/fml/paths.h"
29 std::stringstream sstream(msl_version);
30 std::string version_part;
34 if (std::getline(sstream, version_part,
'.')) {
35 major = std::stoi(version_part);
36 if (std::getline(sstream, version_part,
'.')) {
37 minor = std::stoi(version_part);
38 if (std::getline(sstream, version_part,
'.')) {
39 patch = std::stoi(version_part);
43 if (major < 1 || (major == 1 && minor < 2)) {
44 std::cerr <<
"--metal-version version must be at least 1.2. Have "
45 << msl_version << std::endl;
47 return spirv_cross::CompilerMSL::Options::make_msl_version(major, minor,
52 const spirv_cross::ParsedIR& ir,
54 std::optional<uint32_t> msl_version_override = {}) {
55 auto sl_compiler = std::make_shared<spirv_cross::CompilerMSL>(ir);
56 spirv_cross::CompilerMSL::Options sl_options;
59 sl_options.msl_version = msl_version_override.value_or(
61 sl_options.ios_use_simdgroup_functions =
62 sl_options.is_ios() &&
63 sl_options.msl_version >=
64 spirv_cross::CompilerMSL::Options::make_msl_version(2, 4, 0);
65 sl_options.use_framebuffer_fetch_subpasses =
true;
66 sl_compiler->set_msl_options(sl_options);
77 SortUniforms(&ir, sl_compiler.get(), spirv_cross::SPIRType::Float);
79 SortUniforms(&ir, sl_compiler.get(), spirv_cross::SPIRType::SampledImage);
81 spv::ExecutionModel execution_model =
82 spv::ExecutionModel::ExecutionModelFragment;
84 execution_model = spv::ExecutionModel::ExecutionModelVertex;
87 uint32_t buffer_offset = 0;
88 uint32_t sampler_offset = 0;
89 for (
auto& float_id : floats) {
90 sl_compiler->add_msl_resource_binding(
91 {.stage = execution_model,
92 .basetype = spirv_cross::SPIRType::BaseType::Float,
93 .desc_set = sl_compiler->get_decoration(float_id,
94 spv::DecorationDescriptorSet),
96 sl_compiler->get_decoration(float_id, spv::DecorationBinding),
98 .msl_buffer = buffer_offset});
101 for (
auto& image_id : images) {
102 sl_compiler->add_msl_resource_binding({
103 .stage = execution_model,
104 .basetype = spirv_cross::SPIRType::BaseType::SampledImage,
106 sl_compiler->get_decoration(image_id, spv::DecorationDescriptorSet),
108 sl_compiler->get_decoration(image_id, spv::DecorationBinding),
113 .msl_texture = sampler_offset,
114 .msl_sampler = sampler_offset,
119 return CompilerBackend(sl_compiler);
123 const spirv_cross::ParsedIR& ir,
133 spirv_cross::CompilerMSL::Options::make_msl_version(3, 0, 0));
138 auto gl_compiler = std::make_shared<spirv_cross::CompilerGLSL>(ir);
149 for (
auto&
id : ir.ids_for_constant_or_variable) {
151 gl_compiler->require_extension(
"GL_OES_EGL_image_external");
156 spirv_cross::CompilerGLSL::Options sl_options;
157 sl_options.force_zero_initialized_variables =
true;
158 sl_options.vertex.fixup_clipspace =
true;
164 sl_options.es =
true;
167 gl_compiler->remap_ext_framebuffer_fetch(0, 0,
true);
169 gl_compiler->set_variable_type_remap_callback(
170 [&](
const spirv_cross::SPIRType& type,
const std::string& var_name,
171 std::string& name_of_type) {
173 name_of_type =
"samplerExternalOES";
180 sl_options.es =
false;
182 gl_compiler->set_common_options(sl_options);
188 auto sksl_compiler = std::make_shared<CompilerSkSL>(ir);
248 : options_(source_options) {
249 if (!source_mapping || source_mapping->GetMapping() ==
nullptr) {
251 <<
"Could not read shader source or shader source was empty.";
256 COMPILER_ERROR(error_stream_) <<
"Target platform not specified.";
271 shaderc_source_language::shaderc_source_language_glsl;
273 shaderc_profile::shaderc_profile_core,
279 shaderc_source_language::shaderc_source_language_hlsl;
292 target.
env = shaderc_target_env::shaderc_target_env_opengl;
293 target.
version = shaderc_env_version::shaderc_env_version_opengl_4_5;
294 target.
spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_0;
296 target.
env = shaderc_target_env::shaderc_target_env_vulkan;
297 target.
version = shaderc_env_version::shaderc_env_version_vulkan_1_1;
298 target.
spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_3;
301 spirv_options.
target = target;
308 target.
env = shaderc_target_env::shaderc_target_env_vulkan;
309 target.
version = shaderc_env_version::shaderc_env_version_vulkan_1_1;
310 target.
spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_3;
312 spirv_options.
target = target;
319 target.
env = shaderc_target_env::shaderc_target_env_opengl;
320 target.
version = shaderc_env_version::shaderc_env_version_opengl_4_5;
321 target.
spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_0;
323 spirv_options.
target = target;
329 target.
env = shaderc_target_env::shaderc_target_env_opengl;
330 target.
version = shaderc_env_version::shaderc_env_version_opengl_4_5;
331 target.
spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_0;
338 shaderc_optimization_level::shaderc_optimization_level_zero;
339 spirv_options.
target = target;
350 for (
const auto& define : source_options.
defines) {
354 std::vector<std::string> included_file_names;
355 spirv_options.
includer = std::make_shared<Includer>(
357 [&included_file_names](
auto included_name) {
358 included_file_names.emplace_back(std::move(included_name));
367 if (!spirv_assembly_) {
370 included_file_names_ = std::move(included_file_names);
374 spirv_cross::Parser parser(
375 reinterpret_cast<const uint32_t*
>(spirv_assembly_->GetMapping()),
376 spirv_assembly_->GetSize() /
sizeof(uint32_t));
381 const auto parsed_ir =
382 std::make_shared<spirv_cross::ParsedIR>(parser.get_parsed_ir());
388 <<
"Could not create compiler for target platform.";
395 auto sl_compilation_result =
402 auto stripped_spirv_options = spirv_options;
405 error_stream_, stripped_spirv_options.BuildShadercOptions());
407 sl_mapping_ = sl_compilation_result;
411 COMPILER_ERROR(error_stream_) <<
"Could not generate SL from SPIRV";
415 reflector_ = std::make_unique<Reflector>(std::move(reflector_options),
421 if (!reflector_->IsValid()) {
423 <<
"Could not complete reflection on generated shader.";
433 return spirv_assembly_;
444 std::string Compiler::GetSourcePrefix()
const {
445 std::stringstream stream;
451 return error_stream_.str();
455 return included_file_names_;
459 const std::string& separator) {
460 std::stringstream stream;
461 for (
size_t i = 0, count = items.size(); i < count; i++) {
462 const auto is_last = (i == count - 1);
472 std::string Compiler::GetDependencyNames(
const std::string& separator)
const {
473 std::vector<std::string> dependencies = included_file_names_;
474 dependencies.push_back(options_.
file_name);
479 std::initializer_list<std::string> targets_names)
const {
481 const auto targets =
JoinStrings(targets_names,
" ");
482 const auto dependencies = GetDependencyNames(
" ");
484 std::stringstream stream;
485 stream << targets <<
": " << dependencies <<
"\n";
487 auto contents = std::make_shared<std::string>(stream.str());
488 return std::make_unique<fml::NonOwnedMapping>(
489 reinterpret_cast<const uint8_t*
>(contents->data()), contents->size(),
490 [contents](
auto,
auto) {});
494 return reflector_.get();