diff --git a/engine/src/flutter/impeller/compiler/BUILD.gn b/engine/src/flutter/impeller/compiler/BUILD.gn index 4ec2db0dfb1..aaacc2a27c4 100644 --- a/engine/src/flutter/impeller/compiler/BUILD.gn +++ b/engine/src/flutter/impeller/compiler/BUILD.gn @@ -11,6 +11,8 @@ source_set("compiler_lib") { "logger.h", "reflector.cc", "reflector.h", + "switches.cc", + "switches.h", ] public_deps = [ @@ -22,14 +24,16 @@ source_set("compiler_lib") { ] } -executable("compiler") { - output_name = "impellerc" - +executable("impellerc") { sources = [ "impellerc_main.cc" ] deps = [ ":compiler_lib" ] } +group("compiler") { + deps = [ ":impellerc" ] +} + test_fixtures("compiler_test_fixtures") { fixtures = [ "fixtures/sample.frag", diff --git a/engine/src/flutter/impeller/compiler/impellerc_main.cc b/engine/src/flutter/impeller/compiler/impellerc_main.cc index 619bdd212f3..822bc4c0256 100644 --- a/engine/src/flutter/impeller/compiler/impellerc_main.cc +++ b/engine/src/flutter/impeller/compiler/impellerc_main.cc @@ -3,14 +3,65 @@ // found in the LICENSE file. #include "flutter/fml/command_line.h" +#include "flutter/fml/file.h" #include "flutter/fml/macros.h" +#include "flutter/fml/mapping.h" +#include "flutter/impeller/compiler/compiler.h" +#include "flutter/impeller/compiler/switches.h" #include "third_party/shaderc/libshaderc/include/shaderc/shaderc.hpp" namespace impeller { namespace compiler { bool Main(const fml::CommandLine& command_line) { - return false; + if (command_line.HasOption("help")) { + Switches::PrintHelp(std::cout); + return true; + } + + Switches switches(command_line); + if (!switches.AreValid(std::cerr)) { + std::cerr << "Invalid flags specified." << std::endl; + Switches::PrintHelp(std::cerr); + return false; + } + + auto source_file_mapping = fml::FileMapping::CreateReadOnly( + *switches.working_directory, switches.source_file_name); + if (!source_file_mapping) { + std::cerr << "Could not open input file." << std::endl; + return false; + } + + Compiler::SourceOptions options; + options.type = Compiler::SourceTypeFromFileName(switches.source_file_name); + options.working_directory = switches.working_directory; + options.file_name = switches.source_file_name; + + Compiler compiler(*source_file_mapping, options); + if (!compiler.IsValid()) { + std::cerr << "Compilation failed." << std::endl; + std::cerr << compiler.GetErrorMessages() << std::endl; + return false; + } + + if (!fml::WriteAtomically(*switches.working_directory, + switches.spirv_file_name.c_str(), + *compiler.GetSPIRVAssembly())) { + std::cerr << "Could not write file to " << switches.spirv_file_name + << std::endl; + return false; + } + + if (!fml::WriteAtomically(*switches.working_directory, + switches.metal_file_name.c_str(), + *compiler.GetMSLShaderSource())) { + std::cerr << "Could not write file to " << switches.spirv_file_name + << std::endl; + return false; + } + + return true; } } // namespace compiler diff --git a/engine/src/flutter/impeller/compiler/switches.cc b/engine/src/flutter/impeller/compiler/switches.cc new file mode 100644 index 00000000000..5cb06593d00 --- /dev/null +++ b/engine/src/flutter/impeller/compiler/switches.cc @@ -0,0 +1,59 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "flutter/impeller/compiler/switches.h" + +#include + +#include "flutter/fml/file.h" + +namespace impeller { +namespace compiler { + +void Switches::PrintHelp(std::ostream& stream) { + stream << std::endl << "Valid Argument are:" << std::endl; + stream << "--input=" << std::endl; + stream << "--metal=" << std::endl; + stream << "--spirv=" << std::endl; +} + +Switches::Switches() = default; + +Switches::~Switches() = default; + +Switches::Switches(const fml::CommandLine& command_line) + : working_directory(std::make_shared( + fml::OpenDirectory(std::filesystem::current_path().native().c_str(), + false, // create if necessary, + fml::FilePermission::kRead))), + source_file_name(command_line.GetOptionValueWithDefault("input", "")), + metal_file_name(command_line.GetOptionValueWithDefault("metal", "")), + spirv_file_name(command_line.GetOptionValueWithDefault("spirv", "")) {} + +bool Switches::AreValid(std::ostream& explain) const { + bool valid = true; + if (!working_directory || !working_directory->is_valid()) { + explain << "Could not figure out working directory." << std::endl; + valid = false; + } + + if (source_file_name.empty()) { + explain << "Input file name was empty." << std::endl; + valid = false; + } + + if (metal_file_name.empty()) { + explain << "Metal file name was empty." << std::endl; + valid = false; + } + + if (spirv_file_name.empty()) { + explain << "Spirv file name was empty." << std::endl; + valid = false; + } + return valid; +} + +} // namespace compiler +} // namespace impeller diff --git a/engine/src/flutter/impeller/compiler/switches.h b/engine/src/flutter/impeller/compiler/switches.h new file mode 100644 index 00000000000..0259f253081 --- /dev/null +++ b/engine/src/flutter/impeller/compiler/switches.h @@ -0,0 +1,35 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#pragma once + +#include +#include + +#include "flutter/fml/command_line.h" +#include "flutter/fml/macros.h" +#include "flutter/fml/unique_fd.h" + +namespace impeller { +namespace compiler { + +struct Switches { + std::shared_ptr working_directory; + std::string source_file_name; + std::string metal_file_name; + std::string spirv_file_name; + + Switches(); + + ~Switches(); + + Switches(const fml::CommandLine& command_line); + + bool AreValid(std::ostream& explain) const; + + static void PrintHelp(std::ostream& stream); +}; + +} // namespace compiler +} // namespace impeller diff --git a/engine/src/flutter/impeller/compiler/tools/compiler.gni b/engine/src/flutter/impeller/compiler/tools/compiler.gni index d73f5f64632..2ec27e44790 100644 --- a/engine/src/flutter/impeller/compiler/tools/compiler.gni +++ b/engine/src/flutter/impeller/compiler/tools/compiler.gni @@ -2,6 +2,32 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/compiled_action.gni") + template("impeller_shaders") { - assert(defined(invoker.shaders), "Impeller shaders must be specified.") + compiled_action_foreach(target_name) { + assert(defined(invoker.shaders), "Impeller shaders must be specified.") + + tool = "//flutter/impeller/compiler:impellerc" + + sources = invoker.shaders + + metal_intermediate = "$target_gen_dir/{{source_file_part}}.metal" + spirv_intermediate = "$target_gen_dir/{{source_file_part}}.spirv" + + outputs = [ + metal_intermediate, + spirv_intermediate, + ] + + source_path = "{{source}}" + metal_intermediate_path = rebase_path(metal_intermediate, root_build_dir) + spirv_intermediate_path = rebase_path(spirv_intermediate, root_build_dir) + + args = [ + "--input=$source_path", + "--metal=$metal_intermediate_path", + "--spirv=$spirv_intermediate_path", + ] + } } diff --git a/engine/src/flutter/impeller/impeller/BUILD.gn b/engine/src/flutter/impeller/impeller/BUILD.gn index 414a45dfef1..1199d9a5937 100644 --- a/engine/src/flutter/impeller/impeller/BUILD.gn +++ b/engine/src/flutter/impeller/impeller/BUILD.gn @@ -3,6 +3,7 @@ # found in the LICENSE file. import("//flutter/common/config.gni") +import("//flutter/impeller/compiler/tools/compiler.gni") config("impeller_config") { include_dirs = [ ".." ] @@ -86,6 +87,7 @@ source_set("impeller") { compositor_sources + geometry_sources + entity_sources + image_sources deps = [ + ":shaders", "//flutter/fml", "//flutter/impeller/third_party/stb", "//flutter/runtime:libdart", # For tracing, seems to be pulled in by FML.