Blender V4.3
vk_vertex_attribute_object.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
6
7#include "vk_batch.hh"
8#include "vk_context.hh"
9#include "vk_immediate.hh"
10#include "vk_shader.hh"
12#include "vk_vertex_buffer.hh"
13
14#include "BLI_bit_vector.hh"
16
17namespace blender::gpu {
22
24{
25 is_valid = false;
26 info.pNext = nullptr;
27 bindings.clear();
28 attributes.clear();
29 vbos.clear();
30 buffers.clear();
31}
32
34{
35 if (this == &other) {
36 return *this;
37 }
38
39 is_valid = other.is_valid;
40 info = other.info;
41 bindings.clear();
42 bindings.extend(other.bindings);
43 attributes.clear();
44 attributes.extend(other.attributes);
45 vbos.clear();
46 vbos.extend(other.vbos);
47 buffers.clear();
48 buffers.extend(other.buffers);
49 return *this;
50}
51
52/* -------------------------------------------------------------------- */
55
57 render_graph::VKVertexBufferBindings &r_vertex_buffer_bindings) const
58{
59 BitVector visited_bindings(bindings.size());
60
62 for (VkVertexInputAttributeDescription attribute : attributes) {
63 if (visited_bindings[attribute.binding]) {
64 continue;
65 }
66 visited_bindings[attribute.binding].set(true);
67
68 VkBuffer buffer = dummy.vk_handle();
69 VkDeviceSize offset = 0;
70
71 if (attribute.binding < buffers.size()) {
72 buffer = buffers[attribute.binding].buffer;
73 offset = buffers[attribute.binding].offset;
74 }
75
76 r_vertex_buffer_bindings.buffer[attribute.binding] = buffer;
77 r_vertex_buffer_bindings.offset[attribute.binding] = offset;
78 r_vertex_buffer_bindings.buffer_count = max_ii(r_vertex_buffer_bindings.buffer_count,
79 attribute.binding + 1);
80 }
81}
82
84
85/* -------------------------------------------------------------------- */
88
90{
91 clear();
92 const VKShaderInterface &interface = unwrap(context.shader)->interface_get();
93 AttributeMask occupied_attributes = 0;
94
95 for (int v = 0; v < GPU_BATCH_INST_VBO_MAX_LEN; v++) {
96 VKVertexBuffer *vbo = batch.instance_buffer_get(v);
97 if (vbo) {
100 vbo,
101 nullptr,
102 vbo->vertex_len,
103 interface,
104 occupied_attributes,
105 true);
106 }
107 }
108 for (int v = 0; v < GPU_BATCH_VBO_MAX_LEN; v++) {
109 VKVertexBuffer *vbo = batch.vertex_buffer_get(v);
110 if (vbo) {
113 vbo,
114 nullptr,
115 vbo->vertex_len,
116 interface,
117 occupied_attributes,
118 false);
119 }
120 }
121
122 if (occupied_attributes != interface.enabled_attr_mask_) {
123 fill_unused_bindings(interface, occupied_attributes);
124 }
125 is_valid = true;
126}
127
128/* Determine the number of binding location the given attribute uses. */
130{
131 return ceil_division(attribute.comp_len, 4u);
132}
133
134/* Determine the number of binding location the given type uses. */
136{
137 switch (type) {
168 return 1;
170 return 3;
172 return 4;
173 }
174
175 return 1;
176}
177
178void VKVertexAttributeObject::fill_unused_bindings(const VKShaderInterface &interface,
179 const AttributeMask occupied_attributes)
180{
181 for (int location : IndexRange(16)) {
182 AttributeMask location_mask = 1 << location;
183 /* Skip occupied slots */
184 if (occupied_attributes & location_mask) {
185 continue;
186 }
187 /* Skip slots that are not used by the vertex shader. */
188 if ((interface.enabled_attr_mask_ & location_mask) == 0) {
189 continue;
190 }
191
192 /* Use dummy binding. */
193 shader::Type attribute_type = interface.get_attribute_type(location);
194 const uint32_t num_locations = to_binding_location_len(attribute_type);
195 for (const uint32_t location_offset : IndexRange(num_locations)) {
196 const uint32_t binding = bindings.size();
197 VkVertexInputAttributeDescription attribute_description = {};
198 attribute_description.binding = binding;
199 attribute_description.location = location + location_offset;
200 attribute_description.offset = 0;
201 attribute_description.format = to_vk_format(attribute_type);
202 attributes.append(attribute_description);
203
204 VkVertexInputBindingDescription vk_binding_descriptor = {};
205 vk_binding_descriptor.binding = binding;
206 vk_binding_descriptor.stride = 0;
207 vk_binding_descriptor.inputRate = VK_VERTEX_INPUT_RATE_INSTANCE;
208 bindings.append(vk_binding_descriptor);
209 }
210 }
211}
212
214{
215 clear();
216 const VKShaderInterface &interface = unwrap(unwrap(immediate.shader))->interface_get();
217 AttributeMask occupied_attributes = 0;
218
219 VKBufferWithOffset immediate_buffer = immediate.active_buffer();
220 update_bindings(immediate.vertex_format_converter.device_format_get(),
221 nullptr,
222 &immediate_buffer,
223 immediate.vertex_len,
224 interface,
225 occupied_attributes,
226 false);
227 is_valid = true;
228 BLI_assert(interface.enabled_attr_mask_ == occupied_attributes);
229}
230
232 VKVertexBuffer *vertex_buffer,
233 VKBufferWithOffset *immediate_vertex_buffer,
234 const int64_t vertex_len,
236 AttributeMask &r_occupied_attributes,
237 const bool use_instancing)
238{
239 BLI_assert(vertex_buffer || immediate_vertex_buffer);
240 BLI_assert(!(vertex_buffer && immediate_vertex_buffer));
241
242 if (vertex_format.attr_len <= 0) {
243 return;
244 }
245
246 /* Interleaved offset is added to the buffer binding. Attribute offsets are hardware
247 * restricted (ref: VUID-VkVertexInputAttributeDescription-offset-00622). */
248 uint32_t buffer_offset = 0;
249 uint32_t attribute_offset = 0;
250 uint32_t stride = vertex_format.stride;
251
252 bool add_vbo = false;
253
254 for (uint32_t attribute_index = 0; attribute_index < vertex_format.attr_len; attribute_index++) {
255 const GPUVertAttr &attribute = vertex_format.attrs[attribute_index];
256 if (vertex_format.deinterleaved) {
257 buffer_offset += ((attribute_index == 0) ? 0 :
258 vertex_format.attrs[attribute_index - 1].size) *
259 vertex_len;
260 stride = attribute.size;
261 }
262 else {
263 attribute_offset = attribute.offset;
264 }
265
266 for (uint32_t name_index = 0; name_index < attribute.name_len; name_index++) {
267 const char *name = GPU_vertformat_attr_name_get(&vertex_format, &attribute, name_index);
268 const ShaderInput *shader_input = interface.attr_get(name);
269 if (shader_input == nullptr || shader_input->location == -1) {
270 continue;
271 }
272
273 /* Don't overwrite attributes that are already occupied. */
274 AttributeMask attribute_mask = 1 << shader_input->location;
275 if (r_occupied_attributes & attribute_mask) {
276 continue;
277 }
278 r_occupied_attributes |= attribute_mask;
279 const uint32_t num_locations = to_binding_location_len(attribute);
280 for (const uint32_t location_offset : IndexRange(num_locations)) {
281 const uint32_t binding = bindings.size();
282 VkVertexInputAttributeDescription attribute_description = {};
283 attribute_description.binding = binding;
284 attribute_description.location = shader_input->location + location_offset;
285 attribute_description.offset = attribute_offset + location_offset * sizeof(float4);
286 attribute_description.format = to_vk_format(
287 static_cast<GPUVertCompType>(attribute.comp_type),
289 static_cast<GPUVertFetchMode>(attribute.fetch_mode));
290 attributes.append(attribute_description);
291
292 VkVertexInputBindingDescription vk_binding_descriptor = {};
293 vk_binding_descriptor.binding = binding;
294 vk_binding_descriptor.stride = stride;
295 vk_binding_descriptor.inputRate = use_instancing ? VK_VERTEX_INPUT_RATE_INSTANCE :
296 VK_VERTEX_INPUT_RATE_VERTEX;
297 bindings.append(vk_binding_descriptor);
298 if (vertex_buffer) {
299 add_vbo = true;
300 vertex_buffer->upload();
301 buffers.append({vertex_buffer->vk_handle(), buffer_offset});
302 }
303 if (immediate_vertex_buffer) {
304 buffers.append(*immediate_vertex_buffer);
305 }
306 }
307 }
308 }
309
310 if (add_vbo) {
311 BLI_assert(vertex_buffer != nullptr);
312 vbos.append(vertex_buffer);
313 }
314}
315
317
318/* -------------------------------------------------------------------- */
321
323{
324 std::cout << __FILE__ << "::" << __func__ << "\n";
325 BitVector visited_bindings(bindings.size());
326
327 for (VkVertexInputAttributeDescription attribute : attributes) {
328 std::cout << " - attribute(binding=" << attribute.binding
329 << ", location=" << attribute.location << ")";
330
331 if (visited_bindings[attribute.binding]) {
332 std::cout << " WARNING: Already bound\n";
333 continue;
334 }
335 visited_bindings[attribute.binding].set(true);
336
337 if (attribute.binding < vbos.size()) {
338 std::cout << " Attach to Buffer\n";
339 }
340 else {
341 std::cout << " WARNING: Attach to dummy\n";
342 }
343 }
344}
345
347
348} // namespace blender::gpu
#define BLI_assert(a)
Definition BLI_assert.h:50
MINLINE int max_ii(int a, int b)
#define GPU_BATCH_INST_VBO_MAX_LEN
Definition GPU_batch.hh:33
#define GPU_BATCH_VBO_MAX_LEN
Definition GPU_batch.hh:32
BLI_INLINE const char * GPU_vertformat_attr_name_get(const GPUVertFormat *format, const GPUVertAttr *attr, uint n_idx)
GPUVertFetchMode
GPUVertCompType
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its and value channels Color Retrieve a color attribute
ATTR_WARN_UNUSED_RESULT const BMVert * v
const ShaderInput * attr_get(const char *name) const
static VKBackend & get()
Definition vk_backend.hh:92
VkBuffer vk_handle() const
Definition vk_buffer.hh:69
VKVertexAttributeObject & operator=(const VKVertexAttributeObject &other)
Vector< VkVertexInputAttributeDescription > attributes
void update_bindings(const VKContext &context, VKBatch &batch)
VkPipelineVertexInputStateCreateInfo info
Vector< VkVertexInputBindingDescription > bindings
void bind(render_graph::VKVertexBufferBindings &r_vertex_buffer_bindings) const
const GPUVertFormat & device_format_get() const
struct @157336070235062372277311340362362342103123126032::@262166344314164341202215145112231240022370055142 batch
static Context * unwrap(GPUContext *ctx)
VkFormat to_vk_format(const eGPUTextureFormat format)
Definition vk_common.cc:131
static uint32_t to_binding_location_len(const GPUVertAttr &attribute)
VecBase< float, 4 > float4
constexpr IntT ceil_division(const IntT x, const IntT y)
unsigned int uint32_t
Definition stdint.h:80
__int64 int64_t
Definition stdint.h:89
GPUVertAttr attrs[GPU_VERT_ATTR_MAX_LEN]
float size
Definition particles.h:28
const GPUVertFormat & device_format_get() const