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

#include <memory>
#include <optional>
#include <utility>

#include "impeller/renderer/backend/vulkan/context_vk.h"
#include "impeller/renderer/backend/vulkan/resource_manager_vk.h"

#include "impeller/renderer/backend/vulkan/vk.h"  // IWYU pragma: keep.
#include "vulkan/vulkan_handles.hpp"
#include "vulkan/vulkan_structs.hpp"

namespace impeller {

// Holds the command pool in a background thread, recyling it when not in use.
class BackgroundCommandPoolVK final {
 public:
  BackgroundCommandPoolVK(BackgroundCommandPoolVK&&) = default;

  // The recycler also recycles command buffers that were never used, up to a
  // limit of 16 per frame. This number was somewhat arbitrarily chosen.
  static constexpr size_t kUnusedCommandBufferLimit = 16u;

  explicit BackgroundCommandPoolVK(
      vk::UniqueCommandPool&& pool,
      std::vector<vk::UniqueCommandBuffer>&& buffers,
      size_t unused_count,
      std::weak_ptr<CommandPoolRecyclerVK> recycler)
      : pool_(std::move(pool)),
        buffers_(std::move(buffers)),
        unused_count_(unused_count),
        recycler_(std::move(recycler)) {}

  ~BackgroundCommandPoolVK() {
    auto const recycler = recycler_.lock();

    // Not only does this prevent recycling when the context is being destroyed,
    // but it also prevents the destructor from effectively being called twice;
    // once for the original BackgroundCommandPoolVK() and once for the moved
    // BackgroundCommandPoolVK().
    if (!recycler) {
      return;
    }
    // If there are many unused command buffers, release some of them.
    if (unused_count_ > kUnusedCommandBufferLimit) {
      for (auto i = 0u; i < unused_count_; i++) {
        buffers_.pop_back();
      }
    }

    recycler->Reclaim(std::move(pool_), std::move(buffers_));
  }

 private:
  BackgroundCommandPoolVK(const BackgroundCommandPoolVK&) = delete;

  BackgroundCommandPoolVK& operator=(const BackgroundCommandPoolVK&) = delete;

  vk::UniqueCommandPool pool_;

