14 #include "flutter/fml/paths.h"
28 std::stringstream sstream(msl_version);
29 std::string version_part;
33 if (std::getline(sstream, version_part,
'.')) {
34 major = std::stoi(version_part);
35 if (std::getline(sstream, version_part,
'.')) {
36 minor = std::stoi(version_part);
37 if (std::getline(sstream, version_part,
'.')) {
38 patch = std::stoi(version_part);
42 if (major < 1 || (major == 1 && minor < 2)) {
43 std::cerr <<
"--metal-version version must be at least 1.2. Have "
44 << msl_version << std::endl;
46 return spirv_cross::CompilerMSL::Options::make_msl_version(major, minor,
51 const spirv_cross::ParsedIR& ir,
53 std::optional<uint32_t> msl_version_override = {}) {
54 auto sl_compiler = std::make_shared<spirv_cross::CompilerMSL>(ir);
55 spirv_cross::CompilerMSL::Options sl_options;
58 sl_options.msl_version = msl_version_override.value_or(
60 sl_options.ios_use_simdgroup_functions =
61 sl_options.is_ios() &&
62 sl_options.msl_version >=
63 spirv_cross::CompilerMSL::Options::make_msl_version(2, 4, 0);
64 sl_options.use_framebuffer_fetch_subpasses =
true;
65 sl_compiler->set_msl_options(sl_options);
76 SortUniforms(&ir, sl_compiler.get(), spirv_cross::SPIRType::Float);
78 SortUniforms(&ir, sl_compiler.get(), spirv_cross::SPIRType::SampledImage);
80 uint32_t buffer_offset = 0;
81 uint32_t sampler_offset = 0;
82 for (
auto& float_id : floats) {
83 sl_compiler->add_msl_resource_binding(
84 {.stage = spv::ExecutionModel::ExecutionModelFragment,
85 .basetype = spirv_cross::SPIRType::BaseType::Float,
86 .desc_set = sl_compiler->get_decoration(float_id,
87 spv::DecorationDescriptorSet),
89 sl_compiler->get_decoration(float_id, spv::DecorationBinding),
91 .msl_buffer = buffer_offset});
94 for (
auto& image_id : images) {
95 sl_compiler->add_msl_resource_binding({
96 .stage = spv::ExecutionModel::ExecutionModelFragment,
97 .basetype = spirv_cross::SPIRType::BaseType::SampledImage,
99 sl_compiler->get_decoration(image_id, spv::DecorationDescriptorSet),
101 sl_compiler->get_decoration(image_id, spv::DecorationBinding),
106 .msl_texture = sampler_offset,
107 .msl_sampler = sampler_offset,
112 return CompilerBackend(sl_compiler);
116 const spirv_cross::ParsedIR& ir,
126 spirv_cross::CompilerMSL::Options::make_msl_version(3, 0, 0));
131 auto gl_compiler = std::make_shared<spirv_cross::CompilerGLSL>(ir);
142 for (
auto&
id : ir.ids_for_constant_or_variable) {
144 gl_compiler->require_extension(
"GL_OES_EGL_image_external");
149 spirv_cross::CompilerGLSL::Options sl_options;
150 sl_options.force_zero_initialized_variables =
true;
151 sl_options.vertex.fixup_clipspace =
true;
157 sl_options.es =
true;
158 gl_compiler->set_variable_type_remap_callback(
159 [&](
const spirv_cross::SPIRType& type,
const std::string& var_name,
160 std::string& name_of_type) {
162 name_of_type =
"samplerExternalOES";
169 sl_options.es =
false;
171 gl_compiler->set_common_options(sl_options);
177 auto sksl_compiler = std::make_shared<CompilerSkSL>(ir);
237 : options_(source_options) {
238 if (!source_mapping || source_mapping->GetMapping() ==
nullptr) {
240 <<
"Could not read shader source or shader source was empty.";
245 COMPILER_ERROR(error_stream_) <<
"Target platform not specified.";
260 shaderc_source_language::shaderc_source_language_glsl;
262 shaderc_profile::shaderc_profile_core,
268 shaderc_source_language::shaderc_source_language_hlsl;
281 target.
env = shaderc_target_env::shaderc_target_env_opengl;
282 target.
version = shaderc_env_version::shaderc_env_version_opengl_4_5;
283 target.
spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_0;
285 target.
env = shaderc_target_env::shaderc_target_env_vulkan;
286 target.
version = shaderc_env_version::shaderc_env_version_vulkan_1_1;
287 target.
spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_3;
290 spirv_options.
target = target;
297 target.
env = shaderc_target_env::shaderc_target_env_vulkan;
298 target.
version = shaderc_env_version::shaderc_env_version_vulkan_1_1;
299 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_opengl;
309 target.
version = shaderc_env_version::shaderc_env_version_opengl_4_5;
310 target.
spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_0;
312 spirv_options.
target = target;
318 target.
env = shaderc_target_env::shaderc_target_env_opengl;
319 target.
version = shaderc_env_version::shaderc_env_version_opengl_4_5;
320 target.
spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_0;
327 shaderc_optimization_level::shaderc_optimization_level_zero;
328 spirv_options.
target = target;
339 for (
const auto& define : source_options.
defines) {
343 std::vector<std::string> included_file_names;
344 spirv_options.
includer = std::make_shared<Includer>(
346 [&included_file_names](
auto included_name) {
347 included_file_names.emplace_back(std::move(included_name));
356 if (!spirv_assembly_) {
359 included_file_names_ = std::move(included_file_names);
363 spirv_cross::Parser parser(
364 reinterpret_cast<const uint32_t*
>(spirv_assembly_->GetMapping()),
365 spirv_assembly_->GetSize() /
sizeof(uint32_t));
370 const auto parsed_ir =
371 std::make_shared<spirv_cross::ParsedIR>(parser.get_parsed_ir());
377 <<
"Could not create compiler for target platform.";
384 auto sl_compilation_result =
391 auto stripped_spirv_options = spirv_options;
394 error_stream_, stripped_spirv_options.BuildShadercOptions());
396 sl_mapping_ = sl_compilation_result;
400 COMPILER_ERROR(error_stream_) <<
"Could not generate SL from SPIRV";
404 reflector_ = std::make_unique<Reflector>(std::move(reflector_options),
410 if (!reflector_->IsValid()) {
412 <<
"Could not complete reflection on generated shader.";
422 return spirv_assembly_;
433 std::string Compiler::GetSourcePrefix()
const {
434 std::stringstream stream;
440 return error_stream_.str();
444 return included_file_names_;
448 const std::string& separator) {
449 std::stringstream stream;
450 for (
size_t i = 0, count = items.size(); i < count; i++) {
451 const auto is_last = (i == count - 1);
461 std::string Compiler::GetDependencyNames(
const std::string& separator)
const {
462 std::vector<std::string> dependencies = included_file_names_;
463 dependencies.push_back(options_.
file_name);
468 std::initializer_list<std::string> targets_names)
const {
470 const auto targets =
JoinStrings(targets_names,
" ");
471 const auto dependencies = GetDependencyNames(
" ");
473 std::stringstream stream;
474 stream << targets <<
": " << dependencies <<
"\n";
476 auto contents = std::make_shared<std::string>(stream.str());
477 return std::make_unique<fml::NonOwnedMapping>(
478 reinterpret_cast<const uint8_t*
>(contents->data()), contents->size(),
479 [contents](
auto,
auto) {});
483 return reflector_.get();