Flutter Engine
 
Loading...
Searching...
No Matches
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
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(
31 std::filesystem::path{switches.reflection_header_name}.filename());
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) {
40 auto options = switches.CreateSourceOptions(TargetPlatform::kSkSL);
41
42 Reflector::Options sksl_reflector_options =
43 CreateReflectorOptions(options, switches);
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 =
81 CreateReflectorOptions(options, switches);
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
144static bool OutputReflectionData(const Compiler& compiler,
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
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()) {
214 result_file = switches.sl_file_name;
215 break;
217 result_file = switches.spirv_file_name;
218 break;
219 }
220 auto depfile_path = std::filesystem::absolute(
221 std::filesystem::current_path() / switches.depfile_path.c_str());
223 Utf8FromPath(depfile_path).c_str(),
224 *compiler.CreateDepfileContents({result_file}))) {
225 std::cerr << "Could not write depfile to " << switches.depfile_path
226 << std::endl;
227 return false;
228 }
229 }
230
231 return true;
232}
233
234bool Main(const fml::CommandLine& command_line) {
236 if (command_line.HasOption("help")) {
237 Switches::PrintHelp(std::cout);
238 return true;
239 }
240
241 Switches switches(command_line);
242 if (!switches.AreValid(std::cerr)) {
243 std::cerr << "Invalid flags specified." << std::endl;
244 Switches::PrintHelp(std::cerr);
245 return false;
246 }
247
248 if (!switches.shader_bundle.empty()) {
249 // Invoke the compiler multiple times to build a shader bundle with the
250 // given shader_bundle spec.
251 return GenerateShaderBundle(switches);
252 }
253
254 std::shared_ptr<fml::FileMapping> source_file_mapping =
256 if (!source_file_mapping) {
257 std::cerr << "Could not open input file." << std::endl;
258 return false;
259 }
260
261 if (switches.iplr && !OutputIPLR(switches, source_file_mapping)) {
262 return false;
263 }
264
265 // Create at least one compiler to output the SL file, reflection data, and a
266 // depfile.
267
268 SourceOptions options = switches.CreateSourceOptions();
269
270 // Invoke the compiler and generate reflection data for a single shader.
271
272 Reflector::Options reflector_options =
273 CreateReflectorOptions(options, switches);
274
275 Compiler compiler(source_file_mapping, options, reflector_options);
276 if (!compiler.IsValid()) {
277 std::cerr << "Compilation failed." << std::endl;
278 std::cerr << compiler.GetErrorMessages() << std::endl;
279 return false;
280 }
281
282 auto spriv_file_name = std::filesystem::absolute(
283 std::filesystem::current_path() / switches.spirv_file_name);
285 Utf8FromPath(spriv_file_name).c_str(),
286 *compiler.GetSPIRVAssembly())) {
287 std::cerr << "Could not write file to " << switches.spirv_file_name
288 << std::endl;
289 return false;
290 }
291
292 if (!switches.iplr && !OutputSLFile(compiler, switches)) {
293 return false;
294 }
295
296 if (!OutputReflectionData(compiler, switches, options)) {
297 return false;
298 }
299
300 if (!OutputDepfile(compiler, switches)) {
301 return false;
302 }
303
304 return true;
305}
306
307} // namespace compiler
308} // namespace impeller
309
310int main(int argc, char const* argv[]) {
313 ? EXIT_SUCCESS
314 : EXIT_FAILURE;
315}
bool HasOption(std::string_view name, size_t *index=nullptr) const
static std::unique_ptr< FileMapping > CreateReadOnly(const std::string &path)
Definition mapping.cc:20
std::shared_ptr< fml::Mapping > GetSPIRVAssembly() const
Definition compiler.cc:486
const Reflector * GetReflector() const
Definition compiler.cc:547
std::unique_ptr< fml::Mapping > CreateDepfileContents(std::initializer_list< std::string > targets) const
Definition compiler.cc:532
std::shared_ptr< fml::Mapping > GetSLShaderSource() const
Definition compiler.cc:490
std::string GetErrorMessages() const
Definition compiler.cc:504
std::shared_ptr< fml::Mapping > GetReflectionJSON() const
Definition reflector.cc:109
std::shared_ptr< fml::Mapping > GetReflectionCC() const
Definition reflector.cc:126
std::shared_ptr< RuntimeStageData::Shader > GetRuntimeStageShaderData() const
Definition reflector.cc:130
std::shared_ptr< fml::Mapping > GetReflectionHeader() const
Definition reflector.cc:122
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:293
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:308
std::string reflection_cc_name
Definition switches.h:36
bool AreValid(std::ostream &explain) const
Definition switches.cc:240
static void PrintHelp(std::ostream &stream)
Definition switches.cc:42
TargetPlatform SelectDefaultTargetPlatform() const
Definition switches.cc:300
#define FML_DCHECK(condition)
Definition logging.h:122
int main(int argc, char const *argv[])
char ** argv
Definition library.h:9
bool WriteAtomically(const fml::UniqueFD &base_directory, const char *file_name, const Mapping &mapping)
void InstallCrashHandler()
Definition backtrace.cc:126
CommandLine CommandLineFromPlatformOrArgcArgv(int argc, const char *const *argv)
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:328
bool TargetPlatformNeedsReflection(TargetPlatform platform)
Definition types.cc:143
static bool OutputSLFile(const Compiler &compiler, const Switches &switches)
std::string InferShaderNameFromPath(std::string_view path)
Definition utilities.cc:34