[Bf-blender-cvs] [ab7e7a005bd] blender2.8: GWN: Add new dynamic type of batches and remove

Clément Foucault noreply at git.blender.org
Wed Feb 14 19:02:38 CET 2018


Commit: ab7e7a005bde711d14493d51ee26ea297fa99e47
Author: Clément Foucault
Date:   Wed Feb 14 17:59:48 2018 +0100
Branches: blender2.8
https://developer.blender.org/rBab7e7a005bde711d14493d51ee26ea297fa99e47

GWN: Add new dynamic type of batches and remove

Theses batches keeps their memory chuck allocated after transfer to be reused and updated very often.

NOTE: This commit break instancing in DRW. (it's fixed in the next commit)

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

M	intern/gawain/gawain/gwn_vertex_buffer.h
M	intern/gawain/src/gwn_vertex_buffer.c
M	source/blender/draw/intern/draw_manager.c

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

diff --git a/intern/gawain/gawain/gwn_vertex_buffer.h b/intern/gawain/gawain/gwn_vertex_buffer.h
index 50a4e1aa2f6..34f12754f40 100644
--- a/intern/gawain/gawain/gwn_vertex_buffer.h
+++ b/intern/gawain/gawain/gwn_vertex_buffer.h
@@ -13,6 +13,7 @@
 
 #include "gwn_vertex_format.h"
 
+#define VRAM_USAGE 1
 // How to create a Gwn_VertBuf:
 // 1) verts = GWN_vertbuf_create() or GWN_vertbuf_init(verts)
 // 2) GWN_vertformat_attr_add(verts->format, ...)
@@ -24,15 +25,22 @@
 typedef struct Gwn_VertBuf {
 	Gwn_VertFormat format;
 	unsigned vertex_ct;
-	bool own_data; // does gawain own the data an is able to free it
+	unsigned alloc_ct; // size in vertex of alloced data
+#if VRAM_USAGE
+	unsigned vram_size; // size in byte of data present in the VRAM
+#endif
+	unsigned data_dirty : 1; // does the data has been touched since last transfert
+	unsigned data_dynamic : 1; // do we keep the RAM allocation for further updates?
+	unsigned data_resized : 1; // does the data has been resized since last transfert
 	GLubyte* data; // NULL indicates data in VRAM (unmapped) or not yet allocated
 	GLuint vbo_id; // 0 indicates not yet sent to VRAM
 } Gwn_VertBuf;
 
 Gwn_VertBuf* GWN_vertbuf_create(void);
 Gwn_VertBuf* GWN_vertbuf_create_with_format(const Gwn_VertFormat*);
+Gwn_VertBuf* GWN_vertbuf_create_dynamic_with_format(const Gwn_VertFormat*);
 
-void GWN_vertbuf_clear(Gwn_VertBuf* verts);
+void GWN_vertbuf_clear(Gwn_VertBuf*);
 void GWN_vertbuf_discard(Gwn_VertBuf*);
 
 void GWN_vertbuf_init(Gwn_VertBuf*);
@@ -40,7 +48,6 @@ void GWN_vertbuf_init_with_format(Gwn_VertBuf*, const Gwn_VertFormat*);
 
 unsigned GWN_vertbuf_size_get(const Gwn_VertBuf*);
 void GWN_vertbuf_data_alloc(Gwn_VertBuf*, unsigned v_ct);
-void GWN_vertbuf_data_set(Gwn_VertBuf*, unsigned v_ct, void* data, bool pass_ownership);
 void GWN_vertbuf_data_resize(Gwn_VertBuf*, unsigned v_ct);
 
 // The most important set_attrib variant is the untyped one. Get it right first.
diff --git a/intern/gawain/src/gwn_vertex_buffer.c b/intern/gawain/src/gwn_vertex_buffer.c
index 2bab0bc378b..32bef765390 100644
--- a/intern/gawain/src/gwn_vertex_buffer.c
+++ b/intern/gawain/src/gwn_vertex_buffer.c
@@ -38,6 +38,13 @@ Gwn_VertBuf* GWN_vertbuf_create_with_format(const Gwn_VertFormat* format)
 	// TODO: implement those memory savings
 	}
 
