Flutter Impeller
compiler_test.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 
6 #include "flutter/fml/paths.h"
7 #include "flutter/fml/process.h"
8 
9 #include <algorithm>
10 #include <filesystem>
11 
12 namespace impeller {
13 namespace compiler {
14 namespace testing {
15 
16 static std::string GetIntermediatesPath() {
17  auto test_name = flutter::testing::GetCurrentTestName();
18  std::replace(test_name.begin(), test_name.end(), '/', '_');
19  std::replace(test_name.begin(), test_name.end(), '.', '_');
20  std::stringstream dir_name;
21  dir_name << test_name << "_" << std::to_string(fml::GetCurrentProcId());
22  return fml::paths::JoinPaths(
23  {flutter::testing::GetFixturesPath(), dir_name.str()});
24 }
25 
27  intermediates_directory_ =
28  fml::OpenDirectory(intermediates_path_.c_str(),
29  true, // create if necessary
30  fml::FilePermission::kReadWrite);
31  FML_CHECK(intermediates_directory_.is_valid());
32 }
33 
35  intermediates_directory_.reset();
36 
37  std::filesystem::remove_all(std::filesystem::path(intermediates_path_));
38 }
39 
40 static std::string ReflectionHeaderName(const char* fixture_name) {
41  std::stringstream stream;
42  stream << fixture_name << ".h";
43  return stream.str();
44 }
45 
46 static std::string ReflectionCCName(const char* fixture_name) {
47  std::stringstream stream;
48  stream << fixture_name << ".cc";
49  return stream.str();
50 }
51 
52 static std::string ReflectionJSONName(const char* fixture_name) {
53  std::stringstream stream;
54  stream << fixture_name << ".json";
55  return stream.str();
56 }
57 
58 static std::string SPIRVFileName(const char* fixture_name) {
59  std::stringstream stream;
60  stream << fixture_name << ".spv";
61  return stream.str();
62 }
63 
64 static std::string SLFileName(const char* fixture_name,
65  TargetPlatform platform) {
66  std::stringstream stream;
67  stream << fixture_name << "." << TargetPlatformSLExtension(platform);
68  return stream.str();
69 }
70 
71 std::unique_ptr<fml::FileMapping> CompilerTest::GetReflectionJson(
72  const char* fixture_name) const {
73  auto filename = ReflectionJSONName(fixture_name);
74  auto fd = fml::OpenFileReadOnly(intermediates_directory_, filename.c_str());
75  return fml::FileMapping::CreateReadOnly(fd);
76 }
77 
78 std::unique_ptr<fml::FileMapping> CompilerTest::GetShaderFile(
79  const char* fixture_name,
80  TargetPlatform platform) const {
81  auto filename = SLFileName(fixture_name, platform);
82  auto fd = fml::OpenFileReadOnly(intermediates_directory_, filename.c_str());
83  return fml::FileMapping::CreateReadOnly(fd);
84 }
85 
86 bool CompilerTest::CanCompileAndReflect(const char* fixture_name,
87  SourceType source_type,
88  SourceLanguage source_language,
89  const char* entry_point_name) const {
90  std::shared_ptr<fml::Mapping> fixture =
91  flutter::testing::OpenFixtureAsMapping(fixture_name);
92  if (!fixture || !fixture->GetMapping()) {
93  VALIDATION_LOG << "Could not find shader in fixtures: " << fixture_name;
94  return false;
95  }
96 
97  SourceOptions source_options(fixture_name, source_type);
98  source_options.target_platform = GetParam();
99  source_options.source_language = source_language;
100  source_options.working_directory = std::make_shared<fml::UniqueFD>(
101  flutter::testing::OpenFixturesDirectory());
103  fixture_name, SourceTypeFromFileName(fixture_name), source_language,
104  entry_point_name);
105 
106  Reflector::Options reflector_options;
107  reflector_options.header_file_name = ReflectionHeaderName(fixture_name);
108  reflector_options.shader_name = "shader_name";
109 
110  Compiler compiler(fixture, source_options, reflector_options);
111  if (!compiler.IsValid()) {
112  VALIDATION_LOG << "Compilation failed: " << compiler.GetErrorMessages();
113  return false;
114  }
115 
116  auto spirv_assembly = compiler.GetSPIRVAssembly();
117  if (!spirv_assembly) {
118  VALIDATION_LOG << "No spirv was generated.";
119  return false;
120  }
121 
122  if (!fml::WriteAtomically(intermediates_directory_,
123  SPIRVFileName(fixture_name).c_str(),
124  *spirv_assembly)) {
125  VALIDATION_LOG << "Could not write SPIRV intermediates.";
126  return false;
127  }
128 
129  auto sl_source = compiler.GetSLShaderSource();
130  if (!sl_source) {
131  VALIDATION_LOG << "No SL source was generated.";
132  return false;
133  }
134 
135  if (!fml::WriteAtomically(intermediates_directory_,
136  SLFileName(fixture_name, GetParam()).c_str(),
137  *sl_source)) {
138  VALIDATION_LOG << "Could not write SL intermediates.";
139  return false;
140  }
141 
142  if (TargetPlatformNeedsReflection(GetParam())) {
143  auto reflector = compiler.GetReflector();
144  if (!reflector) {
146  << "No reflector was found for target platform SL compiler.";
147  return false;
148  }
149 
150  auto reflection_json = reflector->GetReflectionJSON();
151  auto reflection_header = reflector->GetReflectionHeader();
152  auto reflection_source = reflector->GetReflectionCC();
153 
154  if (!reflection_json) {
155  VALIDATION_LOG << "Reflection JSON was not found.";
156  return false;
157  }
158 
159  if (!reflection_header) {
160  VALIDATION_LOG << "Reflection header was not found.";
161  return false;
162  }
163 
164  if (!reflection_source) {
165  VALIDATION_LOG << "Reflection source was not found.";
166  return false;
167  }
168 
169  if (!fml::WriteAtomically(intermediates_directory_,
170  ReflectionHeaderName(fixture_name).c_str(),
171  *reflection_header)) {
172  VALIDATION_LOG << "Could not write reflection header intermediates.";
173  return false;
174  }
175 
176  if (!fml::WriteAtomically(intermediates_directory_,
177  ReflectionCCName(fixture_name).c_str(),
178  *reflection_source)) {
179  VALIDATION_LOG << "Could not write reflection CC intermediates.";
180  return false;
181  }
182 
183  if (!fml::WriteAtomically(intermediates_directory_,
184  ReflectionJSONName(fixture_name).c_str(),
185  *reflection_json)) {
186  VALIDATION_LOG << "Could not write reflection json intermediates.";
187  return false;
188  }
189  }
190  return true;
191 }
192 
193 } // namespace testing
194 } // namespace compiler
195 } // namespace impeller
std::shared_ptr< fml::Mapping > GetSPIRVAssembly() const
Definition: compiler.cc:486
const Reflector * GetReflector() const
Definition: compiler.cc:547
std::shared_ptr< fml::Mapping > GetSLShaderSource() const
Definition: compiler.cc:490
std::string GetErrorMessages() const
Definition: compiler.cc:504
bool CanCompileAndReflect(const char *fixture_name, SourceType source_type=SourceType::kUnknown, SourceLanguage source_language=SourceLanguage::kGLSL, const char *entry_point_name="main") const
std::unique_ptr< fml::FileMapping > GetReflectionJson(const char *fixture_name) const
std::unique_ptr< fml::FileMapping > GetShaderFile(const char *fixture_name, TargetPlatform platform) const
static std::string ReflectionCCName(const char *fixture_name)
static std::string ReflectionJSONName(const char *fixture_name)
static std::string GetIntermediatesPath()
static std::string ReflectionHeaderName(const char *fixture_name)
static std::string SLFileName(const char *fixture_name, TargetPlatform platform)
static std::string SPIRVFileName(const char *fixture_name)
std::string TargetPlatformSLExtension(TargetPlatform platform)
Definition: types.cc:250
SourceType SourceTypeFromFileName(const std::string &file_name)
Definition: types.cc:30
std::string EntryPointFunctionNameFromSourceName(const std::string &file_name, SourceType type, SourceLanguage source_language, const std::string &entry_point_name)
Definition: types.cc:113
bool TargetPlatformNeedsReflection(TargetPlatform platform)
Definition: types.cc:143
std::shared_ptr< fml::UniqueFD > working_directory
#define VALIDATION_LOG
Definition: validation.h:91