blob: b19a84176cf36745b6ba9576dfd807ae5dca2344 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "impeller/compiler/compiler_test.h"
#include <algorithm>
namespace impeller {
namespace compiler {
namespace testing {
static fml::UniqueFD CreateIntermediatesDirectory() {
auto test_name = flutter::testing::GetCurrentTestName();
std::replace(test_name.begin(), test_name.end(), '/', '_');
std::replace(test_name.begin(), test_name.end(), '.', '_');
return fml::OpenDirectory(flutter::testing::OpenFixturesDirectory(),
test_name.c_str(),
true, // create if necessary
fml::FilePermission::kReadWrite);
}
CompilerTest::CompilerTest()
: intermediates_directory_(CreateIntermediatesDirectory()) {
FML_CHECK(intermediates_directory_.is_valid());
}
CompilerTest::~CompilerTest() = default;
static std::string ReflectionHeaderName(const char* fixture_name) {
std::stringstream stream;
stream << fixture_name << ".h";
return stream.str();
}
static std::string ReflectionCCName(const char* fixture_name) {
std::stringstream stream;
stream << fixture_name << ".cc";
return stream.str();
}
static std::string ReflectionJSONName(const char* fixture_name) {
std::stringstream stream;
stream << fixture_name << ".json";
return stream.str();
}
static std::string SPIRVFileName(const char* fixture_name) {
std::stringstream stream;
stream << fixture_name << ".spv";
return stream.str();
}
static std::string SLFileName(const char* fixture_name,
TargetPlatform platform) {
std::stringstream stream;
stream << fixture_name << "." << TargetPlatformSLExtension(platform);
return stream.str();
}
std::unique_ptr<fml::FileMapping> CompilerTest::GetReflectionJson(
const char* fixture_name) const {
auto filename = ReflectionJSONName(fixture_name);
auto fd = fml::OpenFileReadOnly(intermediates_directory_, filename.c_str());
return fml::FileMapping::CreateReadOnly(fd);
}
std::unique_ptr<fml::FileMapping> CompilerTest::GetShaderFile(
const char* fixture_name,
TargetPlatform platform) const {
auto filename = SLFileName(fixture_name, platform);
auto fd = fml::OpenFileReadOnly(intermediates_directory_, filename.c_str());
return fml::FileMapping::CreateReadOnly(fd);
}
bool CompilerTest::CanCompileAndReflect(const char* fixture_name,
SourceType source_type,
SourceLanguage source_language,
const char* entry_point_name) const {
std::shared_ptr<fml::Mapping> fixture =
flutter::testing::OpenFixtureAsMapping(fixture_name);
if (!fixture || !fixture->GetMapping()) {
VALIDATION_LOG << "Could not find shader in fixtures: " << fixture_name;
return false;
}
SourceOptions source_options(fixture_name, source_type);
source_options.target_platform = GetParam();
source_options.source_language = source_language;
source_options.working_directory = std::make_shared<fml::UniqueFD>(
flutter::testing::OpenFixturesDirectory());
source_options.entry_point_name = EntryPointFunctionNameFromSourceName(
fixture_name, SourceTypeFromFileName(fixture_name), source_language,
entry_point_name);
Reflector::Options reflector_options;
reflector_options.header_file_name = ReflectionHeaderName(fixture_name);
reflector_options.shader_name = "shader_name";
Compiler compiler(fixture, source_options, reflector_options);
if (!compiler.IsValid()) {
VALIDATION_LOG << "Compilation failed: " << compiler.GetErrorMessages();
return false;
}
auto spirv_assembly = compiler.GetSPIRVAssembly();
if (!spirv_assembly) {
VALIDATION_LOG << "No spirv was generated.";
return false;
}
if (!fml::WriteAtomically(intermediates_directory_,
SPIRVFileName(fixture_name).c_str(),
*spirv_assembly)) {
VALIDATION_LOG << "Could not write SPIRV intermediates.";
return false;
}
auto sl_source = compiler.GetSLShaderSource();
if (!sl_source) {
VALIDATION_LOG << "No SL source was generated.";
return false;
}
if (!fml::WriteAtomically(intermediates_directory_,
SLFileName(fixture_name, GetParam()).c_str(),
*sl_source)) {
VALIDATION_LOG << "Could not write SL intermediates.";
return false;
}
if (TargetPlatformNeedsReflection(GetParam())) {
auto reflector = compiler.GetReflector();
if (!reflector) {
VALIDATION_LOG
<< "No reflector was found for target platform SL compiler.";
return false;
}
auto reflection_json = reflector->GetReflectionJSON();
auto reflection_header = reflector->GetReflectionHeader();
auto reflection_source = reflector->GetReflectionCC();
if (!reflection_json) {
VALIDATION_LOG << "Reflection JSON was not found.";
return false;
}
if (!reflection_header) {
VALIDATION_LOG << "Reflection header was not found.";
return false;
}
if (!reflection_source) {
VALIDATION_LOG << "Reflection source was not found.";
return false;
}
if (!fml::WriteAtomically(intermediates_directory_,
ReflectionHeaderName(fixture_name).c_str(),
*reflection_header)) {
VALIDATION_LOG << "Could not write reflection header intermediates.";
return false;
}
if (!fml::WriteAtomically(intermediates_directory_,
ReflectionCCName(fixture_name).c_str(),
*reflection_source)) {
VALIDATION_LOG << "Could not write reflection CC intermediates.";
return false;
}
if (!fml::WriteAtomically(intermediates_directory_,
ReflectionJSONName(fixture_name).c_str(),
*reflection_json)) {
VALIDATION_LOG << "Could not write reflection json intermediates.";
return false;
}
}
return true;
}
} // namespace testing
} // namespace compiler
} // namespace impeller