Flutter Engine
The Flutter Engine
impellerc_main.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <filesystem>
6#include <system_error>
7
8#include "flutter/fml/backtrace.h"
9#include "flutter/fml/command_line.h"
10#include "flutter/fml/file.h"
11#include "flutter/fml/mapping.h"
19
20namespace impeller {
21namespace compiler {
22
24 const Switches& switches) {
25 Reflector::Options reflector_options;
26 reflector_options.target_platform = options.target_platform;
27 reflector_options.entry_point_name = options.entry_point_name;
28 reflector_options.shader_name =
30 reflector_options.header_file_name = Utf8FromPath(
32 return reflector_options;
33}
34
35/// Run the shader compiler to geneate SkSL reflection data.
36/// If there is an error, prints error text and returns `nullptr`.
37static std::shared_ptr<RuntimeStageData::Shader> CompileSkSL(
38 std::shared_ptr<fml::Mapping> source_file_mapping,
39 const Switches& switches) {
41
42 Reflector::Options sksl_reflector_options =
44 sksl_reflector_options.target_platform = TargetPlatform::kSkSL;
45
46 Compiler sksl_compiler =
47 Compiler(std::move(source_file_mapping), options, sksl_reflector_options);
48 if (!sksl_compiler.IsValid()) {
49 std::cerr << "Compilation to SkSL failed." << std::endl;
50 std::cerr << sksl_compiler.GetErrorMessages() << std::endl;
51 return nullptr;
52 }
53 return sksl_compiler.GetReflector()->GetRuntimeStageShaderData();
54}
55
56static bool OutputIPLR(
57 const Switches& switches,
58 const std::shared_ptr<fml::Mapping>& source_file_mapping) {
59 FML_DCHECK(switches.iplr);
60
61 RuntimeStageData stages;
62 std::shared_ptr<RuntimeStageData::Shader> sksl_shader;
64 sksl_shader = CompileSkSL(source_file_mapping, switches);
65 if (!sksl_shader) {
66 return false;
67 }
68 stages.AddShader(sksl_shader);
69 }
70
71 for (const auto& platform : switches.PlatformsToCompile()) {
72 if (platform == TargetPlatform::kSkSL) {
73 // Already handled above.
74 continue;
75 }
76 SourceOptions options = switches.CreateSourceOptions(platform);
77
78 // Invoke the compiler and generate reflection data for a single shader.
79
80 Reflector::Options reflector_options =
82 Compiler compiler(source_file_mapping, options, reflector_options);
83 if (!compiler.IsValid()) {
84 std::cerr << "Compilation failed." << std::endl;
85 std::cerr << compiler.GetErrorMessages() << std::endl;
86 return false;
87 }
88
89 auto reflector = compiler.GetReflector();
90 if (reflector == nullptr) {
91 std::cerr << "Could not create reflector." << std::endl;
92 return false;
93 }
94
95 auto stage_data = reflector->GetRuntimeStageShaderData();
96 if (!stage_data) {
97 std::cerr << "Runtime stage information was nil." << std::endl;
98 return false;
99 }
100
101 stages.AddShader(stage_data);
102 }
103
104 auto stage_data_mapping = switches.json_format ? stages.CreateJsonMapping()
105 : stages.CreateMapping();
106 if (!stage_data_mapping) {
107 std::cerr << "Runtime stage data could not be created." << std::endl;
108 return false;
109 }
110 if (!fml::WriteAtomically(*switches.working_directory, //
111 Utf8FromPath(switches.sl_file_name).c_str(), //
112 *stage_data_mapping //
113 )) {
114 std::cerr << "Could not write file to " << switches.sl_file_name
115 << std::endl;
116 return false;
117 }
118 // Tools that consume the runtime stage data expect the access mode to
119 // be 0644.
120 if (!SetPermissiveAccess(switches.sl_file_name)) {
121 return false;
122 }
123 return true;
124}
125
126static bool OutputSLFile(const Compiler& compiler, const Switches& switches) {
127 // --------------------------------------------------------------------------
128 /// 2. Output the source file. When in IPLR/RuntimeStage mode, output the
129 /// serialized IPLR flatbuffer.
130 ///
131
132 auto sl_file_name = std::filesystem::absolute(
133 std::filesystem::current_path() / switches.sl_file_name);
135 Utf8FromPath(sl_file_name).c_str(),
136 *compiler.GetSLShaderSource())) {
137 std::cerr << "Could not write file to " << switches.sl_file_name
138 << std::endl;
139 return false;
140 }
141 return true;
142}
143
145 const Switches& switches,
146 const SourceOptions& options) {
147 // --------------------------------------------------------------------------
148 /// 3. Output shader reflection data.
149 /// May include a JSON file, a C++ header, and/or a C++ TU.
150 ///
151
152 if (TargetPlatformNeedsReflection(options.target_platform)) {
153 if (!switches.reflection_json_name.empty()) {
154 auto reflection_json_name = std::filesystem::absolute(
155 std::filesystem::current_path() / switches.reflection_json_name);
157 *switches.working_directory,
158 Utf8FromPath(reflection_json_name).c_str(),
159 *compiler.GetReflector()->GetReflectionJSON())) {
160 std::cerr << "Could not write reflection json to "
161 << switches.reflection_json_name << std::endl;
162 return false;
163 }
164 }
165
166 if (!switches.reflection_header_name.empty()) {
167 auto reflection_header_name =
168 std::filesystem::absolute(std::filesystem::current_path() /
169 switches.reflection_header_name.c_str());
171 *switches.working_directory,
172 Utf8FromPath(reflection_header_name).c_str(),
173 *compiler.GetReflector()->GetReflectionHeader())) {
174 std::cerr << "Could not write reflection header to "
175 << switches.reflection_header_name << std::endl;
176 return false;
177 }
178 }
179
180 if (!switches.reflection_cc_name.empty()) {
181 auto reflection_cc_name =
182 std::filesystem::absolute(std::filesystem::current_path() /
183 switches.reflection_cc_name.c_str());
185 Utf8FromPath(reflection_cc_name).c_str(),
186 *compiler.GetReflector()->GetReflectionCC())) {
187 std::cerr << "Could not write reflection CC to "
188 << switches.reflection_cc_name << std::endl;
189 return false;
190 }
191 }
192 }
193 return true;
194}
195
196static bool OutputDepfile(const Compiler& compiler, const Switches& switches) {
197 // --------------------------------------------------------------------------
198 /// 4. Output a depfile.
199 ///
200
201 if (!switches.depfile_path.empty()) {
202 std::string result_file;
203 switch (switches.SelectDefaultTargetPlatform()) {
213 result_file = switches.sl_file_name;
214 break;
216 result_file = switches.spirv_file_name;
217 break;
218 }
219 auto depfile_path = std::filesystem::absolute(
220 std::filesystem::current_path() / switches.depfile_path.c_str());
222 Utf8FromPath(depfile_path).c_str(),
223 *compiler.CreateDepfileContents({result_file}))) {
224 std::cerr << "Could not write depfile to " << switches.depfile_path
225 << std::endl;
226 return false;
227 }
228 }
229
230 return true;
231}
232
233bool Main(const fml::CommandLine& command_line) {
235 if (command_line.HasOption("help")) {
236 Switches::PrintHelp(std::cout);
237 return true;
238 }
239
240 Switches switches(command_line);
241 if (!switches.AreValid(std::cerr)) {
242 std::cerr << "Invalid flags specified." << std::endl;
243 Switches::PrintHelp(std::cerr);
244 return false;
245 }
246
247 if (!switches.shader_bundle.empty()) {
248 // Invoke the compiler multiple times to build a shader bundle with the
249 // given shader_bundle spec.
250 return GenerateShaderBundle(switches);
251 }
252
253 std::shared_ptr<fml::FileMapping> source_file_mapping =
255 if (!source_file_mapping) {
256 std::cerr << "Could not open input file." << std::endl;
257 return false;
258 }
259
260 if (switches.iplr && !OutputIPLR(switches, source_file_mapping)) {
261 return false;
262 }
263
264 // Create at least one compiler to output the SL file, reflection data, and a
265 // depfile.
266 // TODO(dnfield): This seems off. We should more explicitly handle how we
267 // generate reflection and depfile data for the runtime stage case.
268 // https://github.com/flutter/flutter/issues/140841
269
271
272 // Invoke the compiler and generate reflection data for a single shader.
273
274 Reflector::Options reflector_options =
276
277 Compiler compiler(source_file_mapping, options, reflector_options);
278 if (!compiler.IsValid()) {
279 std::cerr << "Compilation failed." << std::endl;
280 std::cerr << compiler.GetErrorMessages() << std::endl;
281 return false;
282 }
283
284 auto spriv_file_name = std::filesystem::absolute(
285 std::filesystem::current_path() / switches.spirv_file_name);
287 Utf8FromPath(spriv_file_name).c_str(),
288 *compiler.GetSPIRVAssembly())) {
289 std::cerr << "Could not write file to " << switches.spirv_file_name
290 << std::endl;
291 return false;
292 }
293
294 if (!switches.iplr && !OutputSLFile(compiler, switches)) {
295 return false;
296 }
297
298 if (!OutputReflectionData(compiler, switches, options)) {
299 return false;
300 }
301
302 if (!OutputDepfile(compiler, switches)) {
303 return false;
304 }
305
306 return true;
307}
308
309} // namespace compiler
310} // namespace impeller
311
312int main(int argc, char const* argv[]) {
315 ? EXIT_SUCCESS
316 : EXIT_FAILURE;
317}
const char * options
bool HasOption(std::string_view name, size_t *index=nullptr) const
Definition: command_line.cc:40
static std::unique_ptr< FileMapping > CreateReadOnly(const std::string &path)
Definition: mapping.cc:20
const Reflector * GetReflector() const
Definition: compiler.cc:498
std::string GetErrorMessages() const
Definition: compiler.cc:455
std::shared_ptr< RuntimeStageData::Shader > GetRuntimeStageShaderData() const
Definition: reflector.cc:129
std::shared_ptr< fml::Mapping > CreateMapping() const
void AddShader(const std::shared_ptr< Shader > &data)
std::shared_ptr< fml::Mapping > CreateJsonMapping() const
std::vector< TargetPlatform > PlatformsToCompile() const
A vector containing at least one valid platform.
Definition: switches.cc:292
std::string reflection_json_name
Definition: switches.h:34
std::string reflection_header_name
Definition: switches.h:35
std::shared_ptr< fml::UniqueFD > working_directory
Definition: switches.h:23
SourceOptions CreateSourceOptions(std::optional< TargetPlatform > target_platform=std::nullopt) const
Definition: switches.cc:307
std::string reflection_cc_name
Definition: switches.h:36
std::string spirv_file_name
Definition: switches.h:33
bool AreValid(std::ostream &explain) const
Definition: switches.cc:239
static void PrintHelp(std::ostream &stream)
Definition: switches.cc:41
std::string source_file_name
Definition: switches.h:25
TargetPlatform SelectDefaultTargetPlatform() const
Definition: switches.cc:299
#define FML_DCHECK(condition)
Definition: logging.h:103
int main(int argc, char const *argv[])
char ** argv
Definition: library.h:9
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
bool WriteAtomically(const fml::UniqueFD &base_directory, const char *file_name, const Mapping &mapping)
Definition: file_posix.cc:191
void InstallCrashHandler()
Definition: backtrace.cc:126
CommandLine CommandLineFromPlatformOrArgcArgv(int argc, const char *const *argv)
Definition: command_line.h:242
bool Main(const fml::CommandLine &command_line)
bool SetPermissiveAccess(const std::filesystem::path &p)
Sets the file access mode of the file at path 'p' to 0644.
Definition: utilities.cc:16
static bool OutputDepfile(const Compiler &compiler, const Switches &switches)
bool GenerateShaderBundle(Switches &switches)
Parses the JSON shader bundle configuration and invokes the compiler multiple times to produce a shad...
static Reflector::Options CreateReflectorOptions(const SourceOptions &options, const Switches &switches)
static bool OutputReflectionData(const Compiler &compiler, const Switches &switches, const SourceOptions &options)
static std::shared_ptr< RuntimeStageData::Shader > CompileSkSL(std::shared_ptr< fml::Mapping > source_file_mapping, const Switches &switches)
static bool OutputIPLR(const Switches &switches, const std::shared_ptr< fml::Mapping > &source_file_mapping)
std::string Utf8FromPath(const std::filesystem::path &path)
Converts a native format path to a utf8 string.
Definition: utilities.cc:30
bool TargetPlatformBundlesSkSL(TargetPlatform platform)
Definition: types.cc:320
bool TargetPlatformNeedsReflection(TargetPlatform platform)
Definition: types.cc:141
static bool OutputSLFile(const Compiler &compiler, const Switches &switches)
std::string InferShaderNameFromPath(std::string_view path)
Definition: utilities.cc:34
compiler
Definition: malisc.py:17