Blender V4.5
vk_vertex_buffer.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2022 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "MEM_guardedalloc.h"
10
11#include "vk_data_conversion.hh"
12#include "vk_shader.hh"
14#include "vk_staging_buffer.hh"
15#include "vk_state_manager.hh"
16#include "vk_vertex_buffer.hh"
17
18#include "CLG_log.h"
19
20static CLG_LogRef LOG = {"gpu.vulkan"};
21
22namespace blender::gpu {
23
28
30{
31 VKContext &context = *VKContext::get();
32 VKStateManager &state_manager = context.state_manager_get();
34}
35
37{
38 VKContext &context = *VKContext::get();
39 VKStateManager &state_manager = context.state_manager_get();
40 state_manager.texel_buffer_bind(*this, binding);
41}
42
47
49{
50 if (vk_buffer_view_ != VK_NULL_HANDLE) {
51 return;
52 }
53
54 VkBufferViewCreateInfo buffer_view_info = {};
55 buffer_view_info.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO;
56 buffer_view_info.buffer = buffer_.vk_handle();
57 buffer_view_info.format = to_vk_format();
58 buffer_view_info.range = buffer_.size_in_bytes();
59
60 const VKDevice &device = VKBackend::get().device;
61 vkCreateBufferView(device.vk_handle(), &buffer_view_info, nullptr, &vk_buffer_view_);
62 debug::object_label(vk_buffer_view_, "VertexBufferView");
63}
64
69
70void VKVertexBuffer::update_sub(uint start_offset, uint data_size_in_bytes, const void *data)
71{
72 if (!buffer_.is_allocated()) {
73 /* Allocating huge buffers can fail, in that case we skip copying data. */
74 return;
75 }
76 if (buffer_.is_mapped()) {
77 buffer_.update_sub_immediately(start_offset, data_size_in_bytes, data);
78 }
79 else {
80 VKContext &context = *VKContext::get();
81 VKStagingBuffer staging_buffer(
82 buffer_, VKStagingBuffer::Direction::HostToDevice, start_offset, data_size_in_bytes);
83 memcpy(staging_buffer.host_buffer_get().mapped_memory_get(), data, data_size_in_bytes);
84 staging_buffer.copy_to_device(context);
85 }
86}
87
88void VKVertexBuffer::read(void *data) const
89{
90 VKContext &context = *VKContext::get();
91 if (buffer_.is_mapped()) {
92 buffer_.read(context, data);
93 return;
94 }
95
96 /* Allocating huge buffers can fail, in that case we skip copying data. */
97 if (buffer_.is_allocated()) {
99 VKBuffer &buffer = staging_buffer.host_buffer_get();
100 if (buffer.is_mapped()) {
101 staging_buffer.copy_from_device(context);
102 staging_buffer.host_buffer_get().read(context, data);
103 }
104 else {
106 &LOG,
107 "Unable to read data from vertex buffer via a staging buffer as the staging buffer "
108 "could not be allocated. ");
109 }
110 }
111}
112
114{
116 return;
117 }
118
119 /* Discard previous data if any. */
120 /* TODO: Use mapped memory. */
122 data_ = MEM_malloc_arrayN<uchar>(this->size_alloc_get(), __func__);
123}
124
126{
128 return;
129 }
130
131 data_ = (uchar *)MEM_reallocN(data_, sizeof(uchar) * this->size_alloc_get());
132}
133
135{
136 if (vk_buffer_view_ != VK_NULL_HANDLE) {
138 vk_buffer_view_ = VK_NULL_HANDLE;
139 }
140
142}
143
144void VKVertexBuffer::upload_data_direct(const VKBuffer &host_buffer)
145{
146 host_buffer.update_immediately(data_);
147}
148
149void VKVertexBuffer::upload_data_via_staging_buffer(VKContext &context)
150{
151 VKStagingBuffer staging_buffer(buffer_, VKStagingBuffer::Direction::HostToDevice);
152 VKBuffer &buffer = staging_buffer.host_buffer_get();
153 if (buffer.is_allocated()) {
154 upload_data_direct(buffer);
155 staging_buffer.copy_to_device(context);
156 }
157 else {
159 "Unable to upload data to vertex buffer via a staging buffer as the staging buffer "
160 "could not be allocated. Vertex buffer will be filled with on zeros to reduce "
161 "drawing artifacts due to read from uninitialized memory.");
162 buffer_.clear(context, 0u);
163 }
164}
165
167{
168 if (!buffer_.is_allocated()) {
169 allocate();
170 /* If allocation fails, don't upload.*/
171 if (!buffer_.is_allocated()) {
172 CLOG_ERROR(&LOG, "Unable to allocate vertex buffer. Most likely an out of memory issue.");
173 return;
174 }
175 }
176
178 return;
179 }
180
182 if (buffer_.is_mapped() && !data_uploaded_) {
183 upload_data_direct(buffer_);
184 }
185 else {
186 VKContext &context = *VKContext::get();
187 upload_data_via_staging_buffer(context);
188 }
189 if (usage_ == GPU_USAGE_STATIC) {
191 }
192 data_uploaded_ = true;
193
196 }
197}
198
199void VKVertexBuffer::allocate()
200{
201 VkBufferUsageFlags vk_buffer_usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
202 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
203 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
204 VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT |
205 VK_BUFFER_USAGE_TRANSFER_DST_BIT;
206
207 buffer_.create(size_alloc_get(),
208 vk_buffer_usage,
209 0,
210 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
211 VmaAllocationCreateFlags(0),
212 0.8f);
213 debug::object_label(buffer_.vk_handle(), "VertexBuffer");
214}
215
216} // namespace blender::gpu
unsigned char uchar
unsigned int uint
#define ELEM(...)
#define CLOG_ERROR(clg_ref,...)
Definition CLG_log.h:182
@ GPU_VERTBUF_DATA_DIRTY
@ GPU_VERTBUF_DATA_UPLOADED
@ GPU_USAGE_STATIC
@ GPU_USAGE_STREAM
@ GPU_USAGE_DYNAMIC
@ GPU_USAGE_DEVICE_ONLY
Read Guarded memory(de)allocation.
unsigned long long int uint64_t
static VKBackend & get()
Definition vk_backend.hh:91
void update_immediately(const void *data) const
Definition vk_buffer.cc:112
bool create(size_t size, VkBufferUsageFlags buffer_usage, VkMemoryPropertyFlags required_flags, VkMemoryPropertyFlags preferred_flags, VmaAllocationCreateFlags vma_allocation_flags, float priority, bool export_memory=false)
Definition vk_buffer.cc:23
bool is_mapped() const
Definition vk_buffer.hh:141
void read(VKContext &context, void *data) const
Definition vk_buffer.cc:171
VkBuffer vk_handle() const
Definition vk_buffer.hh:102
void clear(VKContext &context, uint32_t clear_value)
Definition vk_buffer.cc:142
void * mapped_memory_get() const
Definition vk_buffer.hh:135
static VKContext * get()
VkDevice vk_handle() const
Definition vk_device.hh:336
void discard_buffer_view(VkBufferView vk_buffer_view)
static VKDiscardPool & discard_pool_get()
void copy_from_device(VKContext &context)
void copy_to_device(VKContext &context)
void texel_buffer_bind(VKVertexBuffer &vertex_buffer, int slot)
void storage_buffer_bind(BindSpaceStorageBuffers::Type resource_type, void *resource, int binding)
void update_sub(uint start, uint len, const void *data) override
void wrap_handle(uint64_t handle) override
void bind_as_ssbo(uint binding) override
void bind_as_texture(uint binding) override
void read(void *data) const override
MutableSpan< T > data()
#define MEM_SAFE_FREE(v)
#define MEM_reallocN(vmemh, len)
#define LOG(severity)
Definition log.h:32
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void object_label(GLenum type, GLuint object, const char *name)
Definition gl_debug.cc:329
static CLG_LogRef LOG
#define NOT_YET_IMPLEMENTED
Definition vk_common.hh:142