Newer
Older
ForwardPlusRenderer / include / Buffer / Buffer.h
#pragma once
#include <stdafx.h>
namespace fpr
{
/**
 * @brief Holds some essential information for data transfer between the CPU and GPU.
 * Data transfer between GPU and CPU in Vulkan is not trivial and several important decisions
 * need to be made for data transfer.
 *
 * Different use cases for buffers range from index buffers to buffers that hold culled light indices.
 * Thus, it is evident that their access requirements differ, which is what is handled through this class.
 */
class Buffer
{
  /**
   * @brief The size of the buffer in bytes.
   */
  vk::DeviceSize m_buffer_size;

  /**
   * @brief RAII handle for a VkBuffer.
   */
  vk::UniqueBuffer m_buffer;

  /**
   * @brief RAII handle for VkDeviceMemory.
   */
  vk::UniqueDeviceMemory m_memory;

  /**
   * @brief Buffer information used for descriptor sets. Primarily concerns shaders.
   */
  vk::DescriptorBufferInfo m_buffer_info;
  /**
   * @brief Alignment of buffer data. Mostly irrelevant, though important when _aligned_malloc() is used.
   */
  vk::DeviceSize m_alignment = 0;
  /**
   * @brief Denotes what the buffer will be used for, i.e index buffer or vertex buffer and so on.
   */
  vk::BufferUsageFlags m_usage;
  /**
   * @brief A buffer's held data may not be always available to the CPU intentionally to increase GPU access speed,
   * amongst other performance concerns. See Vulkan documentation for further details.
   */
  vk::MemoryPropertyFlags m_memory_flags;
  /**
   * @brief Raw pointer to the data held on the GPU. In this engine, most data is persistently mapped.
   */
  void* mapped_data = nullptr;
public:
  /**
   * @brief Copy constructor for a buffer is deleted. A buffer must never be copied directly like this, as they contain
   * unique handles for Vulkan objects.
   */
  Buffer(Buffer& other) = delete;


  Buffer() = default;

  /**
   * @brief Parameterised constructor for a buffer.
   *
   * \param buffer_size Size of the buffer in bytes.
   * \param usage_flags Purpose of the buffer, passed as a mask. A buffer can be a transfer buffer, index buffer and so
   * on. Refer to Vulkan docs. \param mem_flags Memory properties of the buffer being used. Passed as a mask. Denotes
   * whether a buffer is meant to be readily available to the CPU amongst other options.
   */
  Buffer(vk::DeviceSize buffer_size, vk::BufferUsageFlags usage_flags, vk::MemoryPropertyFlags mem_flags);

  virtual ~Buffer();
  /**
   * @brief Getter for the buffer size private member.
   *
   * \return Size in bytes of buffer. @see m_buffer_size
   */
  [[nodiscard]] vk::DeviceSize GetSize();

  /**
   * @brief Getter for the VkBuffer private member.
   *
   * \return Reference to the VkBuffer held in the unique handle. @see m_buffer
   */
  [[nodiscard]] vk::Buffer& GetBuffer();

  /**
   * @brief Like the copy constructor, the copy assigment operator is also deleted due to identical reasoning
   */
  Buffer operator=(const Buffer& other) = delete;

  /**
   * @brief Transfer this buffer into another through the use of an intermediary staging buffer.
   * This should be used instead in almost all cases where one would wish to copy a buffer.
   *
   * \param other The destination buffer that will hold the data of the current data.
   */
  void Transfer(Buffer* other);

  /**
   * @brief Does not validate the given data for size. Simply copies the new data and overwrites the currently mapped
   * data.
   *
   * \param new_data The data that will overwrite the currently mapped data held by the buffer.
   */
  void Update(const void* new_data);

  /**
   * @brief Flushes the mapped memory. Used when the buffer is updated and released to ensure the buffer is in a valid
   * state between synchronisation.
   */
  void Flush();

  /**
   * @brief Getter for private member holding the raw data of the buffer. @see m_mapped
   *
   * \return raw untyped pointer to the mapped data. Use with caution.
   */
  [[nodiscard]] void* GetMapped();
};
} // namespace fpr