[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [44761] trunk/blender/source/blender/gpu/ intern/gpu_buffers.c: Optimize index buffers for multires drawing in sculpt mode.

Nicholas Bishop nicholasbishop at gmail.com
Fri Mar 9 10:30:18 CET 2012


Revision: 44761
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=44761
Author:   nicholasbishop
Date:     2012-03-09 09:30:03 +0000 (Fri, 09 Mar 2012)
Log Message:
-----------
Optimize index buffers for multires drawing in sculpt mode.

All multires grids have exactly the same ordering, so rather than
allocate a new index buffer for each PBVH node, just allocate one that
can be reused for every grid.

This requires more draw calls (one per grid rather than one per PBVH
node), but less graphics memory.

Modified Paths:
--------------
    trunk/blender/source/blender/gpu/intern/gpu_buffers.c

Modified: trunk/blender/source/blender/gpu/intern/gpu_buffers.c
===================================================================
--- trunk/blender/source/blender/gpu/intern/gpu_buffers.c	2012-03-09 06:04:17 UTC (rev 44760)
+++ trunk/blender/source/blender/gpu/intern/gpu_buffers.c	2012-03-09 09:30:03 UTC (rev 44761)
@@ -1453,73 +1453,95 @@
 #define FILL_QUAD_BUFFER(type_)                                         \
 	{                                                                   \
 		type_ *quad_data;                                               \
-		int offset = 0;                                                 \
-        int i, j, k;                                                    \
+        int i, j;                                                       \
                                                                         \
 		glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,                    \
-						sizeof(type_) * totquad * 4, NULL,              \
+						sizeof(type_) * (*totquad) * 4, NULL,           \
 						GL_STATIC_DRAW_ARB);                            \
                                                                         \
 		/* Fill the quad buffer */                                      \
 		quad_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB,         \
 								   GL_WRITE_ONLY_ARB);                  \
 		if(quad_data) {                                                 \
-			for(i = 0; i < totgrid; ++i) {                              \
+			for(i = 0; i < gridsize-1; ++i) {                           \
 				for(j = 0; j < gridsize-1; ++j) {                       \
-					for(k = 0; k < gridsize-1; ++k) {                   \
-						*(quad_data++)= offset + j*gridsize + k+1;      \
-						*(quad_data++)= offset + j*gridsize + k;        \
-						*(quad_data++)= offset + (j+1)*gridsize + k;    \
-						*(quad_data++)= offset + (j+1)*gridsize + k+1;  \
-					}                                                   \
+					*(quad_data++)= i*gridsize + j+1;                   \
+					*(quad_data++)= i*gridsize + j;                     \
+					*(quad_data++)= (i+1)*gridsize + j;                 \
+					*(quad_data++)= (i+1)*gridsize + j+1;               \
 				}                                                       \
-																		\
-				offset += gridsize*gridsize;                            \
 			}                                                           \
 			glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);              \
 		}                                                               \
 		else {                                                          \
-			glDeleteBuffersARB(1, &buffers->index_buf);                 \
-			buffers->index_buf = 0;                                     \
+			glDeleteBuffersARB(1, &buffer);                             \
+			buffer = 0;                                                 \
 		}                                                               \
 	}
 /* end FILL_QUAD_BUFFER */
 
