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

#include "src/lib/fxl/macros.h"
#include "src/ui/lib/escher/impl/descriptor_set_pool.h"
#include "src/ui/lib/escher/impl/mesh_shader_binding.h"
#include "src/ui/lib/escher/shape/mesh.h"
#include "src/ui/lib/escher/util/trace_macros.h"
#include "src/ui/lib/escher/vk/buffer.h"
#include "src/ui/lib/escher/vk/framebuffer.h"
#include "src/ui/lib/escher/vk/image.h"
#include "src/ui/lib/escher/vk/render_pass.h"

namespace escher {
namespace impl {

CommandBuffer::CommandBuffer(vk::Device device, vk::CommandBuffer command_buffer, vk::Fence fence,
                             vk::PipelineStageFlags pipeline_stage_mask, bool use_protected_memory)
    : device_(device),
      command_buffer_(command_buffer),
      fence_(fence),
      pipeline_stage_mask_(pipeline_stage_mask),
      use_protected_memory_(use_protected_memory) {}

CommandBuffer::~CommandBuffer() {
  FXL_DCHECK(!is_active_ && !is_submitted_);
  // Owner is responsible for destroying command buffer and fence.
}

void CommandBuffer::Begin(uint64_t sequence_number) {
  FXL_DCHECK(!is_active_ && !is_submitted_);
  FXL_DCHECK(sequence_number > sequence_number_);
  is_active_ = true;
  sequence_number_ = sequence_number;
  auto result = command_buffer_.begin(vk::CommandBufferBeginInfo());
  FXL_DCHECK(result == vk::Result::eSuccess);
}

bool CommandBuffer::Submit(vk::Queue queue, CommandBufferFinishedCallback callback) {
  // NOTE: this name is important for benchmarking.  Do not remove or modify it
  // without also updating the "process_gfx_trace.go" script.
  TRACE_DURATION("gfx", "escher::CommandBuffer::Submit");

  FXL_DCHECK(is_active_ && !is_submitted_);
  is_submitted_ = true;
  callback_ = std::move(callback);

  auto end_command_buffer_result = command_buffer_.end();
  FXL_DCHECK(end_command_buffer_result == vk::Result::eSuccess);

  auto protected_submit_info = vk::ProtectedSubmitInfo().setProtectedSubmit(true);
  vk::SubmitInfo submit_info;
  submit_info.commandBufferCount = 1;
  submit_info.pNext = use_protected_memory_ ? &protected_submit_info : nullptr;
  submit_info.pCommandBuffers = &command_buffer_;
  submit_info.waitSemaphoreCount = wait_semaphores_for_submit_.size();
  submit_info.pWaitSemaphores = wait_semaphores_for_submit_.data();
  submit_info.pWaitDstStageMask = wait_semaphore_stages_.data();
  submit_info.signalSemaphoreCount = signal_semaphores_for_submit_.size();
  submit_info.pSignalSemaphores = signal_semaphores_for_submit_.data();

  auto submit_result = queue.submit(1, &submit_info, fence_);
  if (submit_result != vk::Result::eSuccess) {
    FXL_LOG(WARNING) << "failed queue submission: " << to_string(submit_result);
    // Clearing these flags allows Retire() to make progress.
    is_active_ = is_submitted_ = false;
    return false;
  }
  return true;
}

vk::Result CommandBuffer::Wait(uint64_t nanoseconds) {
  if (!is_active_) {
    // The command buffer is already finished.
    return vk::Result::eSuccess;
  }
  FXL_DCHECK(is_submitted_);
  return device_.waitForFences(1, &fence_, true, nanoseconds);
}

void CommandBuffer::AddWaitSemaphore(SemaphorePtr semaphore, vk::PipelineStageFlags stage) {
  FXL_DCHECK(is_active_);
  if (semaphore) {
    // Build up list that will be used when frame is submitted.
    wait_semaphores_for_submit_.push_back(semaphore->vk_semaphore());
    wait_semaphore_stages_.push_back(stage);
    // Retain semaphore to ensure that it doesn't prematurely die.
    wait_semaphores_.push_back(std::move(semaphore));
  }
}

void CommandBuffer::AddSignalSemaphore(SemaphorePtr semaphore) {
  FXL_DCHECK(is_active_);
  if (semaphore) {
    // Build up list that will be used when frame is submitted.
    signal_semaphores_for_submit_.push_back(semaphore->vk_semaphore());
    // Retain semaphore to ensure that it doesn't prematurely die.
    signal_semaphores_.push_back(std::move(semaphore));
  }
}

bool CommandBuffer::ContainsSignalSemaphore(const SemaphorePtr& semaphore) const {
  return std::find(signal_semaphores_.begin(), signal_semaphores_.end(), semaphore) !=
         signal_semaphores_.end();
}

void CommandBuffer::KeepAlive(Resource* resource) {
  FXL_DCHECK(is_active_);
  if (sequence_number_ == resource->sequence_number()) {
    // The resource is already being kept alive by this CommandBuffer.
    return;
  }

  resource->KeepAlive(sequence_number_);
}

void CommandBuffer::CopyImage(const ImagePtr& src_image, const ImagePtr& dst_image,
                              vk::ImageLayout src_layout, vk::ImageLayout dst_layout,
                              vk::ImageCopy* region) {
  // If commandBuffer is a protected command buffer, then dstImage must not be an unprotected image.
  // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/vkCmdCopyImage.html
  FXL_CHECK(!use_protected_memory() || dst_image->use_protected_memory());

  command_buffer_.copyImage(src_image->vk(), src_layout, dst_image->vk(), dst_layout, 1, region);
  KeepAlive(src_image);
  KeepAlive(dst_image);
}

void CommandBuffer::CopyBuffer(const BufferPtr& src, const BufferPtr& dst, vk::BufferCopy region) {
  // If commandBuffer is a protected command buffer, then dstBuffer must not be an unprotected
  // buffer.
  // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/vkCmdCopyBuffer.html
  // We do not use protected buffers.
  FXL_CHECK(!use_protected_memory());

  command_buffer_.copyBuffer(src->vk(), dst->vk(), 1 /* region_count */, &region);
  KeepAlive(src);
  KeepAlive(dst);
}

void CommandBuffer::CopyBufferAfterBarrier(const BufferPtr& src, const BufferPtr& dst,
                                           vk::BufferCopy region, vk::AccessFlags src_access_mask,
                                           vk::PipelineStageFlags src_stage_mask) {
  vk::BufferMemoryBarrier barrier;
  barrier.srcAccessMask = src_access_mask;
  barrier.dstAccessMask = vk::AccessFlagBits::eTransferRead;
  barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  barrier.buffer = dst->vk();
  barrier.offset = 0;
  barrier.size = dst->size();
  command_buffer_.pipelineBarrier(src_stage_mask, vk::PipelineStageFlagBits::eTransfer,
                                  vk::DependencyFlags(), 0, nullptr, 1, &barrier, 0, nullptr);
  CopyBuffer(src, dst, region);
}

// TODO(41296): Move this function out to a separated utility function, rather
// than part of impl::CommandBuffer.
void CommandBuffer::TransitionImageLayout(const ImagePtr& image, vk::ImageLayout old_layout,
                                          vk::ImageLayout new_layout) {
  KeepAlive(image);

  vk::PipelineStageFlags src_stage_mask;
  vk::PipelineStageFlags dst_stage_mask;

  vk::ImageMemoryBarrier barrier;
  barrier.oldLayout = old_layout;
  barrier.newLayout = new_layout;
  barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  barrier.image = image->vk();

  if (image->has_depth() || image->has_stencil()) {
    if (image->has_depth()) {
      barrier.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eDepth;
    }
    if (image->has_stencil()) {
      barrier.subresourceRange.aspectMask |= vk::ImageAspectFlagBits::eStencil;
    }
  } else {
    barrier.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
  }

  // TODO: assert that image only has one level.
  barrier.subresourceRange.baseMipLevel = 0;
  barrier.subresourceRange.levelCount = 1;
  barrier.subresourceRange.baseArrayLayer = 0;
  barrier.subresourceRange.layerCount = 1;

  switch (old_layout) {
    case vk::ImageLayout::eColorAttachmentOptimal:
      barrier.srcAccessMask =
          vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eColorAttachmentWrite;
      src_stage_mask = vk::PipelineStageFlagBits::eColorAttachmentOutput;
      break;
    case vk::ImageLayout::eDepthStencilAttachmentOptimal:
      barrier.srcAccessMask = vk::AccessFlagBits::eDepthStencilAttachmentRead |
                              vk::AccessFlagBits::eDepthStencilAttachmentWrite;
      src_stage_mask = vk::PipelineStageFlagBits::eLateFragmentTests;
      break;
    case vk::ImageLayout::eGeneral:
      barrier.srcAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite;
      src_stage_mask = vk::PipelineStageFlagBits::eComputeShader;
      break;
    case vk::ImageLayout::ePreinitialized:
      barrier.srcAccessMask = vk::AccessFlagBits::eHostWrite;
      src_stage_mask = vk::PipelineStageFlagBits::eHost;
      break;
    case vk::ImageLayout::eShaderReadOnlyOptimal:
      barrier.srcAccessMask = vk::AccessFlagBits::eShaderRead;
      // TODO: investigate whether there are performance benefits to providing
      // a less-conservative mask.
      src_stage_mask = vk::PipelineStageFlagBits::eVertexShader |
                       vk::PipelineStageFlagBits::eTessellationControlShader |
                       vk::PipelineStageFlagBits::eTessellationEvaluationShader |
                       vk::PipelineStageFlagBits::eGeometryShader |
                       vk::PipelineStageFlagBits::eFragmentShader;
      break;
    case vk::ImageLayout::eTransferDstOptimal:
      barrier.srcAccessMask = vk::AccessFlagBits::eTransferWrite;
      src_stage_mask = vk::PipelineStageFlagBits::eTransfer;
      break;
    case vk::ImageLayout::eTransferSrcOptimal:
      barrier.srcAccessMask = vk::AccessFlagBits::eTransferRead;
      src_stage_mask = vk::PipelineStageFlagBits::eTransfer;
      break;
    case vk::ImageLayout::eUndefined:
      // If layout was eUndefined, we don't need a srcAccessMask.

      // Source images with eUndefined layout have not yet been initialized nor
      // used, or we do not care about their previously stored data. So we use
      // eTopOfPipe as the source stage mask, as it will never block the
      // pipeline barrier.
      src_stage_mask = vk::PipelineStageFlagBits::eTopOfPipe;
      break;
    default:
      FXL_LOG(ERROR) << "CommandBuffer does not know how to transition from layout: "
                     << vk::to_string(old_layout);
      FXL_DCHECK(false);
  }

  switch (new_layout) {
    case vk::ImageLayout::eColorAttachmentOptimal:
      barrier.dstAccessMask =
          vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eColorAttachmentWrite;
      dst_stage_mask = vk::PipelineStageFlagBits::eColorAttachmentOutput;
      break;
    case vk::ImageLayout::eDepthStencilAttachmentOptimal:
      barrier.dstAccessMask = vk::AccessFlagBits::eDepthStencilAttachmentRead |
                              vk::AccessFlagBits::eDepthStencilAttachmentWrite;
      dst_stage_mask = vk::PipelineStageFlagBits::eEarlyFragmentTests;
      break;
    case vk::ImageLayout::eGeneral:
      barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite;
      dst_stage_mask = vk::PipelineStageFlagBits::eComputeShader;
      break;
    case vk::ImageLayout::ePresentSrcKHR:
      barrier.dstAccessMask = vk::AccessFlagBits::eMemoryRead;
      dst_stage_mask = vk::PipelineStageFlagBits::eAllGraphics;
      break;
    case vk::ImageLayout::eShaderReadOnlyOptimal:
      barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead;
      // TODO: investigate whether there are performance benefits to providing
      // a less-conservative mask.
      dst_stage_mask = (pipeline_stage_mask_ & vk::PipelineStageFlagBits::eAllCommands)
                           ? vk::PipelineStageFlagBits::eAllCommands
                           : vk::PipelineStageFlagBits::eAllGraphics;
      break;
    case vk::ImageLayout::eTransferDstOptimal:
      barrier.dstAccessMask = vk::AccessFlagBits::eTransferWrite;
      dst_stage_mask = vk::PipelineStageFlagBits::eTransfer;
      break;
    case vk::ImageLayout::eTransferSrcOptimal:
      barrier.dstAccessMask = vk::AccessFlagBits::eTransferRead;
      dst_stage_mask = vk::PipelineStageFlagBits::eTransfer;
      break;
    case vk::ImageLayout::eUndefined:
    default:
      FXL_LOG(ERROR) << "CommandBuffer does not know how to transition to layout: "
                     << vk::to_string(new_layout);
      FXL_DCHECK(false);
  }

  src_stage_mask = src_stage_mask & pipeline_stage_mask_;
  dst_stage_mask = dst_stage_mask & pipeline_stage_mask_;

  image->set_layout(new_layout);

  command_buffer_.pipelineBarrier(src_stage_mask, dst_stage_mask, vk::DependencyFlagBits::eByRegion,
                                  0, nullptr, 0, nullptr, 1, &barrier);
}

void CommandBuffer::BeginRenderPass(const escher::RenderPassPtr& render_pass,
                                    const escher::FramebufferPtr& framebuffer,
                                    const std::vector<vk::ClearValue>& clear_values,
                                    const vk::Rect2D viewport) {
  KeepAlive(render_pass);
  BeginRenderPass(render_pass->vk(), framebuffer, clear_values.data(), clear_values.size(),
                  viewport);
}

void CommandBuffer::BeginRenderPass(vk::RenderPass render_pass,
                                    const escher::FramebufferPtr& framebuffer,
                                    const std::vector<vk::ClearValue>& clear_values,
                                    const vk::Rect2D viewport) {
  BeginRenderPass(render_pass, framebuffer, clear_values.data(), clear_values.size(), viewport);
}

void CommandBuffer::BeginRenderPass(vk::RenderPass render_pass,
                                    const escher::FramebufferPtr& framebuffer,
                                    const vk::ClearValue* clear_values, size_t clear_value_count,
                                    vk::Rect2D viewport) {
  FXL_DCHECK(is_active_);
  KeepAlive(framebuffer);

  vk::RenderPassBeginInfo info;
  info.renderPass = render_pass;
  info.renderArea = viewport;
  info.clearValueCount = static_cast<uint32_t>(clear_value_count);
  info.pClearValues = clear_values;
  info.framebuffer = framebuffer->vk();

  command_buffer_.beginRenderPass(&info, vk::SubpassContents::eInline);

  vk::Viewport vk_viewport;
  vk_viewport.x = static_cast<float>(viewport.offset.x);
  vk_viewport.y = static_cast<float>(viewport.offset.y);
  vk_viewport.width = static_cast<float>(viewport.extent.width);
  vk_viewport.height = static_cast<float>(viewport.extent.height);
  vk_viewport.minDepth = static_cast<float>(0.0f);
  vk_viewport.maxDepth = static_cast<float>(1.0f);
  command_buffer_.setViewport(0, 1, &vk_viewport);

  // TODO: probably unnecessary?
  vk::Rect2D scissor;
  scissor.extent.width = viewport.extent.width;
  scissor.extent.height = viewport.extent.height;
  scissor.offset.x = viewport.offset.x;
  scissor.offset.y = viewport.offset.y;
  command_buffer_.setScissor(0, 1, &scissor);
}

void CommandBuffer::EndRenderPass() { command_buffer_.endRenderPass(); }

bool CommandBuffer::Retire() {
  if (!is_active_) {
    // Submission failed, so proceed with cleanup.
    FXL_DLOG(INFO) << "CommandBuffer submission failed, proceeding with retirement";
  } else if (!is_submitted_) {
    return false;
  } else {
    FXL_DCHECK(is_active_);
    // Check if fence has been reached.
    auto fence_status = device_.getFenceStatus(fence_);
    if (fence_status == vk::Result::eNotReady) {
      // Fence has not been reached; try again later.
      return false;
    }
  }
  is_active_ = is_submitted_ = false;
  device_.resetFences(1, &fence_);

  if (callback_) {
    TRACE_DURATION("gfx", "escher::CommandBuffer::Retire::callback");
    callback_();
    callback_ = nullptr;
  }

  // TODO: move semaphores to pool for reuse?
  wait_semaphores_.clear();
  wait_semaphores_for_submit_.clear();
  wait_semaphore_stages_.clear();
  signal_semaphores_.clear();
  signal_semaphores_for_submit_.clear();

  auto result = command_buffer_.reset(vk::CommandBufferResetFlags());
  FXL_DCHECK(result == vk::Result::eSuccess);

  return true;
}

}  // namespace impl
}  // namespace escher
