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

#include "src/ui/lib/escher/impl/vulkan_utils.h"
#include "src/ui/lib/escher/resources/resource_manager.h"
#include "src/ui/lib/escher/util/trace_macros.h"

namespace escher {
namespace impl {

namespace {

bool CheckBufferMemoryRequirements(ResourceManager* manager, vk::Buffer vk_buffer,
                                   const GpuMemPtr& mem) {
  auto mem_requirements = manager->vk_device().getBufferMemoryRequirements(vk_buffer);

  auto size_required = mem_requirements.size;
  auto alignment_required = mem_requirements.alignment;

  if (mem->size() < size_required) {
    FX_LOGS(ERROR) << "Memory requirements check failed: Buffer requires " << size_required
                   << " bytes of memory, while the provided mem size is " << mem->size()
                   << " bytes.";
    return false;
  }

  if (mem->offset() % alignment_required != 0) {
    FX_LOGS(ERROR) << "Memory requirements check failed: Buffer requires alignment of "
                   << alignment_required << " bytes, while the provided mem offset is "
                   << mem->offset();
    return false;
  }

  return true;
}

}  // namespace

BufferPtr NaiveBuffer::New(ResourceManager* manager, GpuMemPtr mem,
                           vk::BufferUsageFlags usage_flags) {
  TRACE_DURATION("gfx", "escher::NaiveBuffer::New");
  auto device = manager->vulkan_context().device;
  auto size = mem->size();

  // Create buffer.
  vk::BufferCreateInfo buffer_create_info;
  buffer_create_info.size = mem->size();
  buffer_create_info.usage = usage_flags;
  buffer_create_info.sharingMode = vk::SharingMode::eExclusive;
  auto vk_buffer = ESCHER_CHECKED_VK_RESULT(device.createBuffer(buffer_create_info));

  // Check buffer memory requirements before binding the buffer to memory.
  if (!CheckBufferMemoryRequirements(manager, vk_buffer, mem)) {
    FX_LOGS(ERROR) << "NaiveBuffer::New() Failed: cannot satisfy memory requirements.";
    return nullptr;
  }

  return fxl::AdoptRef(new NaiveBuffer(manager, std::move(mem), size, vk_buffer));
}

BufferPtr NaiveBuffer::AdoptVkBuffer(ResourceManager* manager, GpuMemPtr mem,
                                     vk::DeviceSize vk_buffer_size, vk::Buffer vk_buffer) {
  TRACE_DURATION("gfx", "escher::NaiveBuffer::AdoptVkBuffer");

  // Check buffer memory requirements before binding the buffer to memory.
  if (!CheckBufferMemoryRequirements(manager, vk_buffer, mem)) {
    FX_LOGS(ERROR) << "NaiveBuffer::AdoptVkBuffer() Failed: cannot satisfy memory requirements.";
    return nullptr;
  }

  return fxl::AdoptRef(new NaiveBuffer(manager, std::move(mem), vk_buffer_size, vk_buffer));
}

NaiveBuffer::NaiveBuffer(ResourceManager* manager, GpuMemPtr mem, vk::DeviceSize vk_buffer_size,
                         vk::Buffer buffer)
    : Buffer(manager, buffer, vk_buffer_size, mem->mapped_ptr()), mem_(std::move(mem)) {
  FX_CHECK(vk());
  FX_CHECK(mem_);

  auto status = vulkan_context().device.bindBufferMemory(vk(), mem_->base(), mem_->offset());
  FX_CHECK(status == vk::Result::eSuccess)
      << "bindBufferMemory failed with status " << (VkResult)status;
}

NaiveBuffer::~NaiveBuffer() { vulkan_context().device.destroyBuffer(vk()); }

}  // namespace impl
}  // namespace escher