+Gwn_VertBuf* GWN_vertbuf_create_dynamic_with_format(const Gwn_VertFormat* format)
+	{
+	Gwn_VertBuf* verts = GWN_vertbuf_create_with_format(format);
+	verts->data_dynamic = true;
+	return verts;
+	}
+
 void GWN_vertbuf_init(Gwn_VertBuf* verts)
 	{
 	memset(verts, 0, sizeof(Gwn_VertBuf));
@@ -58,12 +65,12 @@ void GWN_vertbuf_clear(Gwn_VertBuf* verts)
 	{
 	if (verts->vbo_id) {
 		GWN_buf_id_free(verts->vbo_id);
-		vbo_memory_usage -= GWN_vertbuf_size_get(verts);
-	}
-#if KEEP_SINGLE_COPY
-	else
+#if VRAM_USAGE
+		vbo_memory_usage -= verts->vram_size;
 #endif
-	if (verts->data && verts->own_data)
+	}
+
+	if (verts->data)
 		{
 		free(verts->data);
 		verts->data = NULL;
@@ -75,12 +82,12 @@ void GWN_vertbuf_discard(Gwn_VertBuf* verts)
 	if (verts->vbo_id)
 		{
 		GWN_buf_id_free(verts->vbo_id);
-		vbo_memory_usage -= GWN_vertbuf_size_get(verts);
-		}
-#if KEEP_SINGLE_COPY
-	else
+#if VRAM_USAGE
+		vbo_memory_usage -= verts->vram_size;
 #endif
-	if (verts->data && verts->own_data)
+		}
+
+	if (verts->data)
 		{
 		free(verts->data);
 		}
@@ -101,33 +108,22 @@ void GWN_vertbuf_data_alloc(Gwn_VertBuf* verts, unsigned v_ct)
 		VertexFormat_pack(format);
 
 	verts->vertex_ct = v_ct;
-	verts->own_data = true;
 
 	// Data initially lives in main memory. Will be transferred to VRAM when we "prime" it.
 	verts->data = malloc(GWN_vertbuf_size_get(verts));
 	}
 
