[Bf-blender-cvs] [ed555750eb8] blender2.8: DRW: Use pseudo persistent memory pool for the rendering data structure.

Clément Foucault noreply at git.blender.org
Mon Nov 6 17:43:18 CET 2017


Commit: ed555750eb8294005f54425094cb692f29830631
Author: Clément Foucault
Date:   Mon Nov 6 16:47:23 2017 +0100
Branches: blender2.8
https://developer.blender.org/rBed555750eb8294005f54425094cb692f29830631

DRW: Use pseudo persistent memory pool for the rendering data structure.

This gets rid of the bottleneck of allocation / free of thousands of elements every frame.

Cache time (Eevee) (test scene is default file with cube duplicated 3241 times)
pre-patch: 23ms
post-patch: 14ms

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

M	source/blender/draw/intern/draw_manager.c
M	source/blender/gpu/GPU_viewport.h
M	source/blender/gpu/intern/gpu_viewport.c

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

diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 57489153ba0..f18bc9969b1 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -27,6 +27,7 @@
 
 #include "BLI_dynstr.h"
 #include "BLI_listbase.h"
+#include "BLI_mempool.h"
 #include "BLI_rect.h"
 #include "BLI_string.h"
 
@@ -130,13 +131,6 @@
 /* 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"
@@ -147,6 +141,7 @@
 
 
 #define MAX_ATTRIB_NAME 32
+#define MAX_ATTRIB_COUNT 6 /* Can be adjusted for more */
 #define MAX_PASS_NAME 32
 #define MAX_CLIP_PLANES 6 /* GL_MAX_CLIP_PLANES is at least 6 */
 
