15#include "flutter/fml/paths.h"
30 std::stringstream sstream(msl_version);
31 std::string version_part;
35 if (std::getline(sstream, version_part,
'.')) {
37 if (std::getline(sstream, version_part,
'.')) {
39 if (std::getline(sstream, version_part,
'.')) {
44 if (major < 1 || (major == 1 && minor < 2)) {
45 std::cerr <<
"--metal-version version must be at least 1.2. Have "
46 << msl_version << std::endl;
48 return spirv_cross::CompilerMSL::Options::make_msl_version(major, minor,
53 const spirv_cross::ParsedIR& ir,
55 std::optional<uint32_t> msl_version_override = {}) {
56 auto sl_compiler = std::make_shared<spirv_cross::CompilerMSL>(ir);
57 spirv_cross::CompilerMSL::Options sl_options;
60 sl_options.msl_version = msl_version_override.value_or(
62 sl_options.ios_use_simdgroup_functions =
63 sl_options.is_ios() &&
64 sl_options.msl_version >=
65 spirv_cross::CompilerMSL::Options::make_msl_version(2, 4, 0);
66 sl_options.use_framebuffer_fetch_subpasses =
true;
67 sl_compiler->set_msl_options(sl_options);
78 SortUniforms(&ir, sl_compiler.get(), spirv_cross::SPIRType::Float);
80 SortUniforms(&ir, sl_compiler.get(), spirv_cross::SPIRType::SampledImage);
82 spv::ExecutionModel execution_model =
83 spv::ExecutionModel::ExecutionModelFragment;
85 execution_model = spv::ExecutionModel::ExecutionModelVertex;
88 uint32_t buffer_offset = 0;
89 uint32_t sampler_offset = 0;
90 for (
auto& float_id : floats) {
91 sl_compiler->add_msl_resource_binding(
92 {.stage = execution_model,
93 .basetype = spirv_cross::SPIRType::BaseType::Float,
94 .desc_set = sl_compiler->get_decoration(float_id,
95 spv::DecorationDescriptorSet),
97 sl_compiler->get_decoration(float_id, spv::DecorationBinding),
99 .msl_buffer = buffer_offset});
102 for (
auto& image_id :
images) {
103 sl_compiler->add_msl_resource_binding({
104 .stage = execution_model,
105 .basetype = spirv_cross::SPIRType::BaseType::SampledImage,
107 sl_compiler->get_decoration(image_id, spv::DecorationDescriptorSet),
109 sl_compiler->get_decoration(image_id, spv::DecorationBinding),
114 .msl_texture = sampler_offset,
115 .msl_sampler = sampler_offset,
120 return CompilerBackend(sl_compiler);
124 const spirv_cross::ParsedIR& ir,
126 auto gl_compiler = std::make_shared<spirv_cross::CompilerGLSL>(ir);
127 spirv_cross::CompilerGLSL::Options sl_options;
128 sl_options.force_zero_initialized_variables =
true;
129 sl_options.vertex.fixup_clipspace =
true;
130 sl_options.vulkan_semantics =
true;
131 gl_compiler->set_common_options(sl_options);
137 auto gl_compiler = std::make_shared<spirv_cross::CompilerGLSL>(ir);
148 for (
auto&
id : ir.ids_for_constant_or_variable) {
150 gl_compiler->require_extension(
"GL_OES_EGL_image_external");
155 spirv_cross::CompilerGLSL::Options sl_options;
156 sl_options.force_zero_initialized_variables =
true;
157 sl_options.vertex.fixup_clipspace =
true;
163 sl_options.es =
true;
166 gl_compiler->remap_ext_framebuffer_fetch(0, 0,
true);
168 gl_compiler->set_variable_type_remap_callback(
169 [&](
const spirv_cross::SPIRType&
type,
const std::string& var_name,
170 std::string& name_of_type) {
172 name_of_type =
"samplerExternalOES";
179 sl_options.es =
false;
181 gl_compiler->set_common_options(sl_options);
187 auto sksl_compiler = std::make_shared<CompilerSkSL>(ir);
247 : options_(source_options) {
248 if (!source_mapping || source_mapping->GetMapping() ==
nullptr) {
250 <<
"Could not read shader source or shader source was empty.";
255 COMPILER_ERROR(error_stream_) <<
"Target platform not specified.";
270 shaderc_source_language::shaderc_source_language_glsl;
272 shaderc_profile::shaderc_profile_core,
278 shaderc_source_language::shaderc_source_language_hlsl;
291 target.env = shaderc_target_env::shaderc_target_env_opengl;
292 target.version = shaderc_env_version::shaderc_env_version_opengl_4_5;
293 target.spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_0;
295 target.env = shaderc_target_env::shaderc_target_env_vulkan;
296 target.version = shaderc_env_version::shaderc_env_version_vulkan_1_1;
297 target.spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_3;
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;
323 target.env = shaderc_target_env::shaderc_target_env_opengl;
324 target.version = shaderc_env_version::shaderc_env_version_opengl_4_5;
325 target.spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_0;
333 target.env = shaderc_target_env::shaderc_target_env_opengl;
334 target.version = shaderc_env_version::shaderc_env_version_opengl_4_5;
335 target.spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_0;
342 shaderc_optimization_level::shaderc_optimization_level_zero;
354 for (
const auto& define : source_options.
defines) {
358 std::vector<std::string> included_file_names;
359 spirv_options.
includer = std::make_shared<Includer>(
361 [&included_file_names](
auto included_name) {
362 included_file_names.emplace_back(std::move(included_name));
371 if (!spirv_assembly_) {
374 included_file_names_ = std::move(included_file_names);
378 spirv_cross::Parser
parser(
379 reinterpret_cast<const uint32_t*
>(spirv_assembly_->GetMapping()),
380 spirv_assembly_->GetSize() /
sizeof(uint32_t));
385 const auto parsed_ir =
386 std::make_shared<spirv_cross::ParsedIR>(
parser.get_parsed_ir());
392 <<
"Could not create compiler for target platform.";
399 auto sl_compilation_result =
407 auto stripped_spirv_options = spirv_options;
410 error_stream_, stripped_spirv_options.BuildShadercOptions());
412 sl_mapping_ = sl_compilation_result;
416 COMPILER_ERROR(error_stream_) <<
"Could not generate SL from SPIRV";
420 reflector_ = std::make_unique<Reflector>(std::move(reflector_options),
426 if (!reflector_->IsValid()) {
428 <<
"Could not complete reflection on generated shader.";
438 return spirv_assembly_;
449std::string Compiler::GetSourcePrefix()
const {
456 return error_stream_.str();
460 return included_file_names_;
464 const std::string& separator) {
467 const auto is_last = (
i ==
count - 1);
477std::string Compiler::GetDependencyNames(
const std::string& separator)
const {
478 std::vector<std::string>
dependencies = included_file_names_;
484 std::initializer_list<std::string> targets_names)
const {
486 const auto targets =
JoinStrings(targets_names,
" ");
492 auto contents = std::make_shared<std::string>(
stream.str());
493 return std::make_unique<fml::NonOwnedMapping>(
494 reinterpret_cast<const uint8_t*
>(contents->data()), contents->size(),
495 [contents](
auto,
auto) {});
499 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 FML_UNREACHABLE()
#define COMPILER_ERROR(stream)
std::array< MockImage, 3 > images
bool stoi(std::string_view s, SKSL_INT *value)
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)
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
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