-void GWN_vertbuf_data_set(Gwn_VertBuf* verts, unsigned v_ct, void* data, bool pass_ownership)
-	{
-	Gwn_VertFormat* format = &verts->format;
-	if (!format->packed)
-		VertexFormat_pack(format);
-
-	verts->vertex_ct = v_ct;
-	verts->own_data = pass_ownership;
-
-	// Data initially lives in main memory. Will be transferred to VRAM when we "prime" it.
-	verts->data = data;
-	}
-
 void GWN_vertbuf_data_resize(Gwn_VertBuf* verts, unsigned v_ct)
 	{
 #if TRUST_NO_ONE
 	assert(verts->vertex_ct != v_ct); // allow this?
 	assert(verts->data != NULL); // has already been allocated
-	assert(verts->vbo_id == 0); // has not been sent to VRAM
+	assert(verts->vbo_id == 0 || verts->data_dynamic); // has not been sent to VRAM
 #endif
 
+	// for dynamic buffers
+	verts->data_resized = true;
+
 	verts->vertex_ct = v_ct;
 	verts->data = realloc(verts->data, GWN_vertbuf_size_get(verts));
 	// TODO: skip realloc if v_ct < existing vertex count
@@ -139,6 +135,8 @@ void GWN_vertbuf_attr_set(Gwn_VertBuf* verts, unsigned a_idx, unsigned v_idx, co
 	const Gwn_VertFormat* format = &verts->format;
 	const Gwn_VertAttr* a = format->attribs + a_idx;
 
+	verts->data_dirty = true;
+
 #if TRUST_NO_ONE
 	assert(a_idx < format->attrib_ct);
 	assert(v_idx < verts->vertex_ct);
@@ -153,6 +151,8 @@ void GWN_vertbuf_attr_fill(Gwn_VertBuf* verts, unsigned a_idx, const void* data)
 	const Gwn_VertFormat* format = &verts->format;
 	const Gwn_VertAttr* a = format->attribs + a_idx;
 
+	verts->data_dirty = true;
+
 #if TRUST_NO_ONE
 	assert(a_idx < format->attrib_ct);
 #endif
@@ -167,6 +167,8 @@ void GWN_vertbuf_attr_fill_stride(Gwn_VertBuf* verts, unsigned a_idx, unsigned s
 	const Gwn_VertFormat* format = &verts->format;
 	const Gwn_VertAttr* a = format->attribs + a_idx;
 
+	verts->data_dirty = true;
+
 #if TRUST_NO_ONE
 	assert(a_idx < format->attrib_ct);
 	assert(verts->data != NULL); // data must be in main mem
@@ -209,31 +211,58 @@ void GWN_vertbuf_attr_get_raw_data(Gwn_VertBuf* verts, unsigned a_idx, Gwn_VertB
 
 static void VertexBuffer_prime(Gwn_VertBuf* verts)
 	{
-	const unsigned buffer_sz = GWN_vertbuf_size_get(verts);
+	unsigned buffer_sz = GWN_vertbuf_size_get(verts);
+
+#if VRAM_USAGE
+	vbo_memory_usage += buffer_sz;
+	verts->vram_size = buffer_sz;
+#endif
 
 	verts->vbo_id = GWN_buf_id_alloc();
 	glBindBuffer(GL_ARRAY_BUFFER, verts->vbo_id);
 	// fill with delicious data & send to GPU the first time only
-	glBufferData(GL_ARRAY_BUFFER, buffer_sz, verts->data, GL_STATIC_DRAW);
-
-	vbo_memory_usage += buffer_sz;
+	glBufferData(GL_ARRAY_BUFFER, verts->vram_size, verts->data, (verts->data_dynamic) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
 
-#if KEEP_SINGLE_COPY
 	// now that GL has a copy, discard original
-	if (verts->own_data)
+	if (!verts->data_dynamic)
 		{
 		free(verts->data);
 		verts->data = NULL;
 		}
+
+	verts->data_dirty = false;
+	}
+
+static void VertexBuffer_update(Gwn_VertBuf* verts)
+	{
+	unsigned buffer_sz = GWN_vertbuf_size_get(verts);
+
+#if VRAM_USAGE
+	vbo_memory_usage -= verts->vram_size;
+	vbo_memory_usage += buffer_sz;
+	verts->vram_size = buffer_sz;
 #endif
+
+	glBindBuffer(GL_ARRAY_BUFFER, verts->vbo_id);
+
+	// fill with delicious data & send to GPU ... AGAIN
+	if (verts->data_resized)
+		glBufferData(GL_ARRAY_BUFFER, buffer_sz, verts->data, GL_DYNAMIC_DRAW);
+	else
+		glBufferSubData(GL_ARRAY_BUFFER, 0, buffer_sz, verts->data); // .. todo try glMapBuffer
+
+	verts->data_dirty = false;
+	verts->data_resized = false;
 	}
 
 void GWN_vertbuf_use(Gwn_VertBuf* verts)
 	{
-	if (verts->vbo_id)
-		glBindBuffer(GL_ARRAY_BUFFER, verts->vbo_id);
-	else
+	if (!verts->vbo_id)
 		VertexBuffer_prime(verts);
+	else if (verts->data_dirty)
+		VertexBuffer_update(verts);
+	else
+		glBindBuffer(GL_ARRAY_BUFFER, verts->vbo_id);
 	}
 
 unsigned GWN_vertbuf_get_memory_usage(void)
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index db1046039d5..6feab32f8e1 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -1188,13 +1188,9 @@ static void shgroup_dynamic_batch(DRWShadingGroup *shgroup)
 
 	/* Upload Data */
 	Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&interface->vbo_format);
-	if (interface->inst_data) {
-		GWN_vertbuf_data_set(vbo, nbr, DRW_instance_data_get(interface->inst_data), false);
-	} else {
 		/* Use unitialized memory. This is for dummy vertex buffers. */
 		/* XXX TODO do not alloc at all. */
 		GWN_vertbuf_data_alloc(vbo, nbr);
-	}
 
 	/* TODO make the batch dynamic instead of freeing it every times */
 	if (shgroup->batch_geom)
@@ -1218,13 +1214,9 @@ static void shgroup_dynamic_instance(DRWShadingGroup *shgroup)
 
 	/* Upload Data */
 	Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&interface->vbo_format);
-	if (interface->inst_data) {
-		GWN_vertbuf_data_set(vbo, nbr, DRW_instance_data_get(interface->inst_data), false);
-	} else {
 		/* Use unitialized memory. This is for dummy vertex buffers. */
 		/* XXX TODO do not alloc at all. */
 		GWN_vertbuf_data_alloc(vbo, nbr);
-	}
 
 	/* TODO make the batch dynamic instead of freeing it every times */
 	if (shgroup->instancing_geom)



More information about the Bf-blender-cvs mailing list