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