// 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.h"

#include <filesystem>
#include <memory>
#include <sstream>

#include "flutter/fml/paths.h"
#include "impeller/base/allocation.h"
#include "impeller/compiler/compiler_backend.h"
#include "impeller/compiler/includer.h"
#include "impeller/compiler/logger.h"

namespace impeller {
namespace compiler {

static CompilerBackend CreateMSLCompiler(const spirv_cross::ParsedIR& ir,
                                         const SourceOptions& source_options) {
  auto sl_compiler = std::make_shared<spirv_cross::CompilerMSL>(ir);
  spirv_cross::CompilerMSL::Options sl_options;
  sl_options.platform =
      TargetPlatformToMSLPlatform(source_options.target_platform);
  // If this version specification changes, the GN rules that process the
  // Metal to AIR must be updated as well.
  sl_options.msl_version =
      spirv_cross::CompilerMSL::Options::make_msl_version(1, 2);
  sl_compiler->set_msl_options(sl_options);
  return CompilerBackend(sl_compiler);
}

static CompilerBackend CreateGLSLCompiler(const spirv_cross::ParsedIR& ir,
                                          const SourceOptions& source_options) {
  auto gl_compiler = std::make_shared<spirv_cross::CompilerGLSL>(ir);
  spirv_cross::CompilerGLSL::Options sl_options;
  sl_options.force_zero_initialized_variables = true;
  sl_options.vertex.fixup_clipspace = true;
  if (source_options.target_platform == TargetPlatform::kOpenGLES) {
    sl_options.version = 100;
    sl_options.es = true;
  } else {
    sl_options.version = 120;
    sl_options.es = false;
  }
  gl_compiler->set_common_options(sl_options);
  return CompilerBackend(gl_compiler);
}

static CompilerBackend CreateSkSLCompiler(const spirv_cross::ParsedIR& ir,
                                          const SourceOptions& source_options) {
  auto sksl_compiler = std::make_shared<CompilerSkSL>(ir);
  return CompilerBackend(sksl_compiler);
}

static bool EntryPointMustBeNamedMain(TargetPlatform platform) {
  switch (platform) {
    case TargetPlatform::kUnknown:
      FML_UNREACHABLE();
    case TargetPlatform::kMetalDesktop:
    case TargetPlatform::kMetalIOS:
    case TargetPlatform::kVulkan:
    case TargetPlatform::kRuntimeStageMetal:
      return false;
    case TargetPlatform::kFlutterSPIRV:
    case TargetPlatform::kSkSL:
    case TargetPlatform::kOpenGLES:
    case TargetPlatform::kOpenGLDesktop:
    case TargetPlatform::kRuntimeStageGLES:
      return true;
  }
  FML_UNREACHABLE();
}

static CompilerBackend CreateCompiler(const spirv_cross::ParsedIR& ir,
                                      const SourceOptions& source_options) {
  CompilerBackend compiler;
  switch (source_options.target_platform) {
    case TargetPlatform::kMetalDesktop:
    case TargetPlatform::kMetalIOS:
    case TargetPlatform::kRuntimeStageMetal:
    case TargetPlatform::kRuntimeStageGLES:
    case TargetPlatform::kVulkan:
      compiler = CreateMSLCompiler(ir, source_options);
      break;
    case TargetPlatform::kUnknown:
    case TargetPlatform::kFlutterSPIRV:
    case TargetPlatform::kOpenGLES:
    case TargetPlatform::kOpenGLDesktop:
      compiler = CreateGLSLCompiler(ir, source_options);
      break;
    case TargetPlatform::kSkSL:
      compiler = CreateSkSLCompiler(ir, source_options);
  }
  if (!compiler) {
    return {};
  }
  auto* backend = compiler.GetCompiler();
  if (!EntryPointMustBeNamedMain(source_options.target_platform)) {
    backend->rename_entry_point("main", source_options.entry_point_name,
                                ToExecutionModel(source_options.type));
  }
  return compiler;
}

Compiler::Compiler(const fml::Mapping& source_mapping,
                   SourceOptions source_options,
                   Reflector::Options reflector_options)
    : options_(source_options) {
  if (source_mapping.GetMapping() == nullptr) {
    COMPILER_ERROR
        << "Could not read shader source or shader source was empty.";
    return;
  }

  if (source_options.target_platform == TargetPlatform::kUnknown) {
    COMPILER_ERROR << "Target platform not specified.";
    return;
  }

  auto shader_kind = ToShaderCShaderKind(source_options.type);

  if (shader_kind == shaderc_shader_kind::shaderc_glsl_infer_from_source) {
    COMPILER_ERROR << "Could not figure out shader stage.";
    return;
  }

  shaderc::CompileOptions spirv_options;

  // Make sure reflection is as effective as possible. The generated shaders
  // will be processed later by backend specific compilers. So optimizations
  // here are irrelevant and get in the way of generating reflection code.
  spirv_options.SetGenerateDebugInfo();

  // Expects GLSL 4.60 (Core Profile).
  // https://www.khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.4.60.pdf
  spirv_options.SetSourceLanguage(
      shaderc_source_language::shaderc_source_language_glsl);
  spirv_options.SetForcedVersionProfile(460,
                                        shaderc_profile::shaderc_profile_core);
  switch (source_options.target_platform) {
    case TargetPlatform::kMetalDesktop:
    case TargetPlatform::kMetalIOS:
    case TargetPlatform::kOpenGLES:
    case TargetPlatform::kOpenGLDesktop:
      spirv_options.SetOptimizationLevel(
          shaderc_optimization_level::shaderc_optimization_level_performance);
      spirv_options.SetTargetEnvironment(
          shaderc_target_env::shaderc_target_env_vulkan,
          shaderc_env_version::shaderc_env_version_vulkan_1_1);
      spirv_options.SetTargetSpirv(
          shaderc_spirv_version::shaderc_spirv_version_1_3);
      break;
    case TargetPlatform::kVulkan:
      spirv_options.SetOptimizationLevel(
          shaderc_optimization_level::shaderc_optimization_level_performance);
      spirv_options.SetTargetEnvironment(
          shaderc_target_env::shaderc_target_env_vulkan,
          shaderc_env_version::shaderc_env_version_vulkan_1_0);
      spirv_options.SetTargetSpirv(
          shaderc_spirv_version::shaderc_spirv_version_1_0);
      break;
    case TargetPlatform::kRuntimeStageMetal:
    case TargetPlatform::kRuntimeStageGLES:
      spirv_options.SetOptimizationLevel(
          shaderc_optimization_level::shaderc_optimization_level_performance);
      spirv_options.SetTargetEnvironment(
          shaderc_target_env::shaderc_target_env_opengl,
          shaderc_env_version::shaderc_env_version_opengl_4_5);
      spirv_options.SetTargetSpirv(
          shaderc_spirv_version::shaderc_spirv_version_1_0);
      break;
    case TargetPlatform::kFlutterSPIRV:
      // With any optimization level above 'zero' enabled, shaderc will emit
      // ops that are not supported by the Engine's SPIR-V -> SkSL transpiler.
      // In particular, with 'shaderc_optimization_level_size' enabled, it will
      // generate OpPhi (opcode 245) for test 246_OpLoopMerge.frag instead of
      // the OpLoopMerge op expected by that test.
      // See: https://github.com/flutter/flutter/issues/105396.
      spirv_options.SetOptimizationLevel(
          shaderc_optimization_level::shaderc_optimization_level_zero);
      spirv_options.SetTargetEnvironment(
          shaderc_target_env::shaderc_target_env_opengl,
          shaderc_env_version::shaderc_env_version_opengl_4_5);
      spirv_options.SetTargetSpirv(
          shaderc_spirv_version::shaderc_spirv_version_1_0);
      break;
    case TargetPlatform::kSkSL:
      // When any optimization level above 'zero' is enabled, the phi merges at
      // loop continue blocks are rendered using syntax that is supported in
      // GLSL, but not in SkSL.
      // https://bugs.chromium.org/p/skia/issues/detail?id=13518.
      spirv_options.SetOptimizationLevel(
          shaderc_optimization_level::shaderc_optimization_level_zero);
      spirv_options.SetTargetEnvironment(
          shaderc_target_env::shaderc_target_env_opengl,
          shaderc_env_version::shaderc_env_version_opengl_4_5);
      spirv_options.SetTargetSpirv(
          shaderc_spirv_version::shaderc_spirv_version_1_0);
      break;
    case TargetPlatform::kUnknown:
      COMPILER_ERROR << "Target platform invalid.";
      return;
  }

  // Implicit definition that indicates that this compilation is for the device
  // (instead of the host).
  spirv_options.AddMacroDefinition("IMPELLER_DEVICE");
  for (const auto& define : source_options.defines) {
    spirv_options.AddMacroDefinition(define);
  }

  spirv_options.SetAutoBindUniforms(true);
  spirv_options.SetAutoMapLocations(true);

  std::vector<std::string> included_file_names;
  spirv_options.SetIncluder(std::make_unique<Includer>(
      options_.working_directory, options_.include_dirs,
      [&included_file_names](auto included_name) {
        included_file_names.emplace_back(std::move(included_name));
      }));

  shaderc::Compiler spv_compiler;
  if (!spv_compiler.IsValid()) {
    COMPILER_ERROR << "Could not initialize the GLSL to SPIRV compiler.";
    return;
  }

  // SPIRV Generation.
  spv_result_ = std::make_shared<shaderc::SpvCompilationResult>(
      spv_compiler.CompileGlslToSpv(
          reinterpret_cast<const char*>(
              source_mapping.GetMapping()),         // source_text
          source_mapping.GetSize(),                 // source_text_size
          shader_kind,                              // shader_kind
          source_options.file_name.c_str(),         // input_file_name
          source_options.entry_point_name.c_str(),  // entry_point_name
          spirv_options                             // options
          ));
  if (spv_result_->GetCompilationStatus() !=
      shaderc_compilation_status::shaderc_compilation_status_success) {
    COMPILER_ERROR << "GLSL to SPIRV failed; "
                   << ShaderCErrorToString(spv_result_->GetCompilationStatus())
                   << ". " << spv_result_->GetNumErrors() << " error(s) and "
                   << spv_result_->GetNumWarnings() << " warning(s).";
    if (spv_result_->GetNumErrors() > 0 || spv_result_->GetNumWarnings() > 0) {
      COMPILER_ERROR_NO_PREFIX << spv_result_->GetErrorMessage();
    }
    return;
  } else {
    included_file_names_ = std::move(included_file_names);
  }

  if (!TargetPlatformNeedsSL(source_options.target_platform)) {
    is_valid_ = true;
    return;
  }

  // SL Generation.
  spirv_cross::Parser parser(spv_result_->cbegin(),
                             spv_result_->cend() - spv_result_->cbegin());
  // The parser and compiler must be run separately because the parser contains
  // meta information (like type member names) that are useful for reflection.
  parser.parse();

  const auto parsed_ir =
      std::make_shared<spirv_cross::ParsedIR>(parser.get_parsed_ir());

  auto sl_compiler = CreateCompiler(*parsed_ir, options_);

  if (!sl_compiler) {
    COMPILER_ERROR << "Could not create compiler for target platform.";
    return;
  }

  // We need to invoke the compiler even if we don't use the SL mapping later
  // for Vulkan. The reflector needs information that is only valid after a
  // successful compilation call.
  auto sl_compilation_result =
      CreateMappingWithString(sl_compiler.GetCompiler()->compile());

  // If the target is Vulkan, our shading language is SPIRV which we already
  // have. If it isn't, we need to invoke the appropriate compiler to compile
  // the SPIRV to the target SL.
  sl_mapping_ = source_options.target_platform == TargetPlatform::kVulkan
                    ? GetSPIRVAssembly()
                    : sl_compilation_result;

  if (!sl_mapping_) {
    COMPILER_ERROR << "Could not generate SL from SPIRV";
    return;
  }

  reflector_ = std::make_unique<Reflector>(std::move(reflector_options),  //
                                           parsed_ir,                     //
                                           GetSLShaderSource(),           //
                                           sl_compiler                    //
  );

  if (!reflector_->IsValid()) {
    COMPILER_ERROR << "Could not complete reflection on generated shader.";
    return;
  }

  is_valid_ = true;
}

Compiler::~Compiler() = default;

std::unique_ptr<fml::Mapping> Compiler::GetSPIRVAssembly() const {
  if (!spv_result_) {
    return nullptr;
  }
  const auto data_length =
      (spv_result_->cend() - spv_result_->cbegin()) *
      sizeof(decltype(spv_result_)::element_type::element_type);

  return std::make_unique<fml::NonOwnedMapping>(
      reinterpret_cast<const uint8_t*>(spv_result_->cbegin()), data_length,
      [result = spv_result_](auto, auto) mutable { result.reset(); });
}

std::shared_ptr<fml::Mapping> Compiler::GetSLShaderSource() const {
  return sl_mapping_;
}

bool Compiler::IsValid() const {
  return is_valid_;
}

std::string Compiler::GetSourcePrefix() const {
  std::stringstream stream;
  stream << options_.file_name << ": ";
  return stream.str();
}

std::string Compiler::GetErrorMessages() const {
  return error_stream_.str();
}

const std::vector<std::string>& Compiler::GetIncludedFileNames() const {
  return included_file_names_;
}

static std::string JoinStrings(std::vector<std::string> items,
                               std::string separator) {
  std::stringstream stream;
  for (size_t i = 0, count = items.size(); i < count; i++) {
    const auto is_last = (i == count - 1);

    stream << items[i];
    if (!is_last) {
      stream << separator;
    }
  }
  return stream.str();
}

std::string Compiler::GetDependencyNames(std::string separator) const {
  std::vector<std::string> dependencies = included_file_names_;
  dependencies.push_back(options_.file_name);
  return JoinStrings(dependencies, separator);
}

std::unique_ptr<fml::Mapping> Compiler::CreateDepfileContents(
    std::initializer_list<std::string> targets_names) const {
  const auto targets = JoinStrings(targets_names, " ");
  const auto dependencies = GetDependencyNames(" ");

  std::stringstream stream;
  stream << targets << ": " << dependencies << "\n";

  auto contents = std::make_shared<std::string>(stream.str());
  return std::make_unique<fml::NonOwnedMapping>(
      reinterpret_cast<const uint8_t*>(contents->data()), contents->size(),
      [contents](auto, auto) {});
}

const Reflector* Compiler::GetReflector() const {
  return reflector_.get();
}

}  // namespace compiler
}  // namespace impeller
