// 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.

#ifndef LIB_ESCHER_IMPL_COMMAND_BUFFER_H_
#define LIB_ESCHER_IMPL_COMMAND_BUFFER_H_

#include <functional>
#include <vector>

#include <lib/fit/function.h>

#include "lib/escher/forward_declarations.h"
#include "lib/escher/renderer/semaphore.h"
#include "lib/escher/scene/camera.h"
#include "lib/escher/vk/vulkan_context.h"
#include "lib/fxl/macros.h"

namespace escher {
typedef fit::function<void()> CommandBufferFinishedCallback;

namespace impl {

// CommandBuffer is a wrapper around vk::CommandBuffer.  Vulkan forbids the
// client application from destroying any resources while they are used by
// any "pending command buffers" (i.e. those that have not finished executing
// on the GPU).
//
// CommandBuffers are obtained from a CommandBufferPool, and is automatically
// returned to it when all GPU-work is finished.
//
// Not thread-safe.
//
// TODO(ES-77): RenderPass and Framebuffer are deprecated, to be replaced by
// impl::RenderPass and impl::Framebuffer.  The latter two aren't visible to
// Escher clients; they are an implementation detail of escher::CommandBuffer
// (NOTE: NOT escher::impl::CommandBuffer, which is also deprecated).
class CommandBuffer {
 public:
  ~CommandBuffer();

  vk::CommandBuffer vk() const { return command_buffer_; }

  // Return true if successful.  The callback will be invoked after all commands
  // have finished executing on the GPU (there is no guarantee about how long
  // afterward: this depends on when the CommandBufferPool that owns this buffer
  // calls Retire()).
  bool Submit(vk::Queue queue, CommandBufferFinishedCallback callback);

  // During Submit(), these semaphores will be added to the vk::SubmitInfo.
  // No-op if semaphore is null.
  void AddWaitSemaphore(SemaphorePtr semaphore, vk::PipelineStageFlags stage);

  // For convenience, calls TakeWaitSemaphore() on the resource, and passes the
  // result to AddWaitSemaphore().
  template <typename ResourcePtrT>
  void TakeWaitSemaphore(const ResourcePtrT& resource,
                         vk::PipelineStageFlags stage) {
    AddWaitSemaphore(resource->TakeWaitSemaphore(), stage);
  }

  // During Submit(), these semaphores will be added to the vk::SubmitInfo.
  // No-op if semaphore is null.
  void AddSignalSemaphore(SemaphorePtr semaphore);

  // These resources will be retained until the command-buffer is finished
  // running on the GPU.
  void KeepAlive(Resource* resource);
  template <typename ResourceT>
  void KeepAlive(const fxl::RefPtr<ResourceT>& ptr) {
    KeepAlive(ptr.get());
  }

  // Bind index/vertex buffers and write draw command.
  // Retain mesh in used_resources.
  void DrawMesh(const MeshPtr& mesh);

  // Copy pixels from one image to another.  No image barriers or other
  // synchronization is used.  Retain both images in used_resources.
  void CopyImage(const ImagePtr& src_image, const ImagePtr& dst_image,
                 vk::ImageLayout src_layout, vk::ImageLayout dst_layout,
                 vk::ImageCopy* region);

  // Copy memory from one buffer to another.
  void CopyBuffer(const BufferPtr& src, const BufferPtr& dst,
                  vk::BufferCopy region);

  // Copy the specified region of |src| into |dst| after inserting a
  // memory-barrier to use the memory on the same queue (i.e. the barrier's
  // queue family indices are VK_QUEUE_FAMILY_IGNORED).
  void CopyBufferAfterBarrier(const BufferPtr& src, const BufferPtr& dst,
                              vk::BufferCopy region,
                              vk::AccessFlags src_access_mask,
                              vk::PipelineStageFlags src_stage_mask);

  // Transition the image between the two layouts; see section 11.4 of the
  // Vulkan spec.  Retain image in used_resources.
  void TransitionImageLayout(const ImagePtr& image, vk::ImageLayout old_layout,
                             vk::ImageLayout new_layout);

  // Convenient way to begin a render-pass that renders to the whole framebuffer
  // (i.e. width/height of viewport and scissors are obtained from framebuffer).
  void BeginRenderPass(const escher::RenderPassPtr& render_pass,
                       const escher::FramebufferPtr& framebuffer,
                       const std::vector<vk::ClearValue>& clear_values,
                       const vk::Rect2D viewport);
  void BeginRenderPass(vk::RenderPass render_pass,
                       const escher::FramebufferPtr& framebuffer,
                       const std::vector<vk::ClearValue>& clear_values,
                       const vk::Rect2D viewport);
  void BeginRenderPass(vk::RenderPass render_pass,
                       const escher::FramebufferPtr& framebuffer,
                       const vk::ClearValue* clear_values,
                       size_t clear_value_count, const vk::Rect2D viewport);

  // Simple wrapper around endRenderPass().
  void EndRenderPass();

  // Block until the command-buffer is no longer pending, or the specified
  // number of nanoseconds has elapsed.  Return vk::Result::eSuccess in the
  // former case, and vk::Result::eTimeout in the latter.
  vk::Result Wait(uint64_t timeout_nanoseconds);

  // Each CommandBuffer that is obtained from a CommandBufferPool is given a
  // monotonically-increasing sequence number.  This number is globally unique
  // (per Escher instance), even across multiple CommandBufferPools.
  uint64_t sequence_number() const { return sequence_number_; }

 private:
  friend class CommandBufferPool;

  // Called by CommandBufferPool, which is responsible for eventually destroying
  // the Vulkan command buffer and fence.  Submit() and Retire() use the fence
  // to determine when the command buffer has finished executing on the GPU.
  CommandBuffer(vk::Device device, vk::CommandBuffer command_buffer,
                vk::Fence fence, vk::PipelineStageFlags pipeline_stage_mask);
  vk::Fence fence() const { return fence_; }

  // Called by CommandBufferPool when this buffer is obtained from it.
  void Begin(uint64_t sequence_number);

  // Called by CommandBufferPool, to attempt to reset the buffer for reuse.
  // Return false and do nothing if the buffer's submission fence is not ready.
  bool Retire();

  const vk::Device device_;
  const vk::CommandBuffer command_buffer_;
  const vk::Fence fence_;
  const vk::PipelineStageFlags pipeline_stage_mask_;

  std::vector<SemaphorePtr> wait_semaphores_;
  std::vector<vk::PipelineStageFlags> wait_semaphore_stages_;
  std::vector<vk::Semaphore> wait_semaphores_for_submit_;

  std::vector<SemaphorePtr> signal_semaphores_;
  std::vector<vk::Semaphore> signal_semaphores_for_submit_;

  bool is_active_ = false;
  bool is_submitted_ = false;

  uint64_t sequence_number_ = 0;

  CommandBufferFinishedCallback callback_;

  FXL_DISALLOW_COPY_AND_ASSIGN(CommandBuffer);
};

}  // namespace impl
}  // namespace escher

#endif  // LIB_ESCHER_IMPL_COMMAND_BUFFER_H_
