[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