// 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 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 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 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( 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