[Bf-blender-cvs] [377915b0814] blender2.8: DRW: Make use of DRWInstanceData.

Clément Foucault noreply at git.blender.org
Tue Jan 9 15:17:27 CET 2018


Commit: 377915b08144e0945ed1984338def3dcad267a6d
Author: Clément Foucault
Date:   Tue Jan 9 14:21:55 2018 +0100
Branches: blender2.8
https://developer.blender.org/rB377915b08144e0945ed1984338def3dcad267a6d

DRW: Make use of DRWInstanceData.

This modify the selection code quite a bit but it's for the better.
When using selection we use the same batching / instancing process but we draw each element at a time using a an offset to the first element we want to draw and by drawing only one element.
This result much less memory allocation and better draw time.

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

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

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

diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index eda2f775028..9aead1d4c33 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -88,6 +88,8 @@
 /* only for callbacks */
 #include "draw_cache_impl.h"
 
+#include "draw_instance_data.h"
+
 #include "draw_mode_engines.h"
 #include "engines/clay/clay_engine.h"
 #include "engines/eevee/eevee_engine.h"
@@ -221,6 +223,12 @@ struct DRWInterface {
 	/* Dynamic batch */
 	Gwn_Batch *instance_batch; /* contains instances attributes */
 	GLuint instance_vbo; /* same as instance_batch but generated from DRWCalls */
+	struct DRWInstanceData *inst_data;
+#ifdef USE_GPU_SELECT
+	struct DRWInstanceData *inst_selectid;
+	/* Override for single object instances. */
+	int override_selectid;
+#endif
 	int instance_count;
 	Gwn_VertFormat vbo_format;
 };
@@ -328,6 +336,7 @@ static struct DRWGlobalState {
 	DRWCallGenerate *last_callgenerate;
 	DRWCallDynamic *last_calldynamic;
 	DRWShadingGroup *last_shgroup;
+	DRWInstanceDataList *idatalist;
 
 	/* Rendering state */
 	GPUShader *shader;
@@ -686,12 +695,14 @@ static void drw_interface_create(DRWInterface *interface, GPUShader *shader)
 	interface->attribs_stride = 0;
 	interface->instance_vbo = 0;
 	interface->instance_batch = NULL;
+	interface->inst_data = NULL;
+	interface->uniforms = NULL;
+#ifdef USE_GPU_SELECT
+	interface->inst_selectid = NULL;
+	interface->override_selectid = -1;
+#endif
 
 	memset(&interface->vbo_format, 0, sizeof(Gwn_VertFormat));
-
-	interface->uniforms = NULL;
-	interface->attribs = NULL;
-	interface->attribs_first = NULL;
 }
 
 
@@ -729,14 +740,22 @@ static void drw_interface_uniform(DRWShadingGroup *shgroup, const char *name,
 	shgroup->interface.uniforms = uni;
 }
 
