// Copyright 2016 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/impl/uniform_buffer_pool.h"

#include "src/ui/lib/escher/escher.h"
#include "src/ui/lib/escher/impl/naive_buffer.h"
#include "src/ui/lib/escher/impl/vulkan_utils.h"
#include "src/ui/lib/escher/vk/gpu_allocator.h"

namespace escher {
namespace impl {

// TODO: obtain max uniform-buffer size from Vulkan.  64kB is typical.
constexpr vk::DeviceSize kBufferSize = 65536;

UniformBufferPool::UniformBufferPool(EscherWeakPtr escher, size_t ring_size,
                                     GpuAllocator* allocator,
                                     vk::MemoryPropertyFlags additional_flags)
    : ResourceManager(escher),
      allocator_(allocator ? allocator : escher->gpu_allocator()),
      flags_(additional_flags | vk::MemoryPropertyFlagBits::eHostVisible),
      buffer_size_(kBufferSize),
      ring_size_(ring_size),
      weak_factory_(this) {
  FXL_DCHECK(ring_size >= 1 && ring_size <= kMaxRingSize);
}

UniformBufferPool::~UniformBufferPool() {}

BufferPtr UniformBufferPool::Allocate() {
  if (ring_[0].empty()) {
    InternalAllocate();
  }
  BufferPtr buf(ring_[0].back().release());
  ring_[0].pop_back();
  return buf;
}

void UniformBufferPool::InternalAllocate() {
  // Create a batch of buffers.
  constexpr uint32_t kBufferBatchSize = 10;
  vk::Buffer new_buffers[kBufferBatchSize];
  vk::BufferCreateInfo info;
  info.size = buffer_size_;
  info.usage = vk::BufferUsageFlagBits::eUniformBuffer;
  info.sharingMode = vk::SharingMode::eExclusive;
  for (uint32_t i = 0; i < kBufferBatchSize; ++i) {
    new_buffers[i] = ESCHER_CHECKED_VK_RESULT(vk_device().createBuffer(info));
  }

  // Determine the memory requirements for a single buffer.
  vk::MemoryRequirements reqs = vk_device().getBufferMemoryRequirements(new_buffers[0]);
  // If necessary, we can write the logic to deal with the conditions below.
  FXL_CHECK(buffer_size_ == reqs.size);
  FXL_CHECK(buffer_size_ % reqs.alignment == 0);

  // Allocate enough memory for all of the buffers.
  reqs.size *= kBufferBatchSize;
  auto batch_mem = allocator_->AllocateMemory(reqs, flags_);

  // See below: when OnReceiveOwnable() receives the newly-allocated buffer we
  // need to know that it is new and can therefore be used immediately instead
  // added to the back of the ring.
  is_allocating_ = true;

  for (uint32_t i = 0; i < kBufferBatchSize; ++i) {
    // Validation layer complains if we bind a buffer to memory without first
    // querying it's memory requirements.  This shouldn't be necessary, since
    // all buffers are identically-configured.
    // TODO: disable this in release mode.
    vk_device().getBufferMemoryRequirements(new_buffers[i]);

    // Sub-allocate memory for each buffer.
    auto mem = batch_mem->Suballocate(buffer_size_, i * buffer_size_);

    // Workaround for dealing with RefPtr/Reffable Adopt() semantics.  Let the
    // RefPtr go out of scope immediately; the Buffer will be added to
    // free_buffers_ via OnReceiveOwnable().
    NaiveBuffer::AdoptVkBuffer(this, std::move(mem), buffer_size_, new_buffers[i]);
  }

  is_allocating_ = false;
}

void UniformBufferPool::OnReceiveOwnable(std::unique_ptr<Resource> resource) {
  FXL_DCHECK(resource->IsKindOf<Buffer>());
  size_t ring_index = is_allocating_ ? 0 : ring_size_ - 1;
  ring_[ring_index].emplace_back(static_cast<Buffer*>(resource.release()));
}

void UniformBufferPool::BeginFrame() {
  if (ring_size_ == 1)
    return;

  // Move all entries from ring_[1] to ring_[0].
  for (auto& buf : ring_[1]) {
    ring_[0].push_back(std::move(buf));
  }
  ring_[1].clear();

  // The ring cleared above is moved to the back, and all others are moved one
  // forward.
  //
  // TODO(ES-101): This is a constant amount of cache-friendly work per frame
  // (just swapping pointers in the vectors), so it's probably not a performance
  // issue, but is worth looking into later.
  for (size_t i = 2; i < ring_size_; ++i) {
    std::swap(ring_[i], ring_[i - 1]);
  }
}

}  // namespace impl
}  // namespace escher