  // These are retained because the destructor of the C++ UniqueCommandBuffer
  // wrapper type will attempt to reset the cmd buffer, and doing so may be a
  // thread safety violation as this may happen on the fence waiter thread.
  std::vector<vk::UniqueCommandBuffer> buffers_;
  const size_t unused_count_;
  std::weak_ptr<CommandPoolRecyclerVK> recycler_;
};

CommandPoolVK::~CommandPoolVK() {
  if (!pool_) {
    return;
  }

  auto const context = context_.lock();
  if (!context) {
    return;
  }
  auto const recycler = context->GetCommandPoolRecycler();
  if (!recycler) {
    return;
  }
  // Any unused command buffers are added to the set of used command buffers.
  // both will be reset to the initial state when the pool is reset.
  size_t unused_count = unused_command_buffers_.size();
  for (auto i = 0u; i < unused_command_buffers_.size(); i++) {
    collected_buffers_.push_back(std::move(unused_command_buffers_[i]));
  }
  unused_command_buffers_.clear();

  auto reset_pool_when_dropped = BackgroundCommandPoolVK(
      std::move(pool_), std::move(collected_buffers_), unused_count, recycler);

  UniqueResourceVKT<BackgroundCommandPoolVK> pool(
      context->GetResourceManager(), std::move(reset_pool_when_dropped));
}

// TODO(matanlurey): Return a status_or<> instead of {} when we have one.
vk::UniqueCommandBuffer CommandPoolVK::CreateCommandBuffer() {
  auto const context = context_.lock();
  if (!context) {
    return {};
  }

  Lock lock(pool_mutex_);
  if (!pool_) {
    return {};
  }
  if (!unused_command_buffers_.empty()) {
    vk::UniqueCommandBuffer buffer = std::move(unused_command_buffers_.back());
    unused_command_buffers_.pop_back();
    return buffer;
  }

  auto const device = context->GetDevice();
  vk::CommandBufferAllocateInfo info;
  info.setCommandPool(pool_.get());
  info.setCommandBufferCount(1u);
  info.setLevel(vk::CommandBufferLevel::ePrimary);
  auto [result, buffers] = device.allocateCommandBuffersUnique(info);
  if (result != vk::Result::eSuccess) {
    return {};
  }
  return std::move(buffers[0]);
}

void CommandPoolVK::CollectCommandBuffer(vk::UniqueCommandBuffer&& buffer) {
  Lock lock(pool_mutex_);
  if (!pool_) {
    // If the command pool has already been destroyed, then its buffers have
    // already been freed.
    buffer.release();
    return;
  }
  collected_buffers_.push_back(std::move(buffer));
}

void CommandPoolVK::Destroy() {
  Lock lock(pool_mutex_);
  pool_.reset();

  // When the command pool is destroyed, all of its command buffers are freed.
  // Handles allocated from that pool are now invalid and must be discarded.
  for (auto& buffer : collected_buffers_) {
    buffer.release();
  }
  for (auto& buffer : unused_command_buffers_) {
    buffer.release();
  }
  unused_command_buffers_.clear();
  collected_buffers_.clear();
}

// Associates a resource with a thread and context.
using CommandPoolMap =
    std::unordered_map<uint64_t, std::shared_ptr<CommandPoolVK>>;

// CommandPoolVK Lifecycle:
// 1. End of frame will reset the command pool (clearing this on a thread).
//    There will still be references to the command pool from the uncompleted
//    command buffers.
// 2. The last reference to the command pool will be released from the fence
//    waiter thread, which will schedule a task on the resource
//    manager thread, which in turn will reset the command pool and make it
//    available for reuse ("recycle").
static thread_local std::unique_ptr<CommandPoolMap> tls_command_pool_map;

// Map each context to a list of all thread-local command pools associated
// with that context.
static Mutex g_all_pools_map_mutex;
static std::unordered_map<
    const ContextVK*,
    std::vector<std::weak_ptr<CommandPoolVK>>> g_all_pools_map
    IPLR_GUARDED_BY(g_all_pools_map_mutex);

// TODO(matanlurey): Return a status_or<> instead of nullptr when we have one.
std::shared_ptr<CommandPoolVK> CommandPoolRecyclerVK::Get() {
  auto const strong_context = context_.lock();
  if (!strong_context) {
    return nullptr;
  }

  // If there is a resource in used for this thread and context, return it.
  if (!tls_command_pool_map.get()) {
    tls_command_pool_map.reset(new CommandPoolMap());
  }
  CommandPoolMap& pool_map = *tls_command_pool_map.get();
  auto const hash = strong_context->GetHash();
  auto const it = pool_map.find(hash);
  if (it != pool_map.end()) {
    return it->second;
  }

  // Otherwise, create a new resource and return it.
  auto data = Create();
  if (!data || !data->pool) {
    return nullptr;
  }

  auto const resource = std::make_shared<CommandPoolVK>(
      std::move(data->pool), std::move(data->buffers), context_);
  pool_map.emplace(hash, resource);

  {
    Lock all_pools_lock(g_all_pools_map_mutex);
    g_all_pools_map[strong_context.get()].push_back(resource);
  }

  return resource;
}

// TODO(matanlurey): Return a status_or<> instead of nullopt when we have one.
std::optional<CommandPoolRecyclerVK::RecycledData>
CommandPoolRecyclerVK::Create() {
  // If we can reuse a command pool and its buffers, do so.
  if (auto data = Reuse()) {
    return data;
  }

  // Otherwise, create a new one.
  auto context = context_.lock();
  if (!context) {
    return std::nullopt;
  }
  vk::CommandPoolCreateInfo info;
  info.setQueueFamilyIndex(context->GetGraphicsQueue()->GetIndex().family);
  info.setFlags(vk::CommandPoolCreateFlagBits::eTransient);

  auto device = context->GetDevice();
  auto [result, pool] = device.createCommandPoolUnique(info);
  if (result != vk::Result::eSuccess) {
    return std::nullopt;
  }
  return CommandPoolRecyclerVK::RecycledData{.pool = std::move(pool),
                                             .buffers = {}};
}

std::optional<CommandPoolRecyclerVK::RecycledData>
CommandPoolRecyclerVK::Reuse() {
  // If there are no recycled pools, return nullopt.
  Lock recycled_lock(recycled_mutex_);
  if (recycled_.empty()) {
    return std::nullopt;
  }

  // Otherwise, remove and return a recycled pool.
  auto data = std::move(recycled_.back());
  recycled_.pop_back();
  return std::move(data);
}

void CommandPoolRecyclerVK::Reclaim(
    vk::UniqueCommandPool&& pool,
    std::vector<vk::UniqueCommandBuffer>&& buffers) {
  // Reset the pool on a background thread.
  auto strong_context = context_.lock();
  if (!strong_context) {
    return;
  }
  auto device = strong_context->GetDevice();
  device.resetCommandPool(pool.get());

  // Move the pool to the recycled list.
  Lock recycled_lock(recycled_mutex_);
  recycled_.push_back(
      RecycledData{.pool = std::move(pool), .buffers = std::move(buffers)});
}

CommandPoolRecyclerVK::~CommandPoolRecyclerVK() {
  // Ensure all recycled pools are reclaimed before this is destroyed.
  Dispose();
}

void CommandPoolRecyclerVK::Dispose() {
  CommandPoolMap* pool_map = tls_command_pool_map.get();
  if (pool_map) {
    pool_map->clear();
  }
}

void CommandPoolRecyclerVK::DestroyThreadLocalPools(const ContextVK* context) {
  // Delete the context's entry in this thread's command pool map.
  if (tls_command_pool_map.get()) {
    tls_command_pool_map.get()->erase(context->GetHash());
  }

  // Destroy all other thread-local CommandPoolVK instances associated with
  // this context.
  Lock all_pools_lock(g_all_pools_map_mutex);
  auto found = g_all_pools_map.find(context);
  if (found != g_all_pools_map.end()) {
    for (auto& weak_pool : found->second) {
      auto pool = weak_pool.lock();
      if (!pool) {
        continue;
      }
      // Delete all objects held by this pool.  The destroyed pool will still
      // remain in its thread's TLS map until that thread exits.
      pool->Destroy();
    }
    g_all_pools_map.erase(found);
  }
}

}  // namespace impeller
