// 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 "lib/escher/impl/mesh_manager.h"

#include <iterator>

#include "lib/escher/geometry/types.h"
#include "lib/escher/impl/command_buffer_pool.h"
#include "lib/escher/impl/vulkan_utils.h"
#include "lib/escher/resources/resource_recycler.h"
#include "lib/escher/vk/buffer.h"
#include "lib/escher/vk/gpu_allocator.h"
#include "lib/escher/vk/vulkan_context.h"

namespace escher {
namespace impl {

MeshManager::MeshManager(CommandBufferPool* command_buffer_pool,
                         GpuAllocator* allocator, GpuUploader* uploader,
                         ResourceRecycler* resource_recycler)
    : command_buffer_pool_(command_buffer_pool),
      allocator_(allocator),
      uploader_(uploader),
      resource_recycler_(resource_recycler),
      device_(command_buffer_pool->device()),
      queue_(command_buffer_pool->queue()),
      builder_count_(0) {}

MeshManager::~MeshManager() { FXL_DCHECK(builder_count_ == 0); }

MeshBuilderPtr MeshManager::NewMeshBuilder(const MeshSpec& spec,
                                           size_t max_vertex_count,
                                           size_t max_index_count) {
  FXL_DCHECK(spec.IsValidOneBufferMesh());
  size_t stride = spec.stride(0);
  return AdoptRef(new MeshManager::MeshBuilder(
      this, spec, max_vertex_count, max_index_count,
      uploader_->GetWriter(max_vertex_count * stride),
      uploader_->GetWriter(max_index_count * sizeof(uint32_t))));
}

MeshManager::MeshBuilder::MeshBuilder(MeshManager* manager,
                                      const MeshSpec& spec,
                                      size_t max_vertex_count,
                                      size_t max_index_count,
                                      GpuUploader::Writer vertex_writer,
                                      GpuUploader::Writer index_writer)
    : escher::MeshBuilder(max_vertex_count, max_index_count, spec.stride(0),
                          vertex_writer.ptr(),
                          reinterpret_cast<uint32_t*>(index_writer.ptr())),
      manager_(manager),
      spec_(spec),
      is_built_(false),
      vertex_writer_(std::move(vertex_writer)),
      index_writer_(std::move(index_writer)) {
  FXL_DCHECK(spec.IsValidOneBufferMesh());
}

MeshManager::MeshBuilder::~MeshBuilder() {}

BoundingBox MeshManager::MeshBuilder::ComputeBoundingBox2D() const {
  FXL_DCHECK(spec_.attribute_offset(0, MeshAttribute::kPosition2D) == 0);
  uint8_t* vertex_ptr = vertex_staging_buffer_;

  vec2* pos = reinterpret_cast<vec2*>(vertex_ptr);
  vec3 min(*pos, 0);
  vec3 max(*pos, 0);

  for (size_t i = 1; i < vertex_count_; ++i) {
    vertex_ptr += vertex_stride_;
    pos = reinterpret_cast<vec2*>(vertex_ptr);
    min = glm::min(min, vec3(*pos, 0));
    max = glm::max(max, vec3(*pos, 0));
  }

  return BoundingBox(min, max);
}

BoundingBox MeshManager::MeshBuilder::ComputeBoundingBox3D() const {
  FXL_DCHECK(spec_.attribute_offset(0, MeshAttribute::kPosition3D) == 0);
  uint8_t* vertex_ptr = vertex_staging_buffer_;

  vec3* pos = reinterpret_cast<vec3*>(vertex_ptr);
  vec3 min(*pos);
  vec3 max(*pos);

  for (size_t i = 1; i < vertex_count_; ++i) {
    vertex_ptr += vertex_stride_;
    pos = reinterpret_cast<vec3*>(vertex_ptr);
    min = glm::min(min, *pos);
    max = glm::max(max, *pos);
  }

  return BoundingBox(min, max);
}

BoundingBox MeshManager::MeshBuilder::ComputeBoundingBox() const {
  FXL_DCHECK(vertex_count_ > 0);
  FXL_DCHECK(spec_.IsValidOneBufferMesh());
  return spec_.has_attribute(0, MeshAttribute::kPosition2D)
             ? ComputeBoundingBox2D()
             : ComputeBoundingBox3D();
}

MeshPtr MeshManager::MeshBuilder::Build() {
  FXL_DCHECK(!is_built_);
  if (is_built_) {
    return MeshPtr();
  }
  is_built_ = true;

  vk::Device device = manager_->device_;
  GpuAllocator* allocator = manager_->allocator_;

  // TODO: use eTransferDstOptimal instead of eTransferDst?
  auto vertex_buffer = allocator->AllocateBuffer(
      manager_->resource_recycler(), vertex_count_ * vertex_stride_,
      vk::BufferUsageFlagBits::eVertexBuffer |
          vk::BufferUsageFlagBits::eTransferSrc |
          vk::BufferUsageFlagBits::eTransferDst,
      vk::MemoryPropertyFlagBits::eDeviceLocal);
  auto index_buffer = allocator->AllocateBuffer(
      manager_->resource_recycler(), index_count_ * sizeof(uint32_t),
      vk::BufferUsageFlagBits::eIndexBuffer |
          vk::BufferUsageFlagBits::eTransferSrc |
          vk::BufferUsageFlagBits::eTransferDst,
      vk::MemoryPropertyFlagBits::eDeviceLocal);

  vertex_writer_.WriteBuffer(vertex_buffer, {0, 0, vertex_buffer->size()},
                             Semaphore::New(device));
  vertex_writer_.Submit();

  index_writer_.WriteBuffer(index_buffer, {0, 0, index_buffer->size()},
                            SemaphorePtr());
  index_writer_.Submit();

  auto mesh = fxl::MakeRefCounted<Mesh>(
      manager_->resource_recycler(), spec_, ComputeBoundingBox(), vertex_count_,
      index_count_, vertex_buffer, std::move(index_buffer));

  mesh->SetWaitSemaphore(vertex_buffer->TakeWaitSemaphore());
  return mesh;
}

}  // namespace impl
}  // namespace escher
