#pragma once /** * @authors Tobias Frisch, Lars Hoerttrich, Alexander Gauggel * @file vkcv/Buffer.hpp * @brief Template buffer class for type security with buffers. */ #include "BufferTypes.hpp" #include "Container.hpp" #include "Core.hpp" #include "Handles.hpp" namespace vkcv { /** * @brief Template class for buffer handling and filling data. * * @tparam T Buffer content type */ template <typename T> class Buffer { public: Buffer() : m_core(nullptr), m_handle() {} Buffer(Core* core, const BufferHandle &handle) : m_core(core), m_handle(handle) {} Buffer(const Buffer &other) = default; Buffer(Buffer &&other) noexcept = default; ~Buffer() = default; Buffer &operator=(const Buffer &other) = default; Buffer &operator=(Buffer &&other) noexcept = default; /** * @brief Returns the buffers handle. * * @return The #BufferHandle to be used with the #Core */ [[nodiscard]] const BufferHandle &getHandle() const { return m_handle; } /** * @brief Returns the type of the buffer. * * @return The #BufferType of the #Buffer */ [[nodiscard]] BufferType getType() const { return m_core->getBufferType(m_handle); }; [[nodiscard]] BufferMemoryType getMemoryType() const { return m_core->getBufferMemoryType(m_handle); } /** * @brief Returns the stride of elements in the buffer. * * Beware that this returned value is only the correct * stride for this buffer if it is used tightly packed * storing elements of type T. * * @return The likely stride of the #Buffer using type T */ [[nodiscard]] size_t getStride() const { return sizeof(T); } /** * @brief Returns the count of elements in the buffer. * * @return The number of objects of type T the #Buffer holds */ [[nodiscard]] size_t getCount() const { return m_core->getBufferSize(m_handle) / sizeof(T); } /** * @brief Returns the size of the buffer in bytes. * * @return The size of the #Buffer in bytes */ [[nodiscard]] size_t getSize() const { return m_core->getBufferSize(m_handle); } /** * @brief Returns the vulkan buffer handle of the buffer. * * @return The vulkan handle of the #Buffer to be used for manual vulkan commands */ [[nodiscard]] vk::Buffer getVulkanHandle() const { return m_core->getBuffer(m_handle); } /** * @brief Fills the #Buffer with data of type T. * * @param[in] data Pointer to the array of object type T * @param[in] count The number of objects to copy from the data array * @param[in] offset The offset into the #Buffer where the data is copied into */ void fill(const T* data, size_t count = 0, size_t offset = 0) { m_core->fillBuffer(m_handle, data, count * sizeof(T), offset * sizeof(T)); } /** * @brief Fills the #Buffer with data from a vector of type T. * * @param vector Vector of type T to be copied into the #Buffer * @param offset The offset into the #Buffer where the data is copied into */ void fill(const Vector<T> &vector, size_t offset = 0) { fill(static_cast<const T*>(vector.data()), static_cast<size_t>(vector.size()), offset); } /** * @brief Fills the #Buffer with data from an array of type T * and size N. * * @tparam N Size of the array to be copied into the #Buffer * @param array Array of type T to be copied into the #Buffer * @param offset The offset into the #Buffer where the data is copied into */ template<size_t N> void fill(const std::array<T, N> &array, size_t offset = 0) { fill(static_cast<const T*>(array.data()), N, offset); } /** * @brief Reads the #Buffer directly into a data pointer of type T. * * @param[in] data Pointer to the array of object type T * @param[in] count The number of objects to copy from the buffer * @param[in] offset The offset into the #Buffer where the data is copied from */ void read(T* data, size_t count = 0, size_t offset = 0) { m_core->readBuffer(m_handle, data, count * sizeof(T), offset * sizeof(T)); } /** * @brief Reads the #Buffer directly to a vector of type T. * * @param vector Vector of type T to be copied into from the #Buffer * @param offset The offset into the #Buffer where the data is copied from */ void read(Vector<T> &vector, size_t offset = 0) { read(static_cast<T*>(vector.data()), static_cast<size_t>(vector.size()), offset); } /** * @brief Maps memory to the #Buffer and returns it. * * @param[in] offset Offset of mapping in objects of type T * @param[in] count Count of objects of type T that are mapped * @return Pointer to mapped memory as type T */ [[nodiscard]] T* map(size_t offset = 0, size_t count = 0) { return reinterpret_cast<T*>( m_core->mapBuffer(m_handle, offset * sizeof(T), count * sizeof(T))); } /** * @brief Unmaps the #Buffer, invalidates the pointer obtained by map(). */ void unmap() { m_core->unmapBuffer(m_handle); } private: Core* m_core; BufferHandle m_handle; }; template <typename T> Buffer<T> buffer(Core &core, BufferType type, size_t count, BufferMemoryType memoryType = BufferMemoryType::DEVICE_LOCAL, bool readable = false) { return Buffer<T>(&core, core.createBuffer(type, typeGuard<T>(), count, memoryType, readable)); } template <typename T> VertexBufferBinding vertexBufferBinding(const Buffer<T>& buffer) { return vertexBufferBinding(buffer.getHandle(), buffer.getStride()); } } // namespace vkcv