-GPU_Buffers *GPU_build_grid_buffers(int totgrid, int gridsize)
+static GLuint gpu_get_grid_buffer(int gridsize, GLenum *index_type, unsigned *totquad)
 {
-	GPU_Buffers *buffers;
-	int totquad;
+	static int prev_gridsize = -1;
+	static GLenum prev_index_type = 0;
+	static GLuint buffer = 0;
+	static unsigned prev_totquad;
 
-	buffers = MEM_callocN(sizeof(GPU_Buffers), "GPU_Buffers");
+	/* VBO is disabled; delete the previous buffer (if it exists) and
+	   return an invalid handle */
+	if(!GLEW_ARB_vertex_buffer_object || (U.gameflags & USER_DISABLE_VBO)) {
+		if(buffer)
+			glDeleteBuffersARB(1, &buffer);
+		return 0;
+	}
 
-	/* Count the number of quads */
-	totquad= (gridsize-1)*(gridsize-1)*totgrid;
+	/* VBO is already built */
+	if(buffer && prev_gridsize == gridsize) {
+		*index_type = prev_index_type;
+		*totquad = prev_totquad;
+		return buffer;
+	}
 
-	/* Generate index buffer object */
-	if(GLEW_ARB_vertex_buffer_object && !(U.gameflags & USER_DISABLE_VBO))
-		glGenBuffersARB(1, &buffers->index_buf);
+	/* Build new VBO */
+	glGenBuffersARB(1, &buffer);
+	if(buffer) {
+		*totquad= (gridsize-1)*(gridsize-1);
 
-	if(buffers->index_buf) {
-		glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf);
+		glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffer);
 
-		if(totquad < USHRT_MAX) {
-			buffers->index_type = GL_UNSIGNED_SHORT;
+		if(*totquad < USHRT_MAX) {
+			*index_type = GL_UNSIGNED_SHORT;
 			FILL_QUAD_BUFFER(unsigned short);
 		}
 		else {
-			buffers->index_type = GL_UNSIGNED_INT;
+			*index_type = GL_UNSIGNED_INT;
 			FILL_QUAD_BUFFER(unsigned int);
 		}
 
 		glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
 	}
 
-	/* Build VBO */
+	prev_gridsize = gridsize;
+	prev_index_type = *index_type;
+	prev_totquad = *totquad;
+	return buffer;
+}
+
+GPU_Buffers *GPU_build_grid_buffers(int totgrid, int gridsize)
+{
+	GPU_Buffers *buffers;
+
+	buffers = MEM_callocN(sizeof(GPU_Buffers), "GPU_Buffers");
+
+	/* Build index VBO */
+	buffers->index_buf = gpu_get_grid_buffer(gridsize, &buffers->index_type, &buffers->tot_quad);
+	buffers->totgrid = totgrid;
+	buffers->gridsize = gridsize;
+
+	/* Build coord/normal VBO */
 	if(buffers->index_buf)
 		glGenBuffersARB(1, &buffers->vert_buf);
 
-	buffers->tot_quad = totquad;
-
 	return buffers;
 }
 
@@ -1642,10 +1664,16 @@
 		glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf);
 
 		if(buffers->tot_quad) {
-			glVertexPointer(3, GL_FLOAT, sizeof(DMGridData), (void*)offsetof(DMGridData, co));
-			glNormalPointer(GL_FLOAT, sizeof(DMGridData), (void*)offsetof(DMGridData, no));
+			unsigned offset = 0;
+			int i;
+			for(i = 0; i < buffers->totgrid; i++) {
+				glVertexPointer(3, GL_FLOAT, sizeof(DMGridData), offset + (char*)offsetof(DMGridData, co));
+				glNormalPointer(GL_FLOAT, sizeof(DMGridData), offset + (char*)offsetof(DMGridData, no));
+				
+				glDrawElements(GL_QUADS, buffers->tot_quad * 4, buffers->index_type, 0);
 
-			glDrawElements(GL_QUADS, buffers->tot_quad * 4, buffers->index_type, 0);
+				offset += buffers->gridsize * buffers->gridsize * sizeof(DMGridData);
+			}
 		}
 		else {
 			glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat), (void*)offsetof(VertexBufferFormat, co));
@@ -1674,7 +1702,7 @@
 	if(buffers) {
 		if(buffers->vert_buf)
 			glDeleteBuffersARB(1, &buffers->vert_buf);
-		if(buffers->index_buf)
+		if(buffers->index_buf && buffers->tot_tri)
 			glDeleteBuffersARB(1, &buffers->index_buf);
 
 		MEM_freeN(buffers);




More information about the Bf-blender-cvs mailing list