// Copyright 2013 The Flutter 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 "impeller/renderer/backend/vulkan/command_buffer_vk.h"

#include <memory>
#include <utility>

#include "flutter/fml/logging.h"
#include "impeller/base/validation.h"
#include "impeller/renderer/backend/vulkan/context_vk.h"
#include "impeller/renderer/backend/vulkan/fenced_command_buffer_vk.h"
#include "impeller/renderer/backend/vulkan/formats_vk.h"
#include "impeller/renderer/backend/vulkan/render_pass_vk.h"
#include "impeller/renderer/command_buffer.h"
#include "impeller/renderer/render_target.h"

namespace impeller {

std::shared_ptr<CommandBufferVK> CommandBufferVK::Create(
    const std::weak_ptr<const Context>& context_arg,
    vk::Device device,
    vk::CommandPool command_pool) {
  if (auto context = context_arg.lock()) {
    auto queue =
        reinterpret_cast<const ContextVK*>(context.get())->GetGraphicsQueue();
    auto fenced_command_buffer =
        std::make_shared<FencedCommandBufferVK>(device, queue, command_pool);
    return std::make_shared<CommandBufferVK>(context, device, command_pool,
                                             fenced_command_buffer);
  } else {
    return nullptr;
  }
}

CommandBufferVK::CommandBufferVK(
    std::weak_ptr<const Context> context,
    vk::Device device,
    vk::CommandPool command_pool,
    std::shared_ptr<FencedCommandBufferVK> command_buffer)
    : CommandBuffer(std::move(context)),
      device_(device),
      command_pool_(command_pool),
      fenced_command_buffer_(std::move(command_buffer)) {
  is_valid_ = true;
}

CommandBufferVK::~CommandBufferVK() = default;

void CommandBufferVK::SetLabel(const std::string& label) const {
  if (auto context = context_.lock()) {
    reinterpret_cast<const ContextVK*>(context.get())
        ->SetDebugName(fenced_command_buffer_->Get(), label);
  }
}

bool CommandBufferVK::IsValid() const {
  return is_valid_;
}

bool CommandBufferVK::OnSubmitCommands(CompletionCallback callback) {
  bool submit = fenced_command_buffer_->Submit();
  if (callback) {
    callback(submit ? CommandBuffer::Status::kCompleted
                    : CommandBuffer::Status::kError);
  }
  return submit;
}

std::shared_ptr<RenderPass> CommandBufferVK::OnCreateRenderPass(
    RenderTarget target) {
  std::vector<vk::AttachmentDescription> color_attachments;
  for (const auto& [k, attachment] : target.GetColorAttachments()) {
    const TextureDescriptor& tex_desc =
        attachment.texture->GetTextureDescriptor();

    vk::AttachmentDescription color_attachment;
    color_attachment.setFormat(ToVKImageFormat(tex_desc.format));
    color_attachment.setSamples(ToVKSampleCountFlagBits(tex_desc.sample_count));
    color_attachment.setLoadOp(ToVKAttachmentLoadOp(attachment.load_action));
    color_attachment.setStoreOp(ToVKAttachmentStoreOp(attachment.store_action));

    color_attachment.setStencilLoadOp(vk::AttachmentLoadOp::eDontCare);
    color_attachment.setStencilStoreOp(vk::AttachmentStoreOp::eDontCare);
    color_attachment.setInitialLayout(vk::ImageLayout::eColorAttachmentOptimal);
    color_attachment.setFinalLayout(vk::ImageLayout::ePresentSrcKHR);

    color_attachments.push_back(color_attachment);
  }

  // TODO (kaushikiska): support depth and stencil attachments.

  vk::AttachmentReference color_attachment_ref;
  color_attachment_ref.setAttachment(0);
  color_attachment_ref.setLayout(vk::ImageLayout::eColorAttachmentOptimal);

  vk::SubpassDescription subpass_desc;
  subpass_desc.setPipelineBindPoint(vk::PipelineBindPoint::eGraphics);
  subpass_desc.setColorAttachmentCount(color_attachments.size());
  subpass_desc.setPColorAttachments(&color_attachment_ref);

  vk::RenderPassCreateInfo render_pass_create;
  render_pass_create.setAttachmentCount(color_attachments.size());
  render_pass_create.setPAttachments(color_attachments.data());
  render_pass_create.setSubpassCount(1);
  render_pass_create.setPSubpasses(&subpass_desc);

  auto render_pass_create_res = device_.createRenderPass(render_pass_create);
  if (render_pass_create_res.result != vk::Result::eSuccess) {
    VALIDATION_LOG << "Failed to create render pass: "
                   << vk::to_string(render_pass_create_res.result);
    return nullptr;
  }

  vk::RenderPass render_pass = render_pass_create_res.value;
  return std::make_shared<RenderPassVK>(context_, device_, std::move(target),
                                        fenced_command_buffer_, render_pass);
}

std::shared_ptr<BlitPass> CommandBufferVK::OnCreateBlitPass() const {
  // TODO(kaushikiska): https://github.com/flutter/flutter/issues/112649
  return nullptr;
}

std::shared_ptr<ComputePass> CommandBufferVK::OnCreateComputePass() const {
  // TODO(dnfield): https://github.com/flutter/flutter/issues/110622
  VALIDATION_LOG << "ComputePasses unimplemented for Vulkan";
  return nullptr;
}

}  // namespace impeller
