Blender  V2.93
gpu_vertex_buffer.cc
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2016 by Mike Erwin.
17  * All rights reserved.
18  */
19 
26 #include "MEM_guardedalloc.h"
27 
28 #include "gpu_backend.hh"
30 
31 #include "gl_vertex_buffer.hh" /* TODO remove */
32 #include "gpu_context_private.hh" /* TODO remove */
33 
35 
36 #include <cstring>
37 
38 /* -------------------------------------------------------------------- */
42 namespace blender::gpu {
43 
44 size_t VertBuf::memory_usage = 0;
45 
47 {
48  /* Needed by some code check. */
49  format.attr_len = 0;
50 }
51 
53 {
54  /* Should already have been cleared. */
56 }
57 
59 {
60  usage_ = usage;
62  GPU_vertformat_copy(&this->format, format);
63  if (!format->packed) {
64  VertexFormat_pack(&this->format);
65  }
67 }
68 
70 {
71  this->release_data();
73 }
74 
76 {
78  /* Full copy. */
79  *dst = *this;
80  /* Almost full copy... */
81  dst->handle_refcount_ = 1;
82  /* Duplicate all needed implementation specifics data. */
83  this->duplicate_data(dst);
84  return dst;
85 }
86 
87 void VertBuf::allocate(uint vert_len)
88 {
89  BLI_assert(format.packed);
90  /* Catch any unnecessary usage. */
91  BLI_assert(vertex_alloc != vert_len || data == nullptr);
92  vertex_len = vertex_alloc = vert_len;
93 
94  this->acquire_data();
95 
97 }
98 
99 void VertBuf::resize(uint vert_len)
100 {
101  /* Catch any unnecessary usage. */
102  BLI_assert(vertex_alloc != vert_len);
103  vertex_len = vertex_alloc = vert_len;
104 
105  this->resize_data();
106 
108 }
109 
111 {
112  this->upload_data();
113 }
114 
115 } // namespace blender::gpu
116 
119 /* -------------------------------------------------------------------- */
123 using namespace blender;
124 using namespace blender::gpu;
125 
126 /* -------- Creation & deletion -------- */
127 
129 {
130  return wrap(GPUBackend::get()->vertbuf_alloc());
131 }
132 
134 {
136  unwrap(verts)->init(format, usage);
137  return verts;
138 }
139 
141  const GPUVertFormat *format,
142  GPUUsageType usage)
143 {
144  unwrap(verts_)->init(format, usage);
145 }
146 
148 {
149  return wrap(unwrap(verts_)->duplicate());
150 }
151 
154 {
155  unwrap(verts)->clear();
156 }
157 
159 {
160  unwrap(verts)->clear();
161  unwrap(verts)->reference_remove();
162 }
163 
165 {
166  unwrap(verts)->reference_add();
167 }
168 
170 {
171  unwrap(verts)->reference_remove();
172 }
173 
174 /* -------- Data update -------- */
175 
176 /* create a new allocation, discarding any existing data */
178 {
179  unwrap(verts)->allocate(v_len);
180 }
181 
182 /* resize buffer keeping existing data */
184 {
185  unwrap(verts)->resize(v_len);
186 }
187 
188 /* Set vertex count but does not change allocation.
189  * Only this many verts will be uploaded to the GPU and rendered.
190  * This is useful for streaming data. */
192 {
193  VertBuf *verts = unwrap(verts_);
194  BLI_assert(verts->data != nullptr); /* Only for dynamic data. */
195  BLI_assert(v_len <= verts->vertex_alloc);
196  verts->vertex_len = v_len;
197 }
198 
199 void GPU_vertbuf_attr_set(GPUVertBuf *verts_, uint a_idx, uint v_idx, const void *data)
200 {
201  VertBuf *verts = unwrap(verts_);
202  const GPUVertFormat *format = &verts->format;
203  const GPUVertAttr *a = &format->attrs[a_idx];
204  BLI_assert(v_idx < verts->vertex_alloc);
205  BLI_assert(a_idx < format->attr_len);
206  BLI_assert(verts->data != nullptr);
207  verts->flag |= GPU_VERTBUF_DATA_DIRTY;
208  memcpy(verts->data + a->offset + v_idx * format->stride, data, a->sz);
209 }
210 
211 void GPU_vertbuf_attr_fill(GPUVertBuf *verts_, uint a_idx, const void *data)
212 {
213  VertBuf *verts = unwrap(verts_);
214  const GPUVertFormat *format = &verts->format;
215  BLI_assert(a_idx < format->attr_len);
216  const GPUVertAttr *a = &format->attrs[a_idx];
217  const uint stride = a->sz; /* tightly packed input data */
218  verts->flag |= GPU_VERTBUF_DATA_DIRTY;
219  GPU_vertbuf_attr_fill_stride(verts_, a_idx, stride, data);
220 }
221 
223 void GPU_vertbuf_vert_set(GPUVertBuf *verts_, uint v_idx, const void *data)
224 {
225  VertBuf *verts = unwrap(verts_);
226  const GPUVertFormat *format = &verts->format;
227  BLI_assert(v_idx < verts->vertex_alloc);
228  BLI_assert(verts->data != nullptr);
229  verts->flag |= GPU_VERTBUF_DATA_DIRTY;
230  memcpy(verts->data + v_idx * format->stride, data, format->stride);
231 }
232 
233 void GPU_vertbuf_attr_fill_stride(GPUVertBuf *verts_, uint a_idx, uint stride, const void *data)
234 {
235  VertBuf *verts = unwrap(verts_);
236  const GPUVertFormat *format = &verts->format;
237  const GPUVertAttr *a = &format->attrs[a_idx];
238  BLI_assert(a_idx < format->attr_len);
239  BLI_assert(verts->data != nullptr);
240  verts->flag |= GPU_VERTBUF_DATA_DIRTY;
241  const uint vertex_len = verts->vertex_len;
242 
243  if (format->attr_len == 1 && stride == format->stride) {
244  /* we can copy it all at once */
245  memcpy(verts->data, data, vertex_len * a->sz);
246  }
247  else {
248  /* we must copy it per vertex */
249  for (uint v = 0; v < vertex_len; v++) {
250  memcpy(
251  verts->data + a->offset + v * format->stride, (const uchar *)data + v * stride, a->sz);
252  }
253  }
254 }
255 
257 {
258  VertBuf *verts = unwrap(verts_);
259  const GPUVertFormat *format = &verts->format;
260  const GPUVertAttr *a = &format->attrs[a_idx];
261  BLI_assert(a_idx < format->attr_len);
262  BLI_assert(verts->data != nullptr);
263 
264  verts->flag |= GPU_VERTBUF_DATA_DIRTY;
266  access->size = a->sz;
267  access->stride = format->stride;
268  access->data = (uchar *)verts->data + a->offset;
269  access->data_init = access->data;
270 #ifdef DEBUG
271  access->_data_end = access->data_init + (size_t)(verts->vertex_alloc * format->stride);
272 #endif
273 }
274 
275 /* -------- Getters -------- */
276 
277 /* NOTE: Be careful when using this. The data needs to match the expected format. */
279 {
280  /* TODO Assert that the format has no padding. */
281  return unwrap(verts)->data;
282 }
283 
284 /* Returns the data buffer and set it to null internally to avoid freeing.
285  * NOTE: Be careful when using this. The data needs to match the expected format. */
287 {
288  VertBuf *verts = unwrap(verts_);
289  /* TODO Assert that the format has no padding. */
290  BLI_assert(verts->data);
291  void *data = verts->data;
292  verts->data = nullptr;
293  return data;
294 }
295 
297 {
298  return &unwrap(verts)->format;
299 }
300 
302 {
303  return unwrap(verts)->vertex_alloc;
304 }
305 
307 {
308  return unwrap(verts)->vertex_len;
309 }
310 
312 {
313  return unwrap(verts)->flag;
314 }
315 
317 {
318  return VertBuf::memory_usage;
319 }
320 
321 /* Should be rename to GPU_vertbuf_data_upload */
323 {
324  unwrap(verts)->upload();
325 }
326 
327 /* XXX this is just a wrapper for the use of the Hair refine workaround.
328  * To be used with GPU_vertbuf_use(). */
330 {
331  unwrap(verts)->update_sub(start, len, data);
332 }
333 
#define BLI_assert(a)
Definition: BLI_assert.h:58
unsigned char uchar
Definition: BLI_sys_types.h:86
unsigned int uint
Definition: BLI_sys_types.h:83
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei stride
struct GPUVertBuf GPUVertBuf
GPUVertBufStatus
@ GPU_VERTBUF_INIT
@ GPU_VERTBUF_INVALID
@ GPU_VERTBUF_DATA_DIRTY
@ GPU_VERTBUF_DATA_UPLOADED
GPUUsageType
void GPU_vertformat_copy(GPUVertFormat *dest, const GPUVertFormat *src)
Read Guarded memory(de)allocation.
ATTR_WARN_UNUSED_RESULT const BMVert * v
virtual VertBuf * vertbuf_alloc(void)=0
static GPUBackend * get(void)
Definition: gpu_context.cc:191
virtual void release_data(void)=0
void resize(uint vert_len)
void init(const GPUVertFormat *format, GPUUsageType usage)
void allocate(uint vert_len)
virtual void upload_data(void)=0
virtual void duplicate_data(VertBuf *dst)=0
virtual void resize_data(void)=0
VertBuf * duplicate(void)
virtual void acquire_data(void)=0
static float verts[][3]
void GPU_vertbuf_data_alloc(GPUVertBuf *verts, uint v_len)
void GPU_vertbuf_data_resize(GPUVertBuf *verts, uint v_len)
void * GPU_vertbuf_steal_data(GPUVertBuf *verts_)
uint GPU_vertbuf_get_vertex_alloc(const GPUVertBuf *verts)
const GPUVertFormat * GPU_vertbuf_get_format(const GPUVertBuf *verts)
void GPU_vertbuf_attr_get_raw_data(GPUVertBuf *verts_, uint a_idx, GPUVertBufRaw *access)
uint GPU_vertbuf_get_vertex_len(const GPUVertBuf *verts)
void GPU_vertbuf_data_len_set(GPUVertBuf *verts_, uint v_len)
GPUVertBuf * GPU_vertbuf_duplicate(GPUVertBuf *verts_)
void GPU_vertbuf_clear(GPUVertBuf *verts)
void GPU_vertbuf_handle_ref_remove(GPUVertBuf *verts)
void GPU_vertbuf_init_with_format_ex(GPUVertBuf *verts_, const GPUVertFormat *format, GPUUsageType usage)
void GPU_vertbuf_attr_fill(GPUVertBuf *verts_, uint a_idx, const void *data)
void GPU_vertbuf_attr_set(GPUVertBuf *verts_, uint a_idx, uint v_idx, const void *data)
GPUVertBufStatus GPU_vertbuf_get_status(const GPUVertBuf *verts)
void * GPU_vertbuf_get_data(const GPUVertBuf *verts)
uint GPU_vertbuf_get_memory_usage()
void GPU_vertbuf_attr_fill_stride(GPUVertBuf *verts_, uint a_idx, uint stride, const void *data)
GPUVertBuf * GPU_vertbuf_create_with_format_ex(const GPUVertFormat *format, GPUUsageType usage)
void GPU_vertbuf_update_sub(GPUVertBuf *verts, uint start, uint len, void *data)
void GPU_vertbuf_use(GPUVertBuf *verts)
void GPU_vertbuf_discard(GPUVertBuf *verts)
void GPU_vertbuf_vert_set(GPUVertBuf *verts_, uint v_idx, const void *data)
void GPU_vertbuf_handle_ref_add(GPUVertBuf *verts)
GPUVertBuf * GPU_vertbuf_calloc()
void VertexFormat_pack(GPUVertFormat *format)
format
Definition: logImageCore.h:47
static unsigned a[3]
Definition: RandGen.cpp:92
static GPUContext * wrap(Context *ctx)
static Context * unwrap(GPUContext *ctx)
unsigned char * data_init
unsigned char * data
uint len