// Copyright 2018 The Fuchsia 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 "src/ui/lib/escher/renderer/buffer_cache.h"

#include "src/ui/lib/escher/util/trace_macros.h"
#include "src/ui/lib/escher/vk/gpu_allocator.h"

namespace escher {

// The maximum ratio that the allocated buffer can exceed the requested size.
// Note: If there are large discrepancies between requested size and cached
// buffer size, it would make sense to sub-allocate a buffer and release a
// smaller buffer portion. For now, the cache will reuse a buffer that is at
// most 2x the size requested.
constexpr int8_t kMaxBufferAllocationRequestRatio = 2;

BufferCache::BufferCache(EscherWeakPtr escher)
    : ResourceRecycler(escher),
      cache_size_(0),
      gpu_allocator_(escher->gpu_allocator()->GetWeakPtr()),
      weak_factory_(this) {
  FXL_DCHECK(free_buffer_cache_.empty());
  FXL_DCHECK(free_buffers_.empty());
}

BufferCache::~BufferCache() {
  free_buffer_cache_.clear();
  free_buffers_by_id_.clear();
  cache_size_ = 0;
  free_buffers_.clear();
}

BufferPtr BufferCache::NewHostBuffer(vk::DeviceSize vk_size) {
  TRACE_DURATION("gfx", "escher::BufferCache::NewHostBuffer");
  BufferPtr buffer;
  // See if there's a buffer of the right size. Or, find the smallest buffer
  // that is big enough to handle the size request.
  auto size_itr = free_buffers_.lower_bound(vk_size);

  if (size_itr != free_buffers_.end() &&
      size_itr->first > kMaxBufferAllocationRequestRatio * vk_size) {
    // Next largest buffer is too big, just create a new one.
    size_itr = free_buffers_.end();
  }

  if (size_itr != free_buffers_.end()) {
    // There is a free buffer in the cache that can be recycled.
    auto& buffer_list_at_size = size_itr->second;
    auto buf = std::move(buffer_list_at_size.front());
    buffer = BufferPtr(buf.release());

    // Remove the element from the free map, and prune the map if necessary.
    buffer_list_at_size.pop_front();
    if (buffer_list_at_size.empty()) {
      free_buffers_.erase(size_itr);
    }

    // Remove the buffer from the cache.
    cache_size_ -= buffer->size();
    auto info_itr = free_buffers_by_id_.find(buffer->uid());
    FXL_DCHECK(info_itr != free_buffers_by_id_.end());
    auto time_key = info_itr->second.allocation_time;
    free_buffer_cache_.erase(free_buffer_cache_.find(time_key));
    free_buffers_by_id_.erase(info_itr);
  } else {
    // Construct a new buffer of the requested size.
    buffer = gpu_allocator_->AllocateBuffer(this, vk_size, kUsageFlags, kMemoryPropertyFlags);
  }

  return buffer;
}

void BufferCache::RecycleResource(std::unique_ptr<Resource> resource) {
  FXL_DCHECK(resource->IsKindOf<Buffer>());

  std::unique_ptr<Buffer> buffer(static_cast<Buffer*>(resource.release()));
  CacheInfo cache_info;
  cache_info.id = buffer->uid();
  cache_info.allocation_time = fxl::TimePoint::Now();
  // TODO(40736): Now buffer->size() is the size of VkBuffer, so it can only
  // reclaim buffers of size greater than or equal to the requested size. For
  // buffers with size less than the requested size, but with memory enough to
  // hold the requested buffer, it doesn't work.
  cache_info.size = buffer->size();
  // Ensure this buffer is not already tracked.
  FXL_DCHECK(free_buffers_by_id_.find(cache_info.id) == free_buffers_by_id_.end())
      << "uid: " << buffer->uid();

  // Add to the map.
  free_buffers_[cache_info.size].emplace_back(std::move(buffer));

  // Add to the cache.
  cache_size_ += cache_info.size;
  free_buffer_cache_[cache_info.allocation_time] = cache_info;
  free_buffers_by_id_[cache_info.id] = cache_info;

  // Prune if the cache has grown too much.
  while (cache_size_ > kMaxMemoryCached && !free_buffer_cache_.empty()) {
    // Find the oldest buffer in the cache.
    auto cache_itr = free_buffer_cache_.lower_bound(fxl::TimePoint::Min());
    FXL_DCHECK(cache_itr != free_buffer_cache_.end());
    uint64_t id_to_free = cache_itr->second.id;
    vk::DeviceSize size_freed = cache_itr->second.size;

    // Drop the entries from the cache.
    free_buffer_cache_.erase(cache_itr);
    free_buffers_by_id_.erase(free_buffers_by_id_.find(id_to_free));
    cache_size_ -= size_freed;
    FXL_DCHECK(cache_size_ >= 0);

    // Remove the buffer from the free map, releasing the buffer.
    auto find_map_for_size_itr = free_buffers_.find(size_freed);
    FXL_DCHECK(find_map_for_size_itr != free_buffers_.end());

    auto& buffer_list_at_size = find_map_for_size_itr->second;
    auto find_buf_itr = std::find_if(buffer_list_at_size.begin(), buffer_list_at_size.end(),
                                     [id_to_free](const std::unique_ptr<Buffer>& buffer) {
                                       return buffer->uid() == id_to_free;
                                     });
    FXL_DCHECK(find_buf_itr != buffer_list_at_size.end());
    // Release the buffer.
    buffer_list_at_size.erase(find_buf_itr);
    // If there's no other buffers of this size, release size map from the
    // free_buffers_ map.
    if (buffer_list_at_size.empty()) {
      free_buffers_.erase(find_map_for_size_itr);
    }
  }
}

}  // namespace escher
