Currently all buffer types were stored in host memory, which is visible to the GPU as well. This is typically slow as the data would be transferred over the PCI bus when used. Most of the time Index and Vertex buffers are written once and read many times so it makes more sense to locate them on the GPU. Storage buffers typically require quick access as they are created for shading/compute purposes. This PR will try to store vertex buffers, index buffers and storage buffers on device memory to improve the performance. Uniform buffers are still located on host memory as they can be uploaded during binding process. This can (will) reset the graphics pipeline triggering draw calls using unattached resources. In future this could be optimized further as in: * using different pools for allocating specific buffers, with a fallback when buffers cannot be stored on the GPU anymore. * store uniform buffers in device memory Pull Request: https://projects.blender.org/blender/blender/pulls/115343
86 lines
1.8 KiB
C++
86 lines
1.8 KiB
C++
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
/** \file
|
|
* \ingroup gpu
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "gpu_context_private.hh"
|
|
|
|
#include "vk_common.hh"
|
|
|
|
namespace blender::gpu {
|
|
class VKContext;
|
|
|
|
/**
|
|
* Class for handing vulkan buffers (allocation/updating/binding).
|
|
*/
|
|
class VKBuffer {
|
|
int64_t size_in_bytes_ = 0;
|
|
VkBuffer vk_buffer_ = VK_NULL_HANDLE;
|
|
VmaAllocation allocation_ = VK_NULL_HANDLE;
|
|
/* Pointer to the virtually mapped memory. */
|
|
void *mapped_memory_ = nullptr;
|
|
|
|
public:
|
|
VKBuffer() = default;
|
|
virtual ~VKBuffer();
|
|
|
|
/** Has this buffer been allocated? */
|
|
bool is_allocated() const;
|
|
bool create(int64_t size,
|
|
GPUUsageType usage,
|
|
VkBufferUsageFlags buffer_usage,
|
|
bool is_host_visible = true);
|
|
void clear(VKContext &context, uint32_t clear_value);
|
|
void update(const void *data) const;
|
|
void flush() const;
|
|
void read(void *data) const;
|
|
bool free();
|
|
|
|
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.
|
|
*
|
|
* VKImmediate mode uses a single VKBuffer with multiple vertex layouts. Those layouts are send to
|
|
* the command buffer containing an offset.
|
|
*
|
|
* VKIndexBuffer uses this when it is a subrange of another buffer.
|
|
*/
|
|
struct VKBufferWithOffset {
|
|
const VKBuffer &buffer;
|
|
VkDeviceSize offset;
|
|
};
|
|
|
|
} // namespace blender::gpu
|