-static void drw_interface_attrib(DRWShadingGroup *shgroup, const char *name, DRWAttribType type, int size, bool dummy)
+static void drw_interface_attrib(DRWShadingGroup *shgroup, const char *name, DRWAttribType UNUSED(type), int size, bool dummy)
 {
-	DRWAttrib *attrib = BLI_mempool_alloc(DST.vmempool->attribs);
+	unsigned int attrib_id = shgroup->interface.attribs_count;
 	GLuint program = GPU_shader_get_program(shgroup->shader);
 
-	attrib->location = glGetAttribLocation(program, name);
-	attrib->type = type;
-	attrib->size = size;
+	shgroup->interface.attribs_loc[attrib_id] = glGetAttribLocation(program, name);
+	shgroup->interface.attribs_size[attrib_id] = size;
+	shgroup->interface.attribs_stride += size;
+	shgroup->interface.attribs_count += 1;
+
+	if (shgroup->type != DRW_SHG_INSTANCE) {
+		BLI_assert(size <= 4); /* Matrices are not supported by Gawain. */
+		GWN_vertformat_attr_add(&shgroup->interface.vbo_format, name, GWN_COMP_F32, size, GWN_FETCH_FLOAT);
+	}
+
+	BLI_assert(shgroup->interface.attribs_count < MAX_ATTRIB_COUNT);
 
 /* Adding attribute even if not found for now (to keep memory alignment).
  * Should ideally take vertex format automatically from batch eventually */
@@ -751,23 +770,6 @@ static void drw_interface_attrib(DRWShadingGroup *shgroup, const char *name, DRW
 #else
 	UNUSED_VARS(dummy);
 #endif
-
-	BLI_assert(BLI_strnlen(name, 32) < 32);
-	BLI_strncpy(attrib->name, name, 32);
-
-	shgroup->interface.attribs_count += 1;
-	BLI_assert(shgroup->interface.attribs_count < MAX_ATTRIB_COUNT);
-
-	/* 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;
 }
 
 /** \} */
@@ -965,14 +967,6 @@ void DRW_shgroup_free(struct DRWShadingGroup *shgroup)
 	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);
-
-	shgroup->interface.instance_batch = instances;
-}
-
 #define CALL_PREPEND(shgroup, call) { \
 	if (shgroup->calls == NULL) { \
 		shgroup->calls = call; \
@@ -985,10 +979,25 @@ void DRW_shgroup_instance_batch(DRWShadingGroup *shgroup, struct Gwn_Batch *inst
 	call->head.prev = NULL; \
 } ((void)0)
 
+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);
+
+	shgroup->interface.instance_batch = instances;
+
+#ifdef USE_GPU_SELECT
+	DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
+	call->head.select_id = g_DRW_select_id;
+
+	CALL_PREPEND(shgroup, call);
+#endif
+}
 
 void DRW_shgroup_call_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, float (*obmat)[4])
 {
 	BLI_assert(geom != NULL);
+	BLI_assert(shgroup->type == DRW_SHG_NORMAL);
 
 	DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
 
@@ -1010,6 +1019,7 @@ void DRW_shgroup_call_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, float (*obm
 void DRW_shgroup_call_object_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, Object *ob)
 {
 	BLI_assert(geom != NULL);
+	BLI_assert(shgroup->type == DRW_SHG_NORMAL);
 
 	DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
 
@@ -1031,6 +1041,7 @@ void DRW_shgroup_call_generate_add(
         float (*obmat)[4])
 {
 	BLI_assert(geometry_fn != NULL);
+	BLI_assert(shgroup->type == DRW_SHG_NORMAL);
 
 	DRWCallGenerate *call = BLI_mempool_alloc(DST.vmempool->calls_generate);
 
@@ -1074,43 +1085,30 @@ void DRW_shgroup_call_dynamic_add_array(DRWShadingGroup *shgroup, const void *at
 	DRWInterface *interface = &shgroup->interface;
 
 #ifdef USE_GPU_SELECT
-	if ((G.f & G_PICKSEL) && (interface->instance_count > 0)) {
-		DRWShadingGroup *original_shgroup = shgroup;
-		shgroup = BLI_mempool_alloc(DST.vmempool->shgroups);
-		memcpy(shgroup, original_shgroup, sizeof(DRWShadingGroup));
-
-		shgroup->calls = NULL;
-		shgroup->calls_first = NULL;
-
-		interface = &shgroup->interface;
-		interface->instance_count = 0;
-
-		/* Append */
-		if (shgroup->pass_parent->shgroups != NULL) {
-			shgroup->pass_parent->shgroups_last->next = shgroup;
-		}
-		else {
-			shgroup->pass_parent->shgroups = shgroup;
+	if (G.f & G_PICKSEL) {
+		if (interface->inst_selectid == NULL) {
+			interface->inst_selectid = DRW_instance_data_request(DST.idatalist, 1, 128);
 		}
-		shgroup->pass_parent->shgroups_last = shgroup;
-		shgroup->next = NULL;
+
+		int *select_id = DRW_instance_data_next(interface->inst_selectid);
+		*select_id = g_DRW_select_id;
 	}
 #endif
 
-	DRWCallDynamic *call = BLI_mempool_alloc(DST.vmempool->calls_dynamic);
-
-	CALL_PREPEND(shgroup, call);
-
 	BLI_assert(attr_len == interface->attribs_count);
 	UNUSED_VARS_NDEBUG(attr_len);
 
-	call->head.type = DRW_CALL_DYNAMIC;
-#ifdef USE_GPU_SELECT
-	call->head.select_id = g_DRW_select_id;
-#endif
+	if (interface->attribs_stride > 0) {
+		if (interface->inst_data == NULL) {
+			interface->inst_data = DRW_instance_data_request(DST.idatalist, interface->attribs_stride, 16);
+		}
+
+		float *data = DRW_instance_data_next(interface->inst_data);
 
-	if (interface->attribs_count != 0) {
-		memcpy((void *)call->data, attr, sizeof(void *) * interface->attribs_count);
+		for (int i = 0; i < interface->attribs_count; ++i) {
+			memcpy(data, attr[i], sizeof(float) * interface->attribs_size[i]);
+			data = data + interface->attribs_size[i];
+		}
 	}
 
 	interface->instance_count += 1;
@@ -1121,8 +1119,15 @@ void DRW_shgroup_set_instance_count(DRWShadingGroup *shgroup, int count)
 {
 	DRWInterface *interface = &shgroup->interface;
 
+	BLI_assert(interface->instance_count == 0);
 	BLI_assert(interface->attribs_count == 0);
 
+#ifdef USE_GPU_SELECT
+	if (G.f & G_PICKSEL) {
+		interface->override_selectid = g_DRW_select_id;
+	}
+#endif
+
 	interface->instance_count = count;
 }
 
@@ -1238,33 +1243,8 @@ static void shgroup_dynamic_batch(DRWShadingGroup *shgroup)
 		return;
 
 	/* Upload Data */
-	if (interface->vbo_format.attrib_ct == 0) {
-		for (DRWAttrib *attrib = interface->attribs_first; attrib; attrib = attrib->prev) {
-			BLI_assert(attrib->size <= 4); /* matrices have no place here for now */
-			if (attrib->type == DRW_ATTRIB_FLOAT) {
-				attrib->format_id = GWN_vertformat_attr_add(
-				        &interface->vbo_format, attrib->name, GWN_COMP_F32, attrib->size, GWN_FETCH_FLOAT);
-			}
-			else if (attrib->type == DRW_ATTRIB_INT) {
-				attrib->format_id = GWN_vertformat_attr_add(
-				        &interface->vbo_format, attrib->name, GWN_COMP_I8, attrib->size, GWN_FETCH_INT);
-			}
-			else {
-				BLI_assert(false);
-			}
-		}
-	}
-
 	Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&interface->vbo_format);
-	GWN_vertbuf_data_alloc(vbo, nbr);
-
-	int j = 0;
-	for (DRWCallDynamic *call = shgroup->calls_first; call; call = call->head.prev, j++) {
-		int i = 0;
-		for (DRWAttrib *attrib = interface->attribs_first; attrib; attrib = attrib->prev, i++) {
-			GWN_vertbuf_attr_set(vbo, attrib->format_id, j, call->data[i]);
-		}
-	}
+	GWN_vertbuf_data_set(vbo, nbr, DRW_instance_data_get(interface->inst_data), false);
 
 	/* TODO make the batch dynamic instead of freeing it every times */
 	if (shgroup->batch_geom)
@@ -1275,10 +1255,9 @@ static void shgroup_dynamic_batch(DRWShadingGroup *shgroup)
 
 static void shgroup_dynamic_instance(DRWShadingGroup *shgroup)
 {
-	int i = 0;
-	int offset = 0;
 	DRWInterface *interface = &shgroup->interface;
 	int buffer_size = 0;
+	void *data = NULL;
 
 	if (interface->instance_batch != NULL) {
 		return;
@@ -1293,26 +1272,8 @@ static void shgroup_dynamic_instance(DRWShadingGroup *shgroup)
 		return;
 	}
 
-	/* only once */
-	if (interface->attribs_stride == 0) {
-		for (DRWAttrib *attrib = interface->attribs_first; attrib; attrib = attrib->prev, i++) {
-			BLI_assert(attrib->type == DRW_ATTRIB_FLOAT); /* Only float for now */
-			interface->attribs_stride += attrib->size;
-			interface->attribs_size[i] = attrib->size;
-			interface->attribs_loc[i] = attrib->location;
-		}
-	}
-
 	/* Gather Data */
 	buffer_size = sizeof(float) * interface->attribs_stride * interface->instance_count;
-	float *data = MEM_mallocN(buffer_size, "Instance VBO data");
-
-	for (DRWCallDynamic *call = shg

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list