@@ -177,7 +172,7 @@ typedef enum {
 } DRWAttribType;
 
 struct DRWUniform {
-	struct DRWUniform *next, *prev;
+	struct DRWUniform *next;
 	DRWUniformType type;
 	int location;
 	int length;
@@ -186,7 +181,7 @@ struct DRWUniform {
 };
 
 typedef struct DRWAttrib {
-	struct DRWAttrib *next, *prev;
+	struct DRWAttrib *prev;
 	char name[MAX_ATTRIB_NAME];
 	int location;
 	int format_id;
@@ -195,8 +190,9 @@ typedef struct DRWAttrib {
 } DRWAttrib;
 
 struct DRWInterface {
-	ListBase uniforms;   /* DRWUniform */
-	ListBase attribs;    /* DRWAttrib */
+	DRWUniform *uniforms;   /* DRWUniform, single-linked list */
+	DRWAttrib *attribs;     /* DRWAttrib, single-linked list */
+	DRWAttrib *attribs_first; /* First added attrib to traverse in the right order */
 	int attribs_count;
 	int attribs_stride;
 	int attribs_size[16];
@@ -227,15 +223,16 @@ struct DRWInterface {
 };
 
 struct DRWPass {
-	ListBase shgroups; /* DRWShadingGroup */
+	/* Single linked list with last member to append */
+	DRWShadingGroup *shgroups;
+	DRWShadingGroup *shgroups_last;
+
 	DRWState state;
 	char name[MAX_PASS_NAME];
 };
 
 typedef struct DRWCallHeader {
-#ifndef USE_MEM_ITER
-	void *next, *prev;
-#endif
+	void *prev;
 
 #ifdef USE_GPU_SELECT
 	int select_id;
@@ -265,21 +262,18 @@ typedef struct DRWCallGenerate {
 typedef struct DRWCallDynamic {
 	DRWCallHeader head;
 
-	const void *data[];
+	const void *data[MAX_ATTRIB_COUNT];
 } DRWCallDynamic;
 
 struct DRWShadingGroup {
-	struct DRWShadingGroup *next, *prev;
+	struct DRWShadingGroup *next;
 
 	GPUShader *shader;               /* Shader to bind */
-	DRWInterface *interface;         /* Uniforms pointers */
+	DRWInterface interface;          /* Uniforms pointers */
 
 	/* DRWCall or DRWCallDynamic depending of type */
-#ifdef USE_MEM_ITER
-	BLI_memiter *calls;
-#else
-	ListBase calls;
-#endif
+	void *calls;
+	void *calls_first; /* To be able to traverse the list in the order of addition */
 
 	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) */
@@ -322,6 +316,15 @@ enum {
 
 /** Render State: No persistent data between draw calls. */
 static struct DRWGlobalState {
+	/* Cache generation */
+	ViewportMemoryPool *vmempool;
+	DRWUniform *last_uniform;
+	DRWAttrib *last_attrib;
+	DRWCall *last_call;
+	DRWCallGenerate *last_callgenerate;
+	DRWCallDynamic *last_calldynamic;
+	DRWShadingGroup *last_shgroup;
+
 	/* Rendering state */
 	GPUShader *shader;
 
@@ -652,10 +655,8 @@ void DRW_shader_free(GPUShader *shader)
 /** \name Interface (DRW_interface)
  * \{ */
 
-static DRWInterface *DRW_interface_create(GPUShader *shader)
+static void DRW_interface_create(DRWInterface *interface, GPUShader *shader)
 {
-	DRWInterface *interface = MEM_mallocN(sizeof(DRWInterface), "DRWInterface");
-
 	interface->model = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_MODEL);
 	interface->modelinverse = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_MODEL_INV);
 	interface->modelview = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_MODELVIEW);
@@ -681,21 +682,11 @@ static DRWInterface *DRW_interface_create(GPUShader *shader)
 
 	memset(&interface->vbo_format, 0, sizeof(Gwn_VertFormat));
 
-	BLI_listbase_clear(&interface->uniforms);
-	BLI_listbase_clear(&interface->attribs);
-
-	return interface;
+	interface->uniforms = NULL;
+	interface->attribs = NULL;
+	interface->attribs_first = NULL;
 }
 
-#ifdef USE_GPU_SELECT
-static DRWInterface *DRW_interface_duplicate(DRWInterface *interface_src)
-{
-	DRWInterface *interface_dst = MEM_dupallocN(interface_src);
-	BLI_duplicatelist(&interface_dst->uniforms, &interface_src->uniforms);
-	BLI_duplicatelist(&interface_dst->attribs, &interface_src->attribs);
-	return interface_dst;
-}
-#endif
 
 static void DRW_interface_uniform(DRWShadingGroup *shgroup, const char *name,
                                   DRWUniformType type, const void *value, int length, int arraysize)
@@ -716,7 +707,7 @@ static void DRW_interface_uniform(DRWShadingGroup *shgroup, const char *name,
 		return;
 	}
 
-	DRWUniform *uni = MEM_mallocN(sizeof(DRWUniform), "DRWUniform");
+	DRWUniform *uni = BLI_mempool_alloc(DST.vmempool->uniforms);
 
 	BLI_assert(arraysize > 0);
 
@@ -726,12 +717,14 @@ static void DRW_interface_uniform(DRWShadingGroup *shgroup, const char *name,
 	uni->length = length;
 	uni->arraysize = arraysize;
 
-	BLI_addtail(&shgroup->interface->uniforms, uni);
+	/* Prepend */
+	uni->next = shgroup->interface.uniforms;
+	shgroup->interface.uniforms = uni;
 }
 
 static void DRW_interface_attrib(DRWShadingGroup *shgroup, const char *name, DRWAttribType type, int size, bool dummy)
 {
-	DRWAttrib *attrib = MEM_mallocN(sizeof(DRWAttrib), "DRWAttrib");
+	DRWAttrib *attrib = BLI_mempool_alloc(DST.vmempool->attribs);
 	GLuint program = GPU_shader_get_program(shgroup->shader);
 
 	attrib->location = glGetAttribLocation(program, name);
@@ -755,9 +748,19 @@ static void DRW_interface_attrib(DRWShadingGroup *shgroup, const char *name, DRW
 	BLI_assert(BLI_strnlen(name, 32) < 32);
 	BLI_strncpy(attrib->name, name, 32);
 
-	shgroup->interface->attribs_count += 1;
+	shgroup->interface.attribs_count += 1;
+	BLI_assert(shgroup->interface.attribs_count < MAX_ATTRIB_COUNT);
 
-	BLI_addtail(&shgroup->interface->attribs, attrib);
+	/* Prepend */
+	if (shgroup->interface.attribs == NULL) {
+		shgroup->interface.attribs = attrib;
+		shgroup->interface.attribs_first = attrib;
+	}
+	else {
+		shgroup->interface.attribs->prev = attrib;
+		shgroup->interface.attribs = attrib;
+	}
+	attrib->prev = NULL;
 }
 
 /** \} */
@@ -770,23 +773,30 @@ 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);
+	DRWShadingGroup *shgroup = BLI_mempool_alloc(DST.vmempool->shgroups);
+
+	/* Append */
+	if (pass->shgroups != NULL) {
+		pass->shgroups_last->next = shgroup;
+	}
+	else {
+		pass->shgroups = shgroup;
+	}
+	pass->shgroups_last = shgroup;
+	shgroup->next = NULL;
+
+	DRW_interface_create(&shgroup->interface, shader);
 
 	shgroup->type = DRW_SHG_NORMAL;
 	shgroup->shader = shader;
-	shgroup->interface = DRW_interface_create(shader);
 	shgroup->state_extra = 0;
 	shgroup->state_extra_disable = ~0x0;
 	shgroup->batch_geom = NULL;
 	shgroup->instance_geom = NULL;
 	shgroup->instance_data = NULL;
 
-#ifdef USE_MEM_ITER
-	shgroup->calls = BLI_memiter_create(BLI_MEMITER_DEFAULT_SIZE);
-#else
-	BLI_listbase_clear(&shgroup->calls);
-#endif
+	shgroup->calls = NULL;
+	shgroup->calls_first = NULL;
 
 #ifdef USE_GPU_SELECT
 	shgroup->pass_parent = pass;
@@ -885,7 +895,7 @@ DRWShadingGroup *DRW_shgroup_material_empty_tri_batch_create(
 
 	if (shgroup) {
 		shgroup->type = DRW_SHG_TRIANGLE_BATCH;
-		shgroup->interface->instance_count = size * 3;
+		shgroup->interface.instance_count = size * 3;
 		DRW_interface_attrib(shgroup, "dummy", DRW_ATTRIB_FLOAT, 1, true);
 	}
 
@@ -930,7 +940,7 @@ DRWShadingGroup *DRW_shgroup_empty_tri_batch_create(struct GPUShader *shader, DR
 	DRWShadingGroup *shgroup = DRW_shgroup_create(shader, pass);
 
 	shgroup->type = DRW_SHG_TRIANGLE_BATCH;
-	shgroup->interface->instance_count = size * 3;
+	shgroup->interface.instance_count = size * 3;
 	DRW_interface_attrib(shgroup, "dummy", DRW_ATTRIB_FLOAT, 1, true);
 
 	return shgroup;
@@ -938,46 +948,43 @@ 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);
-
-	if (shgroup->interface->instance_vbo &&
-	    (shgroup->interface->instance_batch == 0))
+	if (shgroup->interface.instance_vbo &&
+	    (shgroup->interface.instance_batch == 0))
 	{
-		glDeleteBuffers(1, &shgroup->interface->instance_vbo);
+		glDeleteBuffers(1, &shgroup->interface.instance_vbo);
 	}
 
-	MEM_freeN(shgroup->interface);
-
 	GWN_BATCH_DISCARD_SAFE(shgroup->batch_geom);
 }
 
 void DRW_shgroup_instance_batch(DRWShadingGroup *shgroup, struct Gwn_Batch *instances)
 {
 	BLI_assert(shgroup->type == DRW_SHG_INSTANCE);
-	BLI_assert(shgroup->interface->instance_batch == NULL);
+	BLI_assert(shgroup->interface.instance_batch == NULL);
 
-	shgroup->interface->instance_batch = instances;
+	shgroup->interface.instance_batch = instances;
 }
 
+#define CALL_PREPEND(shgroup, call) { \
+	if (shgroup->calls == NULL) { \
+		shgroup->calls = call; \
+		shgroup->calls_first = call; \
+	} \
+	else { \
+		((typeof(call))shgroup->calls)->head.prev = call; \
+		shgroup->calls = call; \
+	} \
+	call->head.prev = NULL; \
+} ((void)0)
+
+
 void DRW_shgroup_call_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, float (*obmat)[4])
 {
 	BLI_assert(geom != NULL);
 
-	DRWCall *call;
+	DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
 
-#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
+	

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list