// 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 "flutter/vulkan/vulkan_command_buffer.h"

#include "flutter/vulkan/vulkan_proc_table.h"

namespace vulkan {

VulkanCommandBuffer::VulkanCommandBuffer(
    const VulkanProcTable& p_vk,
    const VulkanHandle<VkDevice>& device,
    const VulkanHandle<VkCommandPool>& pool)
    : vk(p_vk), device_(device), pool_(pool), valid_(false) {
  const VkCommandBufferAllocateInfo allocate_info = {
      .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
      .pNext = nullptr,
      .commandPool = pool_,
      .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
      .commandBufferCount = 1,
  };

  VkCommandBuffer buffer = VK_NULL_HANDLE;

  if (VK_CALL_LOG_ERROR(vk.AllocateCommandBuffers(device_, &allocate_info,
                                                  &buffer)) != VK_SUCCESS) {
    FML_DLOG(INFO) << "Could not allocate command buffers.";
    return;
  }

  auto buffer_collect = [this](VkCommandBuffer buffer) {
    vk.FreeCommandBuffers(device_, pool_, 1, &buffer);
  };

  handle_ = {buffer, buffer_collect};

  valid_ = true;
}

VulkanCommandBuffer::~VulkanCommandBuffer() = default;

bool VulkanCommandBuffer::IsValid() const {
  return valid_;
}

VkCommandBuffer VulkanCommandBuffer::Handle() const {
  return handle_;
}

bool VulkanCommandBuffer::Begin() const {
  const VkCommandBufferBeginInfo info{
      .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
      .pNext = nullptr,
      .flags = 0,
      .pInheritanceInfo = nullptr,
  };

  return VK_CALL_LOG_ERROR(vk.BeginCommandBuffer(handle_, &info)) == VK_SUCCESS;
}

bool VulkanCommandBuffer::End() const {
  return VK_CALL_LOG_ERROR(vk.EndCommandBuffer(handle_)) == VK_SUCCESS;
}

bool VulkanCommandBuffer::InsertPipelineBarrier(
    VkPipelineStageFlagBits src_stage_flags,
    VkPipelineStageFlagBits dest_stage_flags,
    uint32_t /* mask of VkDependencyFlagBits */ dependency_flags,
    uint32_t memory_barrier_count,
    const VkMemoryBarrier* memory_barriers,
    uint32_t buffer_memory_barrier_count,
    const VkBufferMemoryBarrier* buffer_memory_barriers,
    uint32_t image_memory_barrier_count,
    const VkImageMemoryBarrier* image_memory_barriers) const {
  vk.CmdPipelineBarrier(handle_, src_stage_flags, dest_stage_flags,
                        dependency_flags, memory_barrier_count, memory_barriers,
                        buffer_memory_barrier_count, buffer_memory_barriers,
                        image_memory_barrier_count, image_memory_barriers);
  return true;
}

}  // namespace vulkan
