Blender  V2.93
draw_instance_data.c
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  * Copyright 2016, Blender Foundation.
17  */
18 
32 #include "draw_instance_data.h"
33 #include "draw_manager.h"
34 
35 #include "DRW_engine.h"
36 #include "DRW_render.h" /* For DRW_shgroup_get_instance_count() */
37 
38 #include "GPU_material.h"
39 
40 #include "DNA_particle_types.h"
41 
42 #include "BKE_duplilist.h"
43 
44 #include "RNA_access.h"
45 
46 #include "BLI_bitmap.h"
47 #include "BLI_memblock.h"
48 #include "BLI_mempool.h"
49 #include "BLI_utildefines.h"
50 #include "MEM_guardedalloc.h"
51 
54  bool used; /* If this data is used or not. */
55  size_t data_size; /* Size of one instance data. */
57 };
58 
61  /* Linked lists for all possible data pool size */
64 
68 };
69 
70 typedef struct DRWTempBufferHandle {
75  int *vert_len;
77 
78 typedef struct DRWTempInstancingHandle {
88 
90 
92 {
93  for (int i = 0; i < GPU_BATCH_VBO_MAX_LEN && batch->verts[i]; i++) {
95  }
96  for (int i = 0; i < GPU_BATCH_INST_VBO_MAX_LEN && batch->inst[i]; i++) {
98  }
99 }
100 
102 {
103  for (int i = 0; i < GPU_BATCH_VBO_MAX_LEN && batch->verts[i]; i++) {
105  }
106  for (int i = 0; i < GPU_BATCH_INST_VBO_MAX_LEN && batch->inst[i]; i++) {
108  }
109 }
110 
111 /* -------------------------------------------------------------------- */
125  int *vert_len)
126 {
127  BLI_assert(format != NULL);
128  BLI_assert(vert_len != NULL);
129 
131 
132  if (handle->format != format) {
133  handle->format = format;
134  GPU_VERTBUF_DISCARD_SAFE(handle->buf);
135 
136  GPUVertBuf *vert = GPU_vertbuf_calloc();
139 
140  handle->buf = vert;
141  }
142  handle->vert_len = vert_len;
143  return handle->buf;
144 }
145 
146 /* NOTE: Does not return a valid drawable batch until DRW_instance_buffer_finish has run.
147  * Initialization is delayed because instancer or geom could still not be initialized. */
149  GPUVertBuf *buf,
150  GPUBatch *instancer,
151  GPUBatch *geom)
152 {
153  /* Do not call this with a batch that is already an instancing batch. */
154  BLI_assert(geom->inst[0] == NULL);
155  /* Only call with one of them. */
156  BLI_assert((instancer != NULL) != (buf != NULL));
157 
159  if (handle->batch == NULL) {
160  handle->batch = GPU_batch_calloc();
161  }
162 
163  GPUBatch *batch = handle->batch;
164  bool instancer_compat = buf ? ((batch->inst[0] == buf) &&
166  ((batch->inst[0] == instancer->verts[0]) &&
167  (batch->inst[1] == instancer->verts[1]));
168  bool is_compatible = (batch->prim_type == geom->prim_type) && instancer_compat &&
169  (batch->flag & GPU_BATCH_BUILDING) == 0 && (batch->elem == geom->elem);
170  for (int i = 0; i < GPU_BATCH_VBO_MAX_LEN && is_compatible; i++) {
171  if (batch->verts[i] != geom->verts[i]) {
172  is_compatible = false;
173  }
174  }
175 
176  if (!is_compatible) {
179  /* Save args and init later. */
180  batch->flag = GPU_BATCH_BUILDING;
181  handle->buf = buf;
182  handle->instancer = instancer;
183  handle->geom = geom;
184  }
185  return batch;
186 }
187 
188 /* NOTE: Use only with buf allocated via DRW_temp_buffer_request. */
190  GPUVertBuf *buf,
191  GPUPrimType prim_type)
192 {
193  GPUBatch **batch_ptr = BLI_memblock_alloc(idatalist->pool_batching);
194  if (*batch_ptr == NULL) {
195  *batch_ptr = GPU_batch_calloc();
196  }
197 
198  GPUBatch *batch = *batch_ptr;
199  bool is_compatible = (batch->verts[0] == buf) && (batch->prim_type == prim_type) &&
201  if (!is_compatible) {
203  GPU_batch_init(batch, prim_type, buf, NULL);
204  }
205  return batch;
206 }
207 
209 {
210  handle->format = NULL;
211  GPU_VERTBUF_DISCARD_SAFE(handle->buf);
212 }
213 
215 {
217  GPU_BATCH_DISCARD_SAFE(handle->batch);
218 }
219 
221 {
223 }
224 
226 {
227  /* Resize down buffers in use and send data to GPU. */
228  BLI_memblock_iter iter;
229  DRWTempBufferHandle *handle;
230  BLI_memblock_iternew(idatalist->pool_buffers, &iter);
231  while ((handle = BLI_memblock_iterstep(&iter))) {
232  if (handle->vert_len != NULL) {
233  uint vert_len = *(handle->vert_len);
234  uint target_buf_size = ((vert_len / DRW_BUFFER_VERTS_CHUNK) + 1) * DRW_BUFFER_VERTS_CHUNK;
235  if (target_buf_size < GPU_vertbuf_get_vertex_alloc(handle->buf)) {
236  GPU_vertbuf_data_resize(handle->buf, target_buf_size);
237  }
238  GPU_vertbuf_data_len_set(handle->buf, vert_len);
239  GPU_vertbuf_use(handle->buf); /* Send data. */
240  }
241  }
242  /* Finish pending instancing batches. */
243  DRWTempInstancingHandle *handle_inst;
244  BLI_memblock_iternew(idatalist->pool_instancing, &iter);
245  while ((handle_inst = BLI_memblock_iterstep(&iter))) {
246  GPUBatch *batch = handle_inst->batch;
247  if (batch && batch->flag == GPU_BATCH_BUILDING) {
248  GPUVertBuf *inst_buf = handle_inst->buf;
249  GPUBatch *inst_batch = handle_inst->instancer;
250  GPUBatch *geom = handle_inst->geom;
251  GPU_batch_copy(batch, geom);
252  if (inst_batch != NULL) {
253  for (int i = 0; i < GPU_BATCH_INST_VBO_MAX_LEN && inst_batch->verts[i]; i++) {
254  GPU_batch_instbuf_add_ex(batch, inst_batch->verts[i], false);
255  }
256  }
257  else {
258  GPU_batch_instbuf_add_ex(batch, inst_buf, false);
259  }
260  /* Add reference to avoid comparing pointers (in DRW_temp_batch_request) that could
261  * potentially be the same. This will delay the freeing of the GPUVertBuf itself. */
263  }
264  }
265  /* Resize pools and free unused. */
269 }
270 
273 /* -------------------------------------------------------------------- */
278 {
279  DRWInstanceData *idata = MEM_callocN(sizeof(DRWInstanceData), "DRWInstanceData");
280  idata->next = NULL;
281  idata->used = true;
282  idata->data_size = attr_size;
283  idata->mempool = BLI_mempool_create(sizeof(float) * idata->data_size, 0, 16, 0);
284 
285  BLI_assert(attr_size > 0);
286 
287  /* Push to linked list. */
288  if (idatalist->idata_head[attr_size - 1] == NULL) {
289  idatalist->idata_head[attr_size - 1] = idata;
290  }
291  else {
292  idatalist->idata_tail[attr_size - 1]->next = idata;
293  }
294  idatalist->idata_tail[attr_size - 1] = idata;
295 
296  return idata;
297 }
298 
300 {
302 }
303 
308 {
309  return BLI_mempool_alloc(idata->mempool);
310 }
311 
313 {
314  BLI_assert(attr_size > 0 && attr_size <= MAX_INSTANCE_DATA_SIZE);
315 
316  DRWInstanceData *idata = idatalist->idata_head[attr_size - 1];
317 
318  /* Search for an unused data chunk. */
319  for (; idata; idata = idata->next) {
320  if (idata->used == false) {
321  idata->used = true;
322  return idata;
323  }
324  }
325 
326  return drw_instance_data_create(idatalist, attr_size);
327 }
328 
331 /* -------------------------------------------------------------------- */
336 {
337  DRWInstanceDataList *idatalist = MEM_callocN(sizeof(DRWInstanceDataList), "DRWInstanceDataList");
338 
339  idatalist->pool_batching = BLI_memblock_create(sizeof(GPUBatch *));
342 
343  BLI_addtail(&g_idatalists, idatalist);
344 
345  return idatalist;
346 }
347 
349 {
350  DRWInstanceData *idata, *next_idata;
351 
352  for (int i = 0; i < MAX_INSTANCE_DATA_SIZE; i++) {
353  for (idata = idatalist->idata_head[i]; idata; idata = next_idata) {
354  next_idata = idata->next;
355  DRW_instance_data_free(idata);
356  MEM_freeN(idata);
357  }
358  idatalist->idata_head[i] = NULL;
359  idatalist->idata_tail[i] = NULL;
360  }
361 
365 
366  BLI_remlink(&g_idatalists, idatalist);
367 }
368 
370 {
371  DRWInstanceData *idata;
372 
373  for (int i = 0; i < MAX_INSTANCE_DATA_SIZE; i++) {
374  for (idata = idatalist->idata_head[i]; idata; idata = idata->next) {
375  idata->used = false;
376  }
377  }
378 }
379 
381 {
382  DRWInstanceData *idata, *next_idata;
383 
384  /* Remove unused data blocks and sanitize each list. */
385  for (int i = 0; i < MAX_INSTANCE_DATA_SIZE; i++) {
386  idatalist->idata_tail[i] = NULL;
387  for (idata = idatalist->idata_head[i]; idata; idata = next_idata) {
388  next_idata = idata->next;
389  if (idata->used == false) {
390  if (idatalist->idata_head[i] == idata) {
391  idatalist->idata_head[i] = next_idata;
392  }
393  else {
394  /* idatalist->idata_tail[i] is guaranteed not to be null in this case. */
395  idatalist->idata_tail[i]->next = next_idata;
396  }
397  DRW_instance_data_free(idata);
398  MEM_freeN(idata);
399  }
400  else {
401  if (idatalist->idata_tail[i] != NULL) {
402  idatalist->idata_tail[i]->next = idata;
403  }
404  idatalist->idata_tail[i] = idata;
405  }
406  }
407  }
408 }
409 
411 {
412  DRWInstanceData *idata;
413 
414  for (int i = 0; i < MAX_INSTANCE_DATA_SIZE; i++) {
415  for (idata = idatalist->idata_head[i]; idata; idata = idata->next) {
417  }
418  }
419 }
420 
422 /* -------------------------------------------------------------------- */
426 #define CHUNK_LIST_STEP (1 << 4)
427 
429 typedef struct DRWSparseUniformBuf {
430  /* Memory buffers used to stage chunk data before transfer to UBOs. */
432  /* Uniform buffer objects with flushed data. */
434  /* True if the relevant chunk contains data (distinct from simply being allocated). */
436 
440 
442  unsigned int item_size,
443  unsigned int chunk_size)
444 {
445  buffer->chunk_buffers = NULL;
446  buffer->chunk_used = NULL;
447  buffer->chunk_ubos = NULL;
448  buffer->num_chunks = 0;
449  buffer->item_size = item_size;
450  buffer->chunk_size = chunk_size;
451  buffer->chunk_bytes = item_size * chunk_size;
452 }
453 
455 DRWSparseUniformBuf *DRW_sparse_uniform_buffer_new(unsigned int item_size, unsigned int chunk_size)
456 {
457  DRWSparseUniformBuf *buf = MEM_mallocN(sizeof(DRWSparseUniformBuf), __func__);
458  drw_sparse_uniform_buffer_init(buf, item_size, chunk_size);
459  return buf;
460 }
461 
464 {
465  for (int i = 0; i < buffer->num_chunks; i++) {
466  if (BLI_BITMAP_TEST(buffer->chunk_used, i)) {
467  if (buffer->chunk_ubos[i] == NULL) {
468  buffer->chunk_ubos[i] = GPU_uniformbuf_create(buffer->chunk_bytes);
469  }
470  GPU_uniformbuf_update(buffer->chunk_ubos[i], buffer->chunk_buffers[i]);
471  }
472  }
473 }
474 
477 {
478  int max_used_chunk = 0;
479 
480  for (int i = 0; i < buffer->num_chunks; i++) {
481  /* Delete buffers that were not used since the last clear call. */
482  if (free_all || !BLI_BITMAP_TEST(buffer->chunk_used, i)) {
483  MEM_SAFE_FREE(buffer->chunk_buffers[i]);
484 
485  if (buffer->chunk_ubos[i]) {
486  GPU_uniformbuf_free(buffer->chunk_ubos[i]);
487  buffer->chunk_ubos[i] = NULL;
488  }
489  }
490  else {
491  max_used_chunk = i + 1;
492  }
493  }
494 
495  /* Shrink the chunk array if appropriate. */
496  const int old_num_chunks = buffer->num_chunks;
497 
498  buffer->num_chunks = (max_used_chunk + CHUNK_LIST_STEP - 1) & ~(CHUNK_LIST_STEP - 1);
499 
500  if (buffer->num_chunks == 0) {
501  /* Ensure that an empty pool holds no memory allocations. */
502  MEM_SAFE_FREE(buffer->chunk_buffers);
503  MEM_SAFE_FREE(buffer->chunk_used);
504  MEM_SAFE_FREE(buffer->chunk_ubos);
505  return;
506  }
507 
508  if (buffer->num_chunks != old_num_chunks) {
509  buffer->chunk_buffers = MEM_recallocN(buffer->chunk_buffers,
510  buffer->num_chunks * sizeof(void *));
511  buffer->chunk_ubos = MEM_recallocN(buffer->chunk_ubos, buffer->num_chunks * sizeof(void *));
512  BLI_BITMAP_RESIZE(buffer->chunk_used, buffer->num_chunks);
513  }
514 
515  BLI_bitmap_set_all(buffer->chunk_used, false, buffer->num_chunks);
516 }
517 
520 {
522  MEM_freeN(buffer);
523 }
524 
527 {
528  return buffer->num_chunks == 0;
529 }
530 
532 {
533  if (buffer && chunk < buffer->num_chunks && BLI_BITMAP_TEST(buffer->chunk_used, chunk)) {
534  return buffer->chunk_ubos[chunk];
535  }
536  return NULL;
537 }
538 
541 {
543  if (ubo) {
544  GPU_uniformbuf_bind(ubo, location);
545  }
546 }
547 
550 {
552  if (ubo) {
554  }
555 }
556 
559 {
560  if (chunk >= buffer->num_chunks) {
561  buffer->num_chunks = (chunk + CHUNK_LIST_STEP) & ~(CHUNK_LIST_STEP - 1);
562  buffer->chunk_buffers = MEM_recallocN(buffer->chunk_buffers,
563  buffer->num_chunks * sizeof(void *));
564  buffer->chunk_ubos = MEM_recallocN(buffer->chunk_ubos, buffer->num_chunks * sizeof(void *));
565  BLI_BITMAP_RESIZE(buffer->chunk_used, buffer->num_chunks);
566  }
567 
568  char *chunk_buffer = buffer->chunk_buffers[chunk];
569 
570  if (chunk_buffer == NULL) {
571  buffer->chunk_buffers[chunk] = chunk_buffer = MEM_callocN(buffer->chunk_bytes, __func__);
572  }
573  else if (!BLI_BITMAP_TEST(buffer->chunk_used, chunk)) {
574  memset(chunk_buffer, 0, buffer->chunk_bytes);
575  }
576 
577  BLI_BITMAP_ENABLE(buffer->chunk_used, chunk);
578 
579  return chunk_buffer + buffer->item_size * item;
580 }
581 
584 /* -------------------------------------------------------------------- */
589 typedef struct DRWUniformAttrBuf {
590  /* Attribute list (also used as hash table key) handled by this buffer. */
592  /* Sparse UBO buffer containing the attribute values. */
594  /* Last handle used to update the buffer, checked for avoiding redundant updates. */
596  /* Linked list pointer used for freeing the empty unneeded buffers. */
599 
601 {
602  void **pkey, **pval;
603 
604  if (!BLI_ghash_ensure_p_ex(table, key, &pkey, &pval)) {
605  DRWUniformAttrBuf *buffer = MEM_callocN(sizeof(*buffer), __func__);
606 
607  *pkey = &buffer->key;
608  *pval = buffer;
609 
612  &buffer->ubos, key->count * sizeof(float[4]), DRW_RESOURCE_CHUNK_LEN);
613 
614  buffer->last_handle = (DRWResourceHandle)-1;
615  }
616 
617  return (DRWUniformAttrBuf *)*pval;
618 }
619 
620 /* This function mirrors lookup_property in cycles/blender/blender_object.cpp */
621 static bool drw_uniform_property_lookup(ID *id, const char *name, float r_data[4])
622 {
623  PointerRNA ptr, id_ptr;
624  PropertyRNA *prop;
625 
626  if (!id) {
627  return false;
628  }
629 
630  RNA_id_pointer_create(id, &id_ptr);
631 
632  if (!RNA_path_resolve(&id_ptr, name, &ptr, &prop)) {
633  return false;
634  }
635 
636  if (prop == NULL) {
637  return false;
638  }
639 
641  int arraylen = RNA_property_array_length(&ptr, prop);
642 
643  if (arraylen == 0) {
644  float value;
645 
646  if (type == PROP_FLOAT) {
647  value = RNA_property_float_get(&ptr, prop);
648  }
649  else if (type == PROP_INT) {
650  value = RNA_property_int_get(&ptr, prop);
651  }
652  else {
653  return false;
654  }
655 
656  copy_v4_fl4(r_data, value, value, value, 1);
657  return true;
658  }
659 
660  if (type == PROP_FLOAT && arraylen <= 4) {
661  copy_v4_fl4(r_data, 0, 0, 0, 1);
662  RNA_property_float_get_array(&ptr, prop, r_data);
663  return true;
664  }
665 
666  return false;
667 }
668 
669 /* This function mirrors lookup_instance_property in cycles/blender/blender_object.cpp */
671  Object *ob,
672  Object *dupli_parent,
673  DupliObject *dupli_source,
674  float r_data[4])
675 {
676  copy_v4_fl(r_data, 0);
677 
678  char idprop_name[(sizeof(attr->name) * 2) + 4];
679  {
680  char attr_name_esc[sizeof(attr->name) * 2];
681  BLI_str_escape(attr_name_esc, attr->name, sizeof(attr_name_esc));
682  SNPRINTF(idprop_name, "[\"%s\"]", attr_name_esc);
683  }
684 
685  /* If requesting instance data, check the parent particle system and object. */
686  if (attr->use_dupli) {
687  if (dupli_source && dupli_source->particle_system) {
688  ParticleSettings *settings = dupli_source->particle_system->part;
689  if (drw_uniform_property_lookup((ID *)settings, idprop_name, r_data) ||
690  drw_uniform_property_lookup((ID *)settings, attr->name, r_data)) {
691  return;
692  }
693  }
694  if (drw_uniform_property_lookup((ID *)dupli_parent, idprop_name, r_data) ||
695  drw_uniform_property_lookup((ID *)dupli_parent, attr->name, r_data)) {
696  return;
697  }
698  }
699 
700  /* Check the object and mesh. */
701  if (ob) {
702  if (drw_uniform_property_lookup((ID *)ob, idprop_name, r_data) ||
703  drw_uniform_property_lookup((ID *)ob, attr->name, r_data) ||
704  drw_uniform_property_lookup((ID *)ob->data, idprop_name, r_data) ||
705  drw_uniform_property_lookup((ID *)ob->data, attr->name, r_data)) {
706  return;
707  }
708  }
709 }
710 
713  DRWResourceHandle *handle,
714  Object *ob,
715  Object *dupli_parent,
716  DupliObject *dupli_source)
717 {
719 
720  if (buffer->last_handle != *handle) {
721  buffer->last_handle = *handle;
722 
723  int chunk = DRW_handle_chunk_get(handle);
724  int item = DRW_handle_id_get(handle);
725  float(*values)[4] = DRW_sparse_uniform_buffer_ensure_item(&buffer->ubos, chunk, item);
726 
727  LISTBASE_FOREACH (GPUUniformAttr *, attr, &buffer->key.list) {
728  drw_uniform_attribute_lookup(attr, ob, dupli_parent, dupli_source, *values++);
729  }
730  }
731 }
732 
734 {
736  return buffer ? &buffer->ubos : NULL;
737 }
738 
740 {
741  return GPU_uniform_attr_list_hash_new("obattr_hash");
742 }
743 
745 {
748  }
750 }
751 
753 {
755 
758  MEM_freeN(buffer);
759 }
760 
762 {
763  DRWUniformAttrBuf *remove_list = NULL;
764 
766  buffer->last_handle = (DRWResourceHandle)-1;
768 
770  buffer->next_empty = remove_list;
771  remove_list = buffer;
772  }
773  }
775 
776  while (remove_list) {
777  DRWUniformAttrBuf *buffer = remove_list;
778  remove_list = buffer->next_empty;
780  }
781 }
782 
784 {
786 }
787 
typedef float(TangentPoint)[2]
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define BLI_BITMAP_TEST(_bitmap, _index)
Definition: BLI_bitmap.h:63
#define BLI_BITMAP_ENABLE(_bitmap, _index)
Definition: BLI_bitmap.h:78
void BLI_bitmap_set_all(BLI_bitmap *bitmap, bool set, size_t bits)
Definition: bitmap.c:33
#define BLI_BITMAP_RESIZE(_bitmap, _tot)
Definition: BLI_bitmap.h:106
unsigned int BLI_bitmap
Definition: BLI_bitmap.h:32
#define GHASH_FOREACH_END()
Definition: BLI_ghash.h:315
#define GHASH_FOREACH_BEGIN(type, var, what)
Definition: BLI_ghash.h:309
bool BLI_ghash_remove(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:900
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:1008
bool BLI_ghash_ensure_p_ex(GHash *gh, const void *key, void ***r_key, void ***r_val) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:873
void * BLI_ghash_lookup(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:803
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:133
MINLINE void copy_v4_fl4(float v[4], float x, float y, float z, float w)
MINLINE void copy_v4_fl(float r[4], float f)
void(* MemblockValFreeFP)(void *val)
Definition: BLI_memblock.h:37
void BLI_memblock_destroy(BLI_memblock *mblk, MemblockValFreeFP free_callback) ATTR_NONNULL(1)
Definition: BLI_memblock.c:82
#define BLI_memblock_create(elem_size)
Definition: BLI_memblock.h:44
void BLI_memblock_iternew(BLI_memblock *mblk, BLI_memblock_iter *iter) ATTR_NONNULL()
Definition: BLI_memblock.c:163
void * BLI_memblock_iterstep(BLI_memblock_iter *iter) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: BLI_memblock.c:175
void * BLI_memblock_alloc(BLI_memblock *mblk) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition: BLI_memblock.c:133
void BLI_memblock_clear(BLI_memblock *mblk, MemblockValFreeFP free_callback) ATTR_NONNULL(1)
Definition: BLI_memblock.c:104
void void BLI_mempool_clear_ex(BLI_mempool *pool, const int totelem_reserve) ATTR_NONNULL(1)
Definition: BLI_mempool.c:694
BLI_mempool * BLI_mempool_create(unsigned int esize, unsigned int totelem, unsigned int pchunk, unsigned int flag) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: BLI_mempool.c:268
void * BLI_mempool_alloc(BLI_mempool *pool) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition: BLI_mempool.c:334
void BLI_mempool_destroy(BLI_mempool *pool) ATTR_NONNULL(1)
Definition: BLI_mempool.c:757
int BLI_mempool_len(BLI_mempool *pool) ATTR_NONNULL(1)
Definition: BLI_mempool.c:454
#define SNPRINTF(dst, format,...)
Definition: BLI_string.h:165
size_t size_t char size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, const size_t dst_maxncpy) ATTR_NONNULL()
Definition: string.c:333
unsigned int uint
Definition: BLI_sys_types.h:83
GPUBatch * GPU_batch_calloc(void)
Definition: gpu_batch.cc:53
GPUBatch
Definition: GPU_batch.h:93
void GPU_batch_copy(GPUBatch *batch_dst, GPUBatch *batch_src)
Definition: gpu_batch.cc:94
#define GPU_BATCH_INST_VBO_MAX_LEN
Definition: GPU_batch.h:36
#define GPU_BATCH_VBO_MAX_LEN
Definition: GPU_batch.h:35
void GPU_batch_clear(GPUBatch *)
Definition: gpu_batch.cc:105
#define GPU_BATCH_DISCARD_SAFE(batch)
Definition: GPU_batch.h:199
int GPU_batch_instbuf_add_ex(GPUBatch *, GPUVertBuf *, bool own_vbo)
Definition: gpu_batch.cc:168
#define GPU_batch_init(batch, prim, verts, elem)
Definition: GPU_batch.h:108
@ GPU_BATCH_BUILDING
Definition: GPU_batch.h:59
_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 type
void GPU_uniform_attr_list_copy(GPUUniformAttrList *dest, GPUUniformAttrList *src)
struct GHash * GPU_uniform_attr_list_hash_new(const char *info)
void GPU_uniform_attr_list_free(GPUUniformAttrList *set)
GPUPrimType
Definition: GPU_primitive.h:34
struct GPUUniformBuf GPUUniformBuf
void GPU_uniformbuf_unbind(GPUUniformBuf *ubo)
#define GPU_uniformbuf_create(size)
void GPU_uniformbuf_update(GPUUniformBuf *ubo, const void *data)
void GPU_uniformbuf_free(GPUUniformBuf *ubo)
void GPU_uniformbuf_bind(GPUUniformBuf *ubo, int slot)
uint GPU_vertbuf_get_vertex_alloc(const GPUVertBuf *verts)
struct GPUVertBuf GPUVertBuf
GPUVertBuf * GPU_vertbuf_calloc(void)
void GPU_vertbuf_handle_ref_remove(GPUVertBuf *verts)
void GPU_vertbuf_data_alloc(GPUVertBuf *, uint v_len)
void GPU_vertbuf_init_with_format_ex(GPUVertBuf *, const GPUVertFormat *, GPUUsageType)
@ GPU_VERTBUF_DATA_UPLOADED
GPUVertBufStatus GPU_vertbuf_get_status(const GPUVertBuf *verts)
#define GPU_VERTBUF_DISCARD_SAFE(verts)
void GPU_vertbuf_use(GPUVertBuf *)
void GPU_vertbuf_data_len_set(GPUVertBuf *, uint v_len)
void GPU_vertbuf_handle_ref_add(GPUVertBuf *verts)
@ GPU_USAGE_DYNAMIC
void GPU_vertbuf_data_resize(GPUVertBuf *, uint v_len)
Read Guarded memory(de)allocation.
#define MEM_recallocN(vmemh, len)
#define MEM_SAFE_FREE(v)
PropertyType
Definition: RNA_types.h:72
@ PROP_FLOAT
Definition: RNA_types.h:75
@ PROP_INT
Definition: RNA_types.h:74
static ListBase g_idatalists
static void drw_uniform_attribute_lookup(GPUUniformAttr *attr, Object *ob, Object *dupli_parent, DupliObject *dupli_source, float r_data[4])
void DRW_instance_data_list_free(DRWInstanceDataList *idatalist)
#define CHUNK_LIST_STEP
void * DRW_instance_data_next(DRWInstanceData *idata)
static bool drw_uniform_property_lookup(ID *id, const char *name, float r_data[4])
void * DRW_sparse_uniform_buffer_ensure_item(DRWSparseUniformBuf *buffer, int chunk, int item)
static DRWInstanceData * drw_instance_data_create(DRWInstanceDataList *idatalist, uint attr_size)
static void temp_buffer_handle_free(DRWTempBufferHandle *handle)
static void temp_instancing_handle_free(DRWTempInstancingHandle *handle)
void DRW_instance_data_list_free_unused(DRWInstanceDataList *idatalist)
DRWInstanceDataList * DRW_instance_data_list_create(void)
bool DRW_sparse_uniform_buffer_is_empty(DRWSparseUniformBuf *buffer)
static void temp_batch_free(GPUBatch **batch)
DRWInstanceData * DRW_instance_data_request(DRWInstanceDataList *idatalist, uint attr_size)
DRWSparseUniformBuf * DRW_sparse_uniform_buffer_new(unsigned int item_size, unsigned int chunk_size)
static GPUUniformBuf * drw_sparse_uniform_buffer_get_ubo(DRWSparseUniformBuf *buffer, int chunk)
struct DRWTempBufferHandle DRWTempBufferHandle
void DRW_uniform_attrs_pool_flush_all(GHash *table)
struct DRWSparseUniformBuf DRWSparseUniformBuf
struct DRWUniformAttrBuf DRWUniformAttrBuf
static void DRW_instance_data_free(DRWInstanceData *idata)
GHash * DRW_uniform_attrs_pool_new()
void DRW_instance_buffer_finish(DRWInstanceDataList *idatalist)
void DRW_sparse_uniform_buffer_free(DRWSparseUniformBuf *buffer)
GPUVertBuf * DRW_temp_buffer_request(DRWInstanceDataList *idatalist, GPUVertFormat *format, int *vert_len)
static DRWUniformAttrBuf * drw_uniform_attrs_pool_ensure(GHash *table, GPUUniformAttrList *key)
void DRW_uniform_attrs_pool_clear_all(GHash *table)
static void drw_uniform_attrs_pool_free_cb(void *ptr)
static void instancing_batch_references_add(GPUBatch *batch)
static void drw_sparse_uniform_buffer_init(DRWSparseUniformBuf *buffer, unsigned int item_size, unsigned int chunk_size)
DRWSparseUniformBuf * DRW_uniform_attrs_pool_find_ubo(GHash *table, struct GPUUniformAttrList *key)
void DRW_sparse_uniform_buffer_unbind(DRWSparseUniformBuf *buffer, int chunk)
GPUBatch * DRW_temp_batch_instance_request(DRWInstanceDataList *idatalist, GPUVertBuf *buf, GPUBatch *instancer, GPUBatch *geom)
void drw_uniform_attrs_pool_update(GHash *table, GPUUniformAttrList *key, DRWResourceHandle *handle, Object *ob, Object *dupli_parent, DupliObject *dupli_source)
GPUBatch * DRW_temp_batch_request(DRWInstanceDataList *idatalist, GPUVertBuf *buf, GPUPrimType prim_type)
void DRW_sparse_uniform_buffer_bind(DRWSparseUniformBuf *buffer, int chunk, int location)
struct DRWTempInstancingHandle DRWTempInstancingHandle
void DRW_instance_data_list_reset(DRWInstanceDataList *idatalist)
void DRW_sparse_uniform_buffer_clear(DRWSparseUniformBuf *buffer, bool free_all)
void DRW_sparse_uniform_buffer_flush(DRWSparseUniformBuf *buffer)
static void instancing_batch_references_remove(GPUBatch *batch)
void DRW_instance_data_list_resize(DRWInstanceDataList *idatalist)
void DRW_uniform_attrs_pool_free(GHash *table)
#define DRW_BUFFER_VERTS_CHUNK
#define MAX_INSTANCE_DATA_SIZE
BLI_INLINE uint32_t DRW_handle_chunk_get(const DRWResourceHandle *handle)
Definition: draw_manager.h:138
#define DRW_RESOURCE_CHUNK_LEN
Definition: draw_manager.h:115
BLI_INLINE uint32_t DRW_handle_id_get(const DRWResourceHandle *handle)
Definition: draw_manager.h:143
uint32_t DRWResourceHandle
Definition: draw_manager.h:131
GPUBatch * batch
Definition: drawnode.c:3779
__kernel void ccl_constant KernelData ccl_global void ccl_global char ccl_global int ccl_global char ccl_global unsigned int ccl_global float * buffer
format
Definition: logImageCore.h:47
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
float RNA_property_float_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:2941
void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
Definition: rna_access.c:3033
void RNA_id_pointer_create(ID *id, PointerRNA *r_ptr)
Definition: rna_access.c:122
PropertyType RNA_property_type(PropertyRNA *prop)
Definition: rna_access.c:1155
int RNA_property_int_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:2607
int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:1218
bool RNA_path_resolve(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop)
Definition: rna_access.c:5400
struct DRWInstanceDataList * next
BLI_memblock * pool_batching
DRWInstanceData * idata_tail[MAX_INSTANCE_DATA_SIZE]
DRWInstanceData * idata_head[MAX_INSTANCE_DATA_SIZE]
struct DRWInstanceDataList * prev
BLI_memblock * pool_buffers
BLI_memblock * pool_instancing
struct DRWInstanceData * next
BLI_mempool * mempool
struct GPUUniformBuf ** chunk_ubos
GPUVertFormat * format
DRWSparseUniformBuf ubos
GPUUniformAttrList key
struct DRWUniformAttrBuf * next_empty
DRWResourceHandle last_handle
struct ParticleSystem * particle_system
Definition: BKE_duplilist.h:57
unsigned int count
Definition: GPU_material.h:281
Definition: DNA_ID.h:273
ParticleSettings * part
PointerRNA * ptr
Definition: wm_files.c:3157