#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