/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ /** \file * \ingroup gpu */ #pragma once #include "gpu_context_private.hh" #include "BLI_utility_mixins.hh" #include "vk_common.hh" namespace blender::gpu { class VKContext; class VKDevice; /** * Class for handing vulkan buffers (allocation/updating/binding). */ class VKBuffer : public NonCopyable { size_t size_in_bytes_ = 0; size_t alloc_size_in_bytes_ = 0; VkBuffer vk_buffer_ = VK_NULL_HANDLE; VmaAllocation allocation_ = VK_NULL_HANDLE; VkMemoryPropertyFlags vk_memory_property_flags_; TimelineValue async_timeline_ = 0; /* Pointer to the virtually mapped memory. */ void *mapped_memory_ = nullptr; public: VKBuffer() = default; virtual ~VKBuffer(); /** Has this buffer been allocated? */ bool is_allocated() const; /** * Allocate the buffer. */ bool create(size_t size, VkBufferUsageFlags buffer_usage, VkMemoryPropertyFlags required_flags, VkMemoryPropertyFlags preferred_flags, VmaAllocationCreateFlags vma_allocation_flags); void clear(VKContext &context, uint32_t clear_value); void update_immediately(const void *data) const; void update_sub_immediately(size_t start_offset, size_t data_size, const void *data) const; /** * Update the buffer as part of the render graph evaluation. The ownership of data will be * transferred to the render graph and should have been allocated using guarded alloc. */ void update_render_graph(VKContext &context, void *data) const; void flush() const; /** * Read the buffer (synchronously). */ void read(VKContext &context, void *data) const; /** * Start a async read-back. */ void async_flush_to_host(VKContext &context); /** * Wait until the async read back is finished and fill the given data with the content of the * buffer. * * Will start a new async read-back when there is no read back in progress. */ void read_async(VKContext &context, void *data); /** * Free the buffer. * * Discards the buffer so it can be destroyed safely later. Buffers can still be used when * rendering so we can only destroy them after the rendering is completed. */ bool free(); /** * Destroy the buffer immediately. */ void free_immediately(VKDevice &device); int64_t size_in_bytes() const { return size_in_bytes_; } VkBuffer vk_handle() const { return vk_buffer_; } /** * Get the reference to the mapped memory. * * Can only be called when the buffer is (still) mapped. */ void *mapped_memory_get() const; /** * Is this buffer mapped (visible on host) */ bool is_mapped() const; private: /** Check if this buffer is mapped. */ bool map(); void unmap(); }; /** * Helper struct to enable buffers to be bound with an offset. * * Used for de-interleaved vertex input buffers and immediate mode buffers. */ struct VKBufferWithOffset { const VkBuffer buffer; VkDeviceSize offset; }; } // namespace blender::gpu