[Bf-blender-cvs] [6695dd5] GPU_data_request: store index buffers in VRAM

Mike Erwin noreply at git.blender.org
Thu Apr 16 22:12:43 CEST 2015


Commit: 6695dd5eea421a6ae8b44986a592d9b9a8c21369
Author: Mike Erwin
Date:   Thu Apr 16 16:11:55 2015 -0400
Branches: GPU_data_request
https://developer.blender.org/rB6695dd5eea421a6ae8b44986a592d9b9a8c21369

store index buffers in VRAM

With this change, smooth solid meshes draw faster in the new viewport
than old with VBOs.

Wireframe was already faster, now it's CRAZY fast.

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

M	source/blender/editors/space_view3d/drawobject.c
M	source/blender/gpu/GPUx_element.h
M	source/blender/gpu/intern/gpux_draw.c
M	source/blender/gpu/intern/gpux_element.c
M	source/blender/gpu/intern/gpux_element_private.h

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

diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index ea45d08..3bc717a 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -4515,6 +4515,7 @@ static bool draw_mesh_object_new_new(Scene *scene, ARegion *ar, View3D *v3d, Reg
 //				glShadeModel(GL_SMOOTH);
 
 				GPUx_vertex_buffer_prime(verts);
+				GPUx_element_list_prime(elem);
 
 				dm->gpux_batch->prim_type = GL_TRIANGLES;
 				dm->gpux_batch->buff = verts;
@@ -4535,6 +4536,7 @@ static bool draw_mesh_object_new_new(Scene *scene, ARegion *ar, View3D *v3d, Reg
 				}
 
 				GPUx_vertex_buffer_prime(verts);
+				GPUx_element_list_prime(elem);
 
 				dm->gpux_batch->prim_type = GL_LINES;
 				dm->gpux_batch->buff = verts;
diff --git a/source/blender/gpu/GPUx_element.h b/source/blender/gpu/GPUx_element.h
index d57be96..8007dab7 100644
--- a/source/blender/gpu/GPUx_element.h
+++ b/source/blender/gpu/GPUx_element.h
@@ -21,4 +21,9 @@ void GPUx_set_triangle_vertices(ElementList*, unsigned prim_idx, unsigned v1, un
 
 void GPUx_optimize(ElementList*); /* optionally call this after setting all vertex indices */
 
+/* prime does all the setup(create VBO, send to GPU, etc.) so use_primed doesn't have to */
+void GPUx_element_list_prime(ElementList*);
+void GPUx_element_list_use_primed(const ElementList*);
+void GPUx_element_list_done_using(const ElementList*);
+
 #endif /* BLENDER_GL_ELEMENT_LIST */
diff --git a/source/blender/gpu/intern/gpux_draw.c b/source/blender/gpu/intern/gpux_draw.c
index 7d4549d..c26d146 100644
--- a/source/blender/gpu/intern/gpux_draw.c
+++ b/source/blender/gpu/intern/gpux_draw.c
@@ -32,8 +32,11 @@ void GPUx_draw_points(const VertexBuffer *vbo, const ElementList *el, const Poin
 #ifdef REALLY_DRAW
 	GPUx_vertex_buffer_use_primed(vbo);
 
-	if (el)
-		glDrawRangeElements(GL_POINTS, min_index(el), max_index(el), el->prim_ct, el->index_type, el->indices);
+	if (el) {
+		GPUx_element_list_use_primed(el);
+		glDrawRangeElements(GL_POINTS, min_index(el), max_index(el), el->prim_ct, el->index_type, index_ptr(el));
+		GPUx_element_list_done_using(el);
+	}
 	else
 		glDrawArrays(GL_POINTS, 0, GPUx_vertex_ct(vbo));
 
@@ -56,8 +59,11 @@ void GPUx_draw_lines(const VertexBuffer *vbo, const ElementList *el, const LineD
 #ifdef REALLY_DRAW
 	GPUx_vertex_buffer_use_primed(vbo);
 
-	if (el)
-		glDrawRangeElements(GL_LINES, min_index(el), max_index(el), el->prim_ct * 2, el->index_type, el->indices);
+	if (el) {
+		GPUx_element_list_use_primed(el);
+		glDrawRangeElements(GL_LINES, min_index(el), max_index(el), el->prim_ct * 2, el->index_type, index_ptr(el));
+		GPUx_element_list_done_using(el);
+	}
 	else
 		glDrawArrays(GL_LINES, 0, chop_to_multiple(GPUx_vertex_ct(vbo), 2));
 
@@ -80,8 +86,11 @@ void GPUx_draw_triangles(const VertexBuffer *vbo, const ElementList *el, const P
 #ifdef REALLY_DRAW
 	GPUx_vertex_buffer_use_primed(vbo);
 
-	if (el)
-		glDrawRangeElements(GL_TRIANGLES, min_index(el), max_index(el), el->prim_ct * 3, el->index_type, el->indices);
+	if (el) {
+		GPUx_element_list_use_primed(el);
+		glDrawRangeElements(GL_TRIANGLES, min_index(el), max_index(el), el->prim_ct * 3, el->index_type, index_ptr(el));
+		GPUx_element_list_done_using(el);
+	}
 	else
 		glDrawArrays(GL_TRIANGLES, 0, chop_to_multiple(GPUx_vertex_ct(vbo), 3));
 
@@ -122,9 +131,11 @@ void GPUx_draw_primitives(const VertexBuffer *vbo, const ElementList *el, const
 
 #ifdef REALLY_DRAW
 	GPUx_vertex_buffer_use_primed(vbo);
+	GPUx_element_list_use_primed(el);
 
-	glDrawRangeElements(el->prim_type, min_index(el), max_index(el), el->prim_ct * vert_per_prim, el->index_type, el->indices);
+	glDrawRangeElements(el->prim_type, min_index(el), max_index(el), el->prim_ct * vert_per_prim, el->index_type, index_ptr(el));
 
+	GPUx_element_list_done_using(el);
 	GPUx_vertex_buffer_done_using(vbo);
 #endif /* REALLY_DRAW */
 }
@@ -185,9 +196,12 @@ void GPUx_draw_batch(const GPUxBatch *batch)
 #ifdef REALLY_DRAW
 	GPUx_vertex_buffer_use_primed(batch->buff);
 
-	if (batch->elem)
+	if (batch->elem) {
+		GPUx_element_list_use_primed(batch->elem);
 		glDrawRangeElements(batch->prim_type, min_index(batch->elem), max_index(batch->elem),
-		                    batch->elem->prim_ct * vert_per_prim, batch->elem->index_type, batch->elem->indices);
+		                    batch->elem->prim_ct * vert_per_prim, batch->elem->index_type, index_ptr(batch->elem));
+		GPUx_element_list_done_using(batch->elem);
+	}
 	else
 		glDrawArrays(batch->prim_type, 0, chop_to_multiple(GPUx_vertex_ct(batch->buff), vert_per_prim));
 
diff --git a/source/blender/gpu/intern/gpux_element.c b/source/blender/gpu/intern/gpux_element.c
index a92ef94..12d2689 100644
--- a/source/blender/gpu/intern/gpux_element.c
+++ b/source/blender/gpu/intern/gpux_element.c
@@ -2,6 +2,8 @@
 #include "gpux_element_private.h"
 #include <stdlib.h>
 
+/* private functions */
+
 #ifdef TRACK_INDEX_RANGE
 static void track_index_range(ElementList *el, unsigned v)
 {
@@ -30,6 +32,20 @@ unsigned max_index(const ElementList *el)
 #endif /* TRACK_INDEX_RANGE */
 }
 
+const void *index_ptr(const ElementList *el)
+{
+#ifdef USE_ELEM_VBO
+	if (el->vbo_id) /* primed, data lives in buffer object */
+		return (const void*)0;
+	else /* data lives in client memory */
+		return el->indices;
+#else
+	return el->indices;
+#endif /* USE_ELEM_VBO */
+}
+
+/* public functions */
+
 ElementList *GPUx_element_list_create(GLenum prim_type, unsigned prim_ct, unsigned max_index)
 {
 	ElementList *el;
@@ -80,6 +96,11 @@ ElementList *GPUx_element_list_create(GLenum prim_type, unsigned prim_ct, unsign
 
 void GPUx_element_list_discard(ElementList *el)
 {
+#ifdef USE_ELEM_VBO
+	if (el->vbo_id)
+		glDeleteBuffers(1, &el->vbo_id);
+#endif /* USE_ELEM_VBO */
+
 	free(el->indices);
 	free(el);
 }
@@ -212,3 +233,58 @@ void GPUx_optimize(ElementList *el)
 
 	/* TODO: (optional) rearrange vertex attrib buffer to improve mem locality */
 }
+
+void GPUx_element_list_prime(ElementList *el)
+{
+#ifdef USE_ELEM_VBO
+	int prim_vertex_ct = 0, index_size = 0, total_size;
+
+#ifdef TRUST_NO_ONE
+	assert(el->vbo_id == 0);
+  #endif /* TRUST_NO_ONE */
+
+	if (el->prim_type == GL_POINTS)
+		prim_vertex_ct = 1;
+	else if (el->prim_type == GL_LINES)
+		prim_vertex_ct = 2;
+	else if (el->prim_type == GL_TRIANGLES)
+		prim_vertex_ct = 3;
+
+	if (el->index_type == GL_UNSIGNED_BYTE)
+		index_size = sizeof(GLubyte);
+	else if (el->index_type == GL_UNSIGNED_SHORT)
+		index_size = sizeof(GLushort);
+	else if (el->index_type == GL_UNSIGNED_INT)
+		index_size = sizeof(GLuint);
+
+	total_size = prim_vertex_ct * el->prim_ct * index_size;
+
+	glGenBuffers(1, &el->vbo_id);
+	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, el->vbo_id);
+	/* fill with delicious data & send to GPU the first time only */
+	glBufferData(GL_ELEMENT_ARRAY_BUFFER, total_size, el->indices, GL_STATIC_DRAW);
+	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+#else
+	(void)el;
+#endif /* USE_ELEM_VBO */
+}
+
+void GPUx_element_list_use_primed(const ElementList *el)
+{
+#ifdef USE_ELEM_VBO
+  #ifdef TRUST_NO_ONE
+	assert(el->vbo_id);
+  #endif /* TRUST_NO_ONE */
+	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, el->vbo_id);
+#else
+	(void)el;
+#endif /* USE_ELEM_VBO */
+}
+
+void GPUx_element_list_done_using(const ElementList *el)
+{
+	(void)el;
+#ifdef USE_ELEM_VBO
+	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+#endif /* USE_ELEM_VBO */
+}
diff --git a/source/blender/gpu/intern/gpux_element_private.h b/source/blender/gpu/intern/gpux_element_private.h
index cac43b8..10673fc 100644
--- a/source/blender/gpu/intern/gpux_element_private.h
+++ b/source/blender/gpu/intern/gpux_element_private.h
@@ -7,19 +7,31 @@
 /* track min & max observed index (for glDrawRangeElements) */
 #define TRACK_INDEX_RANGE
 
+/* VBOs are guaranteed for any GL >= 1.5
+* They can be turned off here (mostly for comparison). */
+#define USE_ELEM_VBO
+
 struct ElementList {
 	unsigned prim_ct; 
 	GLenum prim_type; /* GL_POINTS, GL_LINES, GL_TRIANGLES */
 	GLenum index_type; /* GL_UNSIGNED_BYTE, _SHORT (ES), also _INT (full GL) */
 	unsigned max_allowed_index;
+
 #ifdef TRACK_INDEX_RANGE
 	unsigned min_observed_index;
 	unsigned max_observed_index;
 #endif /* TRACK_INDEX_RANGE */
+
+#ifdef USE_ELEM_VBO
+	GLuint vbo_id;
+#endif /* USE_ELEM_VBO */
+
 	void *indices; /* array of index_type */
 };
 
 unsigned min_index(const ElementList*);
 unsigned max_index(const ElementList*);
 
+const void *index_ptr(const ElementList*); /* for glDrawElements */
+
 #endif /* BLENDER_GL_ELEMENT_LIST_PRIVATE */




More information about the Bf-blender-cvs mailing list