Blender V5.0
GPU_index_buffer.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2016 by Mike Erwin. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11#pragma once
12
13#include "BLI_span.hh"
14
15#include "GPU_primitive.hh"
16
17#define GPU_TRACK_INDEX_RANGE 1
18
19namespace blender::gpu {
20
22constexpr uint32_t RESTART_INDEX = 0xFFFFFFFF;
23
28
29inline size_t to_bytesize(GPUIndexBufType type)
30{
31 return (type == GPU_INDEX_U32) ? sizeof(uint32_t) : sizeof(uint16_t);
32}
33
40class IndexBuf {
41 protected:
45 uint32_t index_start_ = 0;
47 uint32_t index_len_ = 0;
49 uint32_t index_base_ = 0;
51 bool is_init_ = false;
53 bool is_subrange_ = false;
55 bool is_empty_ = false;
56
57 union {
59 void *data_ = nullptr;
62 };
63
64 public:
66 virtual ~IndexBuf();
67
68 void init(uint indices_len,
69 uint32_t *indices,
70 uint min_index,
71 uint max_index,
72 GPUPrimType prim_type,
73 bool uses_restart_indices);
74 void init_subrange(IndexBuf *elem_src, uint start, uint length);
75 void init_build_on_device(uint index_len);
76
77 /* Returns render index count (not precise). */
78 uint32_t index_len_get() const
79 {
80 /* Return 0 to bypass drawing for index buffers full of restart indices.
81 * They can lead to graphical glitches on some systems. (See #96892) */
82 return is_empty_ ? 0 : index_len_;
83 }
84 uint32_t index_start_get() const
85 {
86 return index_start_;
87 }
88 uint32_t index_base_get() const
89 {
90 return index_base_;
91 }
92 bool is_32bit() const
93 {
94 return index_type_ == GPU_INDEX_U32;
95 }
96 /* Return size in byte of the drawable data buffer range. Actual buffer size might be bigger. */
97 size_t size_get() const
98 {
100 };
101
102 bool is_init() const
103 {
104 return is_init_;
105 };
106
107 virtual void upload_data() = 0;
108
109 virtual void bind_as_ssbo(uint binding) = 0;
110
111 virtual void read(uint32_t *data) const = 0;
112
113 virtual void update_sub(uint start, uint len, const void *data) = 0;
114
115 private:
116 inline void squeeze_indices_short(uint min_idx,
117 uint max_idx,
118 GPUPrimType prim_type,
119 bool clamp_indices_in_range);
120 virtual void strip_restart_indices() = 0;
121};
122
124{
125 switch (prim_type) {
126 case GPU_PRIM_POINTS:
127 return 1;
128 case GPU_PRIM_LINES:
129 return 2;
130 case GPU_PRIM_TRIS:
131 return 3;
133 return 4;
135 return 6;
141 return 1; /* Minus one for the whole length. */
143 return 1;
144 default:
145 return -1;
146 }
147}
148
149} // namespace blender::gpu
150
152
165
167void GPU_indexbuf_init_ex(GPUIndexBufBuilder *, GPUPrimType, uint index_len, uint vertex_len);
168
170void GPU_indexbuf_init(GPUIndexBufBuilder *, GPUPrimType, uint prim_len, uint vertex_len);
172
174
176
177/*
178 * Thread safe.
179 *
180 * Function inspired by the reduction directives of multi-thread work API's.
181 */
182void GPU_indexbuf_join(GPUIndexBufBuilder *builder, const GPUIndexBufBuilder *builder_from);
183
186
191
195
196/* Skip primitive rendering at the given index. */
200
203 uint index_min,
204 uint index_max,
205 bool uses_restart_indices);
208 uint index_min,
209 uint index_max,
210 bool uses_restart_indices,
212
221 const uint32_t *data,
222 int32_t data_len,
223 int32_t index_min,
224 int32_t index_max,
225 bool uses_restart_indices);
226
231
233 uint curves_num,
234 uint verts_per_curve);
235
236/* Upload data to the GPU (if not built on the device) and bind the buffer to its default target.
237 */
239
240/* Partially update the blender::gpu::IndexBuf which was already sent to the device, or built
241 * directly on the device. The data needs to be compatible with potential compression applied to
242 * the original indices when the index buffer was built, i.e., if the data was compressed to use
243 * shorts instead of ints, shorts should passed here. */
244void GPU_indexbuf_update_sub(blender::gpu::IndexBuf *elem, uint start, uint len, const void *data);
245
246/* Create a sub-range of an existing index-buffer. */
248 uint start,
249 uint length);
251 blender::gpu::IndexBuf *elem_src,
252 uint start,
253 uint length);
254
260void GPU_indexbuf_read(blender::gpu::IndexBuf *elem, uint32_t *data);
261
263
265
267
268/* Macros */
269
270#define GPU_INDEXBUF_DISCARD_SAFE(elem) \
271 do { \
272 if (elem != nullptr) { \
273 GPU_indexbuf_discard(elem); \
274 elem = nullptr; \
275 } \
276 } while (0)
277
278namespace blender::gpu {
279
281 public:
283 {
285 }
286};
287
288using IndexBufPtr = std::unique_ptr<IndexBuf, IndexBufDeleter>;
289
290} // namespace blender::gpu
unsigned int uint
void GPU_indexbuf_discard(blender::gpu::IndexBuf *elem)
void GPU_indexbuf_set_point_vert(GPUIndexBufBuilder *builder, uint elem, uint v1)
void GPU_indexbuf_build_in_place_ex(GPUIndexBufBuilder *builder, uint index_min, uint index_max, bool uses_restart_indices, blender::gpu::IndexBuf *elem)
int GPU_indexbuf_primitive_len(GPUPrimType prim_type)
blender::MutableSpan< uint32_t > GPU_indexbuf_get_data(GPUIndexBufBuilder *)
blender::gpu::IndexBuf * GPU_indexbuf_build_on_device(uint index_len)
void GPU_indexbuf_set_point_restart(GPUIndexBufBuilder *builder, uint elem)
void GPU_indexbuf_create_subrange_in_place(blender::gpu::IndexBuf *elem, blender::gpu::IndexBuf *elem_src, uint start, uint length)
void GPU_indexbuf_init(GPUIndexBufBuilder *, GPUPrimType, uint prim_len, uint vertex_len)
blender::gpu::IndexBuf * GPU_indexbuf_build_ex(GPUIndexBufBuilder *builder, uint index_min, uint index_max, bool uses_restart_indices)
void GPU_indexbuf_bind_as_ssbo(blender::gpu::IndexBuf *elem, int binding)
void GPU_indexbuf_add_primitive_restart(GPUIndexBufBuilder *)
blender::gpu::IndexBuf * GPU_indexbuf_calloc()
void GPU_indexbuf_add_point_vert(GPUIndexBufBuilder *, uint v)
blender::gpu::IndexBuf * GPU_indexbuf_build(GPUIndexBufBuilder *)
void GPU_indexbuf_add_line_verts(GPUIndexBufBuilder *, uint v1, uint v2)
void GPU_indexbuf_join(GPUIndexBufBuilder *builder, const GPUIndexBufBuilder *builder_from)
blender::gpu::IndexBuf * GPU_indexbuf_build_curves_on_device(GPUPrimType prim_type, uint curves_num, uint verts_per_curve)
void GPU_indexbuf_set_line_verts(GPUIndexBufBuilder *builder, uint elem, uint v1, uint v2)
void GPU_indexbuf_read(blender::gpu::IndexBuf *elem, uint32_t *data)
void GPU_indexbuf_set_tri_verts(GPUIndexBufBuilder *builder, uint elem, uint v1, uint v2, uint v3)
void GPU_indexbuf_set_line_restart(GPUIndexBufBuilder *builder, uint elem)
void GPU_indexbuf_add_generic_vert(GPUIndexBufBuilder *, uint v)
void GPU_indexbuf_build_in_place(GPUIndexBufBuilder *, blender::gpu::IndexBuf *)
void GPU_indexbuf_set_tri_restart(GPUIndexBufBuilder *builder, uint elem)
void GPU_indexbuf_add_line_adj_verts(GPUIndexBufBuilder *, uint v1, uint v2, uint v3, uint v4)
void GPU_indexbuf_use(blender::gpu::IndexBuf *elem)
blender::gpu::IndexBuf * GPU_indexbuf_create_subrange(blender::gpu::IndexBuf *elem_src, uint start, uint length)
void GPU_indexbuf_init_ex(GPUIndexBufBuilder *, GPUPrimType, uint index_len, uint vertex_len)
void GPU_indexbuf_update_sub(blender::gpu::IndexBuf *elem, uint start, uint len, const void *data)
void GPU_indexbuf_init_build_on_device(blender::gpu::IndexBuf *elem, uint index_len)
blender::gpu::IndexBuf * GPU_indexbuf_build_from_memory(GPUPrimType prim_type, const uint32_t *data, int32_t data_len, int32_t index_min, int32_t index_max, bool uses_restart_indices)
bool GPU_indexbuf_is_init(blender::gpu::IndexBuf *elem)
void GPU_indexbuf_add_tri_verts(GPUIndexBufBuilder *, uint v1, uint v2, uint v3)
GPUPrimType
@ GPU_PRIM_LINE_LOOP
@ GPU_PRIM_TRIS_ADJ
@ GPU_PRIM_LINES
@ GPU_PRIM_POINTS
@ GPU_PRIM_LINES_ADJ
@ GPU_PRIM_LINE_STRIP
@ GPU_PRIM_TRIS
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
void init()
uint32_t index_start_get() const
uint32_t index_base_get() const
virtual void upload_data()=0
virtual void read(uint32_t *data) const =0
GPUIndexBufType index_type_
virtual void update_sub(uint start, uint len, const void *data)=0
void init_build_on_device(uint index_len)
void init_subrange(IndexBuf *elem_src, uint start, uint length)
uint32_t index_len_get() const
virtual void bind_as_ssbo(uint binding)=0
static ushort indices[]
float length(VecOp< float, D >) RET
std::unique_ptr< IndexBuf, IndexBufDeleter > IndexBufPtr
int to_bytesize(const DataFormat format)
constexpr uint32_t RESTART_INDEX
int indices_per_primitive(GPUPrimType prim_type)
uint len