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