| // 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); | |
| } | |
| 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 |