diff options
author | Campbell Barton <ideasman42@gmail.com> | 2017-07-29 19:17:11 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2017-07-29 19:26:36 +0300 |
commit | be97238308a88d65903fb002cf8db2158d26ef7e (patch) | |
tree | 068d77e03933fb6dbb37776d6cd4ccb716fd2bd0 /source/blender/draw | |
parent | 71388b094fafd9062a3de9157ea5658b76634b36 (diff) |
DwM: use BLI_memiter for draw storage & iteration
This will only be noticeable for drawing many instances.
In contrived use-case with many instances, and `USE_PROFILE` disabled
this can close to double playback FPS.
The option to disable this is left in the code in case we want to
debug memory use.
See D2756 for details.
Diffstat (limited to 'source/blender/draw')
-rw-r--r-- | source/blender/draw/intern/draw_manager.c | 137 |
1 files changed, 119 insertions, 18 deletions
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index caf1894dc91..ce4390c40fb 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -129,6 +129,13 @@ /* Use draw manager to call GPU_select, see: DRW_draw_select_loop */ #define USE_GPU_SELECT +/* Use BLI_memiter */ +#define USE_MEM_ITER + +#ifdef USE_MEM_ITER +#include "BLI_memiter.h" +#endif + #ifdef USE_GPU_SELECT # include "ED_view3d.h" # include "ED_armature.h" @@ -230,7 +237,10 @@ struct DRWPass { }; typedef struct DRWCallHeader { +#ifndef USE_MEM_ITER void *next, *prev; +#endif + #ifdef USE_GPU_SELECT int select_id; #endif @@ -267,7 +277,14 @@ struct DRWShadingGroup { GPUShader *shader; /* Shader to bind */ DRWInterface *interface; /* Uniforms pointers */ - ListBase calls; /* DRWCall or DRWCallDynamic depending of type */ + + /* DRWCall or DRWCallDynamic depending of type */ +#ifdef USE_MEM_ITER + BLI_memiter *calls; +#else + ListBase calls; +#endif + DRWState state_extra; /* State changes for this batch only (or'd with the pass's state) */ DRWState state_extra_disable; /* State changes for this batch only (and'd with the pass's state) */ int type; @@ -729,6 +746,7 @@ static void DRW_interface_attrib(DRWShadingGroup *shgroup, const char *name, DRW DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass) { DRWShadingGroup *shgroup = MEM_mallocN(sizeof(DRWShadingGroup), "DRWShadingGroup"); + BLI_addtail(&pass->shgroups, shgroup); shgroup->type = DRW_SHG_NORMAL; shgroup->shader = shader; @@ -738,8 +756,11 @@ DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass) shgroup->batch_geom = NULL; shgroup->instance_geom = NULL; - BLI_addtail(&pass->shgroups, shgroup); +#ifdef USE_MEM_ITER + shgroup->calls = BLI_memiter_create(BLI_MEMITER_DEFAULT_SIZE); +#else BLI_listbase_clear(&shgroup->calls); +#endif #ifdef USE_GPU_SELECT shgroup->pass_parent = pass; @@ -875,7 +896,12 @@ DRWShadingGroup *DRW_shgroup_empty_tri_batch_create(struct GPUShader *shader, DR void DRW_shgroup_free(struct DRWShadingGroup *shgroup) { +#ifdef USE_MEM_ITER + BLI_memiter_destroy(shgroup->calls); +#else BLI_freelistN(&shgroup->calls); +#endif + BLI_freelistN(&shgroup->interface->uniforms); BLI_freelistN(&shgroup->interface->attribs); @@ -902,7 +928,14 @@ void DRW_shgroup_call_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, float (*obm { BLI_assert(geom != NULL); - DRWCall *call = MEM_callocN(sizeof(DRWCall), "DRWCall"); + DRWCall *call; + +#ifdef USE_MEM_ITER + call = BLI_memiter_calloc(shgroup->calls, sizeof(DRWCall)); +#else + call = MEM_callocN(sizeof(DRWCall), "DRWCall"); + BLI_addtail(&shgroup->calls, call); +#endif call->head.type = DRW_CALL_SINGLE; #ifdef USE_GPU_SELECT @@ -915,14 +948,22 @@ void DRW_shgroup_call_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, float (*obm call->geometry = geom; - BLI_addtail(&shgroup->calls, call); + + } void DRW_shgroup_call_object_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, Object *ob) { BLI_assert(geom != NULL); - DRWCall *call = MEM_callocN(sizeof(DRWCall), "DRWCall"); + DRWCall *call; + +#ifdef USE_MEM_ITER + call = BLI_memiter_calloc(shgroup->calls, sizeof(DRWCall)); +#else + call = MEM_callocN(sizeof(DRWCall), "DRWCall"); + BLI_addtail(&shgroup->calls, call); +#endif call->head.type = DRW_CALL_SINGLE; #ifdef USE_GPU_SELECT @@ -933,7 +974,6 @@ void DRW_shgroup_call_object_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, Obje call->geometry = geom; call->ob_data = ob->data; - BLI_addtail(&shgroup->calls, call); } void DRW_shgroup_call_generate_add( @@ -943,7 +983,14 @@ void DRW_shgroup_call_generate_add( { BLI_assert(geometry_fn != NULL); - DRWCallGenerate *call = MEM_callocN(sizeof(DRWCallGenerate), "DRWCallGenerate"); + DRWCallGenerate *call; + +#ifdef USE_MEM_ITER + call = BLI_memiter_calloc(shgroup->calls, sizeof(DRWCallGenerate)); +#else + call = MEM_callocN(sizeof(DRWCallGenerate), "DRWCallGenerate"); + BLI_addtail(&shgroup->calls, call); +#endif call->head.type = DRW_CALL_GENERATE; #ifdef USE_GPU_SELECT @@ -956,8 +1003,6 @@ void DRW_shgroup_call_generate_add( call->geometry_fn = geometry_fn; call->user_data = user_data; - - BLI_addtail(&shgroup->calls, call); } static void sculpt_draw_cb( @@ -987,7 +1032,12 @@ void DRW_shgroup_call_dynamic_add_array(DRWShadingGroup *shgroup, const void *at #ifdef USE_GPU_SELECT if ((G.f & G_PICKSEL) && (interface->instance_count > 0)) { shgroup = MEM_dupallocN(shgroup); + +#ifdef USE_MEM_ITER + shgroup->calls = BLI_memiter_create(BLI_MEMITER_DEFAULT_SIZE); +#else BLI_listbase_clear(&shgroup->calls); +#endif shgroup->interface = interface = DRW_interface_duplicate(interface); interface->instance_count = 0; @@ -999,7 +1049,16 @@ void DRW_shgroup_call_dynamic_add_array(DRWShadingGroup *shgroup, const void *at unsigned int data_size = sizeof(void *) * interface->attribs_count; int size = sizeof(DRWCallDynamic) + data_size; - DRWCallDynamic *call = MEM_callocN(size, "DRWCallDynamic"); + DRWCallDynamic *call; + +#ifdef USE_MEM_ITER + call = BLI_memiter_alloc(shgroup->calls, size); +#else + call = MEM_mallocN(size, "DRWCallDynamic"); + BLI_addtail(&shgroup->calls, call); +#endif + + memset(call, 0x0, sizeof(DRWCallDynamic)); BLI_assert(attr_len == interface->attribs_count); UNUSED_VARS_NDEBUG(attr_len); @@ -1014,8 +1073,6 @@ void DRW_shgroup_call_dynamic_add_array(DRWShadingGroup *shgroup, const void *at } interface->instance_count += 1; - - BLI_addtail(&shgroup->calls, call); } /* Used for instancing with no attributes */ @@ -1181,7 +1238,14 @@ static void shgroup_dynamic_batch(DRWShadingGroup *shgroup) GWN_vertbuf_data_alloc(vbo, nbr); int j = 0; - for (DRWCallDynamic *call = shgroup->calls.first; call; call = call->head.next, j++) { +#ifdef USE_MEM_ITER + BLI_memiter_handle calls_iter; + BLI_memiter_iter_init(shgroup->calls, &calls_iter); + for (DRWCallDynamic *call; (call = BLI_memiter_iter_step(&calls_iter)); j++) +#else + for (DRWCallDynamic *call = shgroup->calls.first; call; call = call->head.next, j++) +#endif + { int i = 0; for (DRWAttrib *attrib = interface->attribs.first; attrib; attrib = attrib->next, i++) { GWN_vertbuf_attr_set(vbo, attrib->format_id, j, call->data[i]); @@ -1229,7 +1293,14 @@ static void shgroup_dynamic_instance(DRWShadingGroup *shgroup) buffer_size = sizeof(float) * interface->attribs_stride * interface->instance_count; float *data = MEM_mallocN(buffer_size, "Instance VBO data"); - for (DRWCallDynamic *call = shgroup->calls.first; call; call = call->head.next) { +#ifdef USE_MEM_ITER + BLI_memiter_handle calls_iter; + BLI_memiter_iter_init(shgroup->calls, &calls_iter); + for (DRWCallDynamic *call; (call = BLI_memiter_iter_step(&calls_iter)); ) +#else + for (DRWCallDynamic *call = shgroup->calls.first; call; call = call->head.next) +#endif + { for (int j = 0; j < interface->attribs_count; ++j) { memcpy(data + offset, call->data[j], sizeof(float) * interface->attribs_size[j]); offset += interface->attribs_size[j]; @@ -1307,11 +1378,21 @@ typedef struct ZSortData { static int pass_shgroup_dist_sort(void *thunk, const void *a, const void *b) { + const ZSortData *zsortdata = (ZSortData *)thunk; const DRWShadingGroup *shgrp_a = (const DRWShadingGroup *)a; const DRWShadingGroup *shgrp_b = (const DRWShadingGroup *)b; - const DRWCall *call_a = (DRWCall *)(shgrp_a)->calls.first; - const DRWCall *call_b = (DRWCall *)(shgrp_b)->calls.first; - const ZSortData *zsortdata = (ZSortData *)thunk; + + const DRWCall *call_a; + const DRWCall *call_b; + +#ifdef USE_MEM_ITER + call_a = BLI_memiter_elem_first(shgrp_a->calls); + call_b = BLI_memiter_elem_first(shgrp_b->calls); +#else + call_a = shgrp_a->calls.first; + call_b = shgrp_b->calls.first; +#endif + float tmp[3]; sub_v3_v3v3(tmp, zsortdata->origin, call_a->obmat[3]); @@ -1858,11 +1939,24 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) if ((G.f & G_PICKSEL) && (_call)) { \ GPU_select_load_id((_call)->head.select_id); \ } ((void)0) + +#ifdef USE_MEM_ITER +# define GPU_SELECT_LOAD_IF_PICKSEL_LIST(_call_ls) \ + if (G.f & G_PICKSEL) { \ + DRWCall *call_test = BLI_memiter_elem_first(*(_call_ls)); \ + if (call_test != NULL) { \ + BLI_assert(BLI_memiter_count(*(_call_ls)) == 1); \ + GPU_select_load_id(call_test->head.select_id); \ + } \ + } ((void)0) +#else # define GPU_SELECT_LOAD_IF_PICKSEL_LIST(_call_ls) \ if ((G.f & G_PICKSEL) && (_call_ls)->first) { \ BLI_assert(BLI_listbase_is_single(_call_ls)); \ GPU_select_load_id(((DRWCall *)(_call_ls)->first)->head.select_id); \ } ((void)0) +#endif + #else # define GPU_SELECT_LOAD_IF_PICKSEL(call) # define GPU_SELECT_LOAD_IF_PICKSEL_LIST(call) @@ -1889,7 +1983,14 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) } } else { - for (DRWCall *call = shgroup->calls.first; call; call = call->head.next) { +#ifdef USE_MEM_ITER + BLI_memiter_handle calls_iter; + BLI_memiter_iter_init(shgroup->calls, &calls_iter); + for (DRWCall *call; (call = BLI_memiter_iter_step(&calls_iter)); ) +#else + for (DRWCall *call = shgroup->calls.first; call; call = call->head.next) +#endif + { bool neg_scale = is_negative_m4(call->obmat); /* Negative scale objects */ |