Blender V5.0
vk_immediate.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11#include "GPU_capabilities.hh"
12#include "GPU_matrix.hh"
13
14#include "vk_backend.hh"
15#include "vk_context.hh"
16#include "vk_framebuffer.hh"
17#include "vk_immediate.hh"
18#include "vk_state_manager.hh"
19
20#include "CLG_log.h"
21
22namespace blender::gpu {
23
24static CLG_LogRef LOG = {"gpu.vulkan"};
25
27{
28 uint add_vertex = prim_type == GPU_PRIM_LINE_LOOP ? 1 : 0;
29 const size_t bytes_needed = vertex_buffer_size(&vertex_format, vertex_len + add_vertex);
30 size_t offset_alignment = GPU_storage_buffer_alignment();
31 VKBuffer &buffer = ensure_space(bytes_needed, offset_alignment);
32
33 /* Apply alignment when allocating new sub buffer, to reduce signed/unsigned data conversion
34 * later on. */
35 buffer_offset_ += offset_alignment - 1;
36 buffer_offset_ &= ~(offset_alignment - 1);
37 BLI_assert((buffer_offset_ & (offset_alignment - 1)) == 0);
38
39 current_subbuffer_len_ = bytes_needed;
40 uchar *data = static_cast<uchar *>(buffer.mapped_memory_get());
41 return data + buffer_offset_;
42}
43
45{
46 BLI_assert_msg(prim_type != GPU_PRIM_NONE, "Illegal state: not between an immBegin/End pair.");
47 if (vertex_idx == 0) {
48 return;
49 }
50
52 uchar *first_vertex_ptr = static_cast<uchar *>(active_buffer_->mapped_memory_get()) +
53 buffer_offset_;
54 size_t vertex_stride = current_subbuffer_len_ / (vertex_len + 1);
55 uchar *last_vertex_ptr = first_vertex_ptr + vertex_stride * vertex_len;
56 memcpy(last_vertex_ptr, first_vertex_ptr, vertex_stride);
57
59 vertex_idx += 1;
60 }
61
62 VKContext &context = *VKContext::get();
63 BLI_assert(context.shader == shader);
64 Shader &shader = *this->shader;
65 if (shader.is_polyline) {
66 VKBuffer &buffer = active_buffer_.value();
67 VKStateManager &state_manager = context.state_manager_get();
69 &buffer,
71 buffer_offset_);
73 &buffer,
75 buffer_offset_);
76 /* Not used. Satisfy the binding. */
77 state_manager.storage_buffer_bind(
80 }
81 else {
82 GPU_matrix_bind(context.shader);
83 render_graph::VKResourceAccessInfo &resource_access_info = context.reset_and_get_access_info();
84 vertex_attributes_.update_bindings(*this);
85 context.active_framebuffer_get()->rendering_ensure(context);
86
87 render_graph::VKDrawNode::CreateInfo draw(resource_access_info);
88 draw.node_data.vertex_count = vertex_idx;
89 draw.node_data.instance_count = 1;
90 draw.node_data.first_vertex = 0;
91 draw.node_data.first_instance = 0;
92
93 context.active_framebuffer_get()->vk_viewports_append(
94 draw.node_data.graphics.viewport.viewports);
95 context.active_framebuffer_get()->vk_render_areas_append(
96 draw.node_data.graphics.viewport.scissors);
97
98 vertex_attributes_.bind(draw.node_data.vertex_buffers);
99 context.update_pipeline_data(prim_type, vertex_attributes_, draw.node_data.graphics);
100
101 context.render_graph().add_node(draw);
102 }
103
104 buffer_offset_ += current_subbuffer_len_;
105 current_subbuffer_len_ = 0;
106}
107
108VKBufferWithOffset VKImmediate::active_buffer() const
109{
110 VKBufferWithOffset result = {active_buffer_->vk_handle(), buffer_offset_};
111 return result;
112}
113
114VkDeviceSize VKImmediate::buffer_bytes_free()
115{
116 return active_buffer_->size_in_bytes() - buffer_offset_;
117}
118
119static VkDeviceSize new_buffer_size(VkDeviceSize sub_buffer_size)
120{
121 return max_ulul(sub_buffer_size, DEFAULT_INTERNAL_BUFFER_SIZE);
122}
123
124VKBuffer &VKImmediate::ensure_space(VkDeviceSize bytes_needed, VkDeviceSize offset_alignment)
125{
126 VkDeviceSize bytes_required = bytes_needed + offset_alignment;
127
128 /* Last used buffer still has space. */
129 if (active_buffer_.has_value() && buffer_bytes_free() >= bytes_required) {
130 return active_buffer_.value();
131 }
132
133 /* Offset alignment isn't needed when creating buffers as it is managed by VMA. */
134 VkDeviceSize alloc_size = new_buffer_size(bytes_needed);
136 "Immediate buffer cannot hold another %d bytes, it contains %d bytes. A new "
137 "buffer will be allocated (size=%d)",
138 int(bytes_required),
139 int(buffer_offset_),
140 int(alloc_size));
141 buffer_offset_ = 0;
142 VKBuffer &result = active_buffer_.emplace();
143 result.create(alloc_size,
144 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
145 VK_BUFFER_USAGE_TRANSFER_DST_BIT,
146 VMA_MEMORY_USAGE_AUTO_PREFER_HOST,
147 VMA_ALLOCATION_CREATE_MAPPED_BIT |
148 VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
149 0.8);
150 debug::object_label(result.vk_handle(), "Immediate");
151
152 return result;
153}
154
155} // namespace blender::gpu
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
unsigned char uchar
unsigned int uint
#define CLOG_TRACE(clg_ref,...)
Definition CLG_log.h:192
size_t GPU_storage_buffer_alignment()
void GPU_matrix_bind(blender::gpu::Shader *shader)
@ GPU_PRIM_LINE_LOOP
@ GPU_PRIM_NONE
@ GPU_PRIM_LINE_STRIP
BMesh const char void * data
void polyline_draw_workaround(uint64_t offset)
void * mapped_memory_get() const
Definition vk_buffer.hh:134
static VKContext * get()
uchar * begin() override
void storage_buffer_bind(BindSpaceStorageBuffers::Type resource_type, void *resource, int binding)
#define GPU_SSBO_POLYLINE_POS_BUF_SLOT
#define GPU_SSBO_POLYLINE_COL_BUF_SLOT
#define GPU_SSBO_INDEX_BUF_SLOT
uint vertex_buffer_size(const GPUVertFormat *format, uint vertex_len)
#define LOG(level)
Definition log.h:97
MINLINE unsigned long long max_ulul(unsigned long long a, unsigned long long b)
void object_label(GLenum type, GLuint object, const char *name)
Definition gl_debug.cc:329
constexpr size_t DEFAULT_INTERNAL_BUFFER_SIZE
static CLG_LogRef LOG
static VkDeviceSize new_buffer_size(VkDeviceSize sub_buffer_size)