// 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/renderer/backend/vulkan/shader_library_vk.h"

#include "flutter/fml/logging.h"
#include "flutter/fml/trace_event.h"
#include "impeller/blobcat/blob_library.h"
#include "impeller/renderer/backend/vulkan/context_vk.h"
#include "impeller/renderer/backend/vulkan/shader_function_vk.h"

namespace impeller {

static ShaderStage ToShaderStage(BlobShaderType type) {
  switch (type) {
    case BlobShaderType::kVertex:
      return ShaderStage::kVertex;
    case BlobShaderType::kFragment:
      return ShaderStage::kFragment;
    case BlobShaderType::kCompute:
      return ShaderStage::kCompute;
  }
  FML_UNREACHABLE();
}

static std::string VKShaderNameToShaderKeyName(const std::string& name,
                                               ShaderStage stage) {
  std::stringstream stream;
  stream << name;
  switch (stage) {
    case ShaderStage::kUnknown:
      stream << "_unknown_";
      break;
    case ShaderStage::kVertex:
      stream << "_vertex_";
      break;
    case ShaderStage::kFragment:
      stream << "_fragment_";
      break;
    case ShaderStage::kTessellationControl:
      stream << "_tessellation_control_";
      break;
    case ShaderStage::kTessellationEvaluation:
      stream << "_tessellation_evaluation_";
      break;
    case ShaderStage::kCompute:
      stream << "_compute_";
      break;
  }
  stream << "main";
  return stream.str();
}

ShaderLibraryVK::ShaderLibraryVK(
    const vk::Device& device,
    const std::vector<std::shared_ptr<fml::Mapping>>& shader_libraries_data)
    : device_(device) {
  TRACE_EVENT0("impeller", "CreateShaderLibrary");
  bool success = true;
  auto iterator = [&](auto type,         //
                      const auto& name,  //
                      const auto& code   //
                      ) -> bool {
    if (!RegisterFunction(name, ToShaderStage(type), code)) {
      success = false;
      return false;
    }
    return true;
  };
  for (const auto& library_data : shader_libraries_data) {
    auto blob_library = BlobLibrary{library_data};
    if (!blob_library.IsValid()) {
      VALIDATION_LOG << "Could not construct shader blob library.";
      return;
    }
    blob_library.IterateAllBlobs(iterator);
  }

  if (!success) {
    VALIDATION_LOG << "Could not create shader modules for all shader blobs.";
    return;
  }
  is_valid_ = true;
}

ShaderLibraryVK::~ShaderLibraryVK() = default;

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

// |ShaderLibrary|
std::shared_ptr<const ShaderFunction> ShaderLibraryVK::GetFunction(
    std::string_view name,
    ShaderStage stage) {
  ReaderLock lock(functions_mutex_);

  const auto key = ShaderKey{{name.data(), name.size()}, stage};
  auto found = functions_.find(key);
  if (found != functions_.end()) {
    return found->second;
  }
  return nullptr;
}

// |ShaderLibrary|
void ShaderLibraryVK::RegisterFunction(std::string name,
                                       ShaderStage stage,
                                       std::shared_ptr<fml::Mapping> code,
                                       RegistrationCallback callback) {
  const auto result = RegisterFunction(name, stage, code);
  if (callback) {
    callback(result);
  }
}

static bool IsMappingSPIRV(const fml::Mapping& mapping) {
  // https://registry.khronos.org/SPIR-V/specs/1.0/SPIRV.html#Magic
  const uint32_t kSPIRVMagic = 0x07230203;
  if (mapping.GetSize() < sizeof(kSPIRVMagic)) {
    return false;
  }
  uint32_t magic = 0u;
  ::memcpy(&magic, mapping.GetMapping(), sizeof(magic));
  return magic == kSPIRVMagic;
}

bool ShaderLibraryVK::RegisterFunction(
    const std::string& name,
    ShaderStage stage,
    const std::shared_ptr<fml::Mapping>& code) {
  if (!code) {
    return false;
  }

  if (!IsMappingSPIRV(*code)) {
    VALIDATION_LOG << "Shader is not valid SPIRV.";
    return false;
  }

  vk::ShaderModuleCreateInfo shader_module_info;

  shader_module_info.setPCode(
      reinterpret_cast<const uint32_t*>(code->GetMapping()));
  shader_module_info.setCodeSize(code->GetSize());

  auto module = device_.createShaderModuleUnique(shader_module_info);

  if (module.result != vk::Result::eSuccess) {
    VALIDATION_LOG << "Could not create shader module: "
                   << vk::to_string(module.result);
    return false;
  }

  const auto key_name = VKShaderNameToShaderKeyName(name, stage);

  vk::UniqueShaderModule shader_module = std::move(module.value);
  ContextVK::SetDebugName(device_, *shader_module, "Shader " + name);

  WriterLock lock(functions_mutex_);
  functions_[ShaderKey{key_name, stage}] = std::shared_ptr<ShaderFunctionVK>(
      new ShaderFunctionVK(library_id_,              //
                           key_name,                 //
                           stage,                    //
                           std::move(shader_module)  //
                           ));

  return true;
}

// |ShaderLibrary|
void ShaderLibraryVK::UnregisterFunction(std::string name, ShaderStage stage) {
  WriterLock lock(functions_mutex_);

  const auto key = ShaderKey{name, stage};

  auto found = functions_.find(key);
  if (found != functions_.end()) {
    VALIDATION_LOG << "Library function named " << name
                   << " was not found, so it couldn't be unregistered.";
    return;
  }

  functions_.erase(found);

  return;
}

}  // namespace impeller
