/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ #pragma once #define CRASH_ON_MULTIPLE_MAPPINGS_TO_SAME_ALLOCATION #include "MemoryAllocation.hpp" #include #include namespace OpenVulkano::Vulkan { struct ManagedBuffer { using Ptr = std::unique_ptr>; MemoryAllocation* allocation; vk::DeviceSize offset, size; vk::Buffer buffer; vk::BufferUsageFlags usage; vk::MemoryPropertyFlags properties; void* mapped = nullptr; ~ManagedBuffer() { allocation->device.destroy(buffer); } [[nodiscard]] bool IsLast() const { return (offset + size == allocation->used); } [[nodiscard]] bool IsMapped() const { return mapped || allocation->mapped; } /** * \brief Maps the buffer into the memory of the host. * \tparam T The type of the buffers data. * \param offset The offset from where to map the buffer. * \param size The size to be mapped. VK_WHOLE_SIZE to map the whole buffer. * \pparam longTermMapping If the mapping is intended to be held long term. Short term mappings must be freed before mapping a different region in the same memory allocation for them to work reliable with all drivers. * \return The pointer to the mapped buffer. */ template T* Map(size_t offset = 0, vk::DeviceSize size = VK_WHOLE_SIZE, bool longTermMapping = true) { if (!mapped) { if (allocation->mapped || longTermMapping) { mapped = static_cast(allocation->Map()) + offset + this->offset; } else { if (size == VK_WHOLE_SIZE) size = this->size; mapped = allocation->MapChild(this->offset + offset, size); } } return static_cast(mapped); } /** * \brief Un-maps the buffer from the host. */ void UnMap() { if (mapped) { if (allocation->mapped) { allocation->UnMap(); } else { allocation->UnMapChild(); } mapped = nullptr; } } void Copy(void* data) { if (mapped) { memcpy(mapped, data, size); } else { void* dataMapped = Map(0, VK_WHOLE_SIZE, false); memcpy(dataMapped, data, size); UnMap(); } } void Copy(const void* data, uint32_t size, uint32_t offset) { if(mapped) memcpy(static_cast(mapped) + offset, data, size); else { void* dataMapped = Map(offset, size, false); memcpy(dataMapped, data, size); UnMap(); } } }; }