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

// FLUTTER_NOLINT: https://github.com/flutter/flutter/issues/123467

#include "impeller/renderer/backend/vulkan/pipeline_cache_vk.h"

#include <sstream>

#include "flutter/fml/mapping.h"
#include "impeller/base/validation.h"

namespace impeller {

static constexpr const char* kPipelineCacheFileName =
    "flutter.impeller.vkcache";

static bool VerifyExistingCache(const fml::Mapping& mapping,
                                const CapabilitiesVK& caps) {
  return true;
}

static std::shared_ptr<fml::Mapping> DecorateCacheWithMetadata(
    std::shared_ptr<fml::Mapping> data) {
  return data;
}

static std::unique_ptr<fml::Mapping> RemoveMetadataFromCache(
    std::unique_ptr<fml::Mapping> data) {
  return data;
}

static std::unique_ptr<fml::Mapping> OpenCacheFile(
    const fml::UniqueFD& base_directory,
    const std::string& cache_file_name,
    const CapabilitiesVK& caps) {
  if (!base_directory.is_valid()) {
    return nullptr;
  }
  std::unique_ptr<fml::Mapping> mapping =
      fml::FileMapping::CreateReadOnly(base_directory, cache_file_name);
  if (!mapping) {
    return nullptr;
  }
  if (!VerifyExistingCache(*mapping, caps)) {
    return nullptr;
  }
  mapping = RemoveMetadataFromCache(std::move(mapping));
  if (!mapping) {
    return nullptr;
  }
  return mapping;
}

PipelineCacheVK::PipelineCacheVK(std::shared_ptr<const Capabilities> caps,
                                 std::shared_ptr<DeviceHolderVK> device_holder,
                                 fml::UniqueFD cache_directory)
    : caps_(std::move(caps)),
      device_holder_(device_holder),
      cache_directory_(std::move(cache_directory)) {
  if (!caps_ || !device_holder->GetDevice()) {
    return;
  }

  const auto& vk_caps = CapabilitiesVK::Cast(*caps_);

  auto existing_cache_data =
      OpenCacheFile(cache_directory_, kPipelineCacheFileName, vk_caps);

  vk::PipelineCacheCreateInfo cache_info;
  if (existing_cache_data) {
    cache_info.initialDataSize = existing_cache_data->GetSize();
    cache_info.pInitialData = existing_cache_data->GetMapping();
  }

  auto [result, existing_cache] =
      device_holder->GetDevice().createPipelineCacheUnique(cache_info);

  if (result == vk::Result::eSuccess) {
    cache_ = std::move(existing_cache);
  } else {
    // Even though we perform consistency checks because we don't trust the
    // driver, the driver may have additional information that may cause it to
    // reject the cache too.
    FML_LOG(INFO) << "Existing pipeline cache was invalid: "
                  << vk::to_string(result) << ". Starting with a fresh cache.";
    cache_info.pInitialData = nullptr;
    cache_info.initialDataSize = 0u;
    auto [result2, new_cache] =
        device_holder->GetDevice().createPipelineCacheUnique(cache_info);
    if (result2 == vk::Result::eSuccess) {
      cache_ = std::move(new_cache);
    } else {
      VALIDATION_LOG << "Could not create new pipeline cache: "
                     << vk::to_string(result2);
    }
  }

  is_valid_ = !!cache_;
}

PipelineCacheVK::~PipelineCacheVK() {
  std::shared_ptr<DeviceHolderVK> device_holder = device_holder_.lock();
  if (device_holder) {
    cache_.reset();
  } else {
    cache_.release();
  }
}

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

vk::UniquePipeline PipelineCacheVK::CreatePipeline(
    const vk::GraphicsPipelineCreateInfo& info) {
  std::shared_ptr<DeviceHolderVK> strong_device = device_holder_.lock();
  if (!strong_device) {
    return {};
  }

  auto [result, pipeline] =
      strong_device->GetDevice().createGraphicsPipelineUnique(*cache_, info);
  if (result != vk::Result::eSuccess) {
    VALIDATION_LOG << "Could not create graphics pipeline: "
                   << vk::to_string(result);
  }
  return std::move(pipeline);
}

vk::UniquePipeline PipelineCacheVK::CreatePipeline(
    const vk::ComputePipelineCreateInfo& info) {
  std::shared_ptr<DeviceHolderVK> strong_device = device_holder_.lock();
  if (!strong_device) {
    return {};
  }

  auto [result, pipeline] =
      strong_device->GetDevice().createComputePipelineUnique(*cache_, info);
  if (result != vk::Result::eSuccess) {
    VALIDATION_LOG << "Could not create compute pipeline: "
                   << vk::to_string(result);
  }
  return std::move(pipeline);
}

std::shared_ptr<fml::Mapping> PipelineCacheVK::CopyPipelineCacheData() const {
  std::shared_ptr<DeviceHolderVK> strong_device = device_holder_.lock();
  if (!strong_device) {
    return nullptr;
  }

  if (!IsValid()) {
    return nullptr;
  }
  auto [result, data] =
      strong_device->GetDevice().getPipelineCacheData(*cache_);
  if (result != vk::Result::eSuccess) {
    VALIDATION_LOG << "Could not get pipeline cache data to persist.";
    return nullptr;
  }
  auto shared_data = std::make_shared<std::vector<uint8_t>>();
  std::swap(*shared_data, data);
  return std::make_shared<fml::NonOwnedMapping>(
      shared_data->data(), shared_data->size(), [shared_data](auto, auto) {});
}

void PipelineCacheVK::PersistCacheToDisk() const {
  if (!cache_directory_.is_valid()) {
    return;
  }
  auto data = CopyPipelineCacheData();
  if (!data) {
    VALIDATION_LOG << "Could not copy pipeline cache data.";
    return;
  }
  data = DecorateCacheWithMetadata(std::move(data));
  if (!data) {
    VALIDATION_LOG
        << "Could not decorate pipeline cache with additional metadata.";
    return;
  }
  if (!fml::WriteAtomically(cache_directory_, kPipelineCacheFileName, *data)) {
    VALIDATION_LOG << "Could not persist pipeline cache to disk.";
    return;
  }
}

const CapabilitiesVK* PipelineCacheVK::GetCapabilities() const {
  return CapabilitiesVK::Cast(caps_.get());
}

}  // namespace impeller
