Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2017-07-29 19:17:11 +0300
committerCampbell Barton <ideasman42@gmail.com>2017-07-29 19:26:36 +0300
commitbe97238308a88d65903fb002cf8db2158d26ef7e (patch)
tree068d77e03933fb6dbb37776d6cd4ccb716fd2bd0 /source/blender/draw
parent71388b094fafd9062a3de9157ea5658b76634b36 (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.c137
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 */