[Bf-blender-cvs] [be97238308a] blender2.8: DwM: use BLI_memiter for draw storage & iteration

Campbell Barton noreply at git.blender.org
Sat Jul 29 18:12:43 CEST 2017


Commit: be97238308a88d65903fb002cf8db2158d26ef7e
Author: Campbell Barton
Date:   Sun Jul 30 02:17:11 2017 +1000
Branches: blender2.8
https://developer.blender.org/rBbe97238308a88d65903fb002cf8db2158d26ef7e

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.

===================================================================

M	source/blender/draw/intern/draw_manager.c

===================================================================

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 */




More information about the Bf-blender-cvs mailing list