[Bf-blender-cvs] [7163ddf] wiggly-widgets: Initial VBO code for GPU subsurf.

Antony Riakiotakis noreply at git.blender.org
Tue Dec 16 18:10:32 CET 2014


Commit: 7163ddf53e6f5f67c59a8dfc14f60515f8f577c7
Author: Antony Riakiotakis
Date:   Tue Dec 16 16:51:53 2014 +0100
Branches: wiggly-widgets
https://developer.blender.org/rB7163ddf53e6f5f67c59a8dfc14f60515f8f577c7

Initial VBO code for GPU subsurf.

This commit adds a few generalizations to the VBO
code so that modifiers can create and populate their own GPU objects.

The VBO code originally supported CDDerivedMesh only. The design moves
slightly towards the viewport refactor where the rendering system
requests data from modifiers.

In this commit only basic support for vertices and normals is provided
and some features from blender's VBO system, such as mapping to
original faces, unique element indices for vertices and loose vertex/
and can be added later. The one feature that is missing now is the quick
navigation feature of the multires modifier (which uses the same code).

What we do have is full support for solid shading with multiple
materials, flat/smooth shading and a big performance boost.
Performance could

- Why this commit is made on the widget branch -

Facemap widgets need to avoid drawing the whole mesh when we do
collision detection on them. For subsurf drawing we need to iterate
through the whole mesh every time. What we need instead is sort
indexed elemet drawing according to the facemap each face belongs to.
This screams VBOs but since I was going to add that, I thought that
I could push it a bit further and add proper solid shading support.

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

M	source/blender/blenkernel/BKE_DerivedMesh.h
M	source/blender/blenkernel/intern/subsurf_ccg.c
M	source/blender/gpu/GPU_buffers.h
M	source/blender/gpu/intern/gpu_buffers.c

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

diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index da4fcb4..8b801d7 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -466,6 +466,10 @@ struct DerivedMesh {
 	                           void (*setMaterial)(void *userData, int matnr, void *attribs),
 	                           bool (*setFace)(void *userData, int index), void *userData);
 
+	struct GPUDrawObject *(*gpuObjectNew)(DerivedMesh *dm);
+	void (*copy_gpu_data)(DerivedMesh *dm, int type, float *varray, int *index,
+	                      int *mat_orig_to_new, void *user_data);
+	
 	/** Release reference to the DerivedMesh. This function decides internally
 	 * if the DerivedMesh will be freed, or cached for later use. */
 	void (*release)(DerivedMesh *dm);
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index c777fcd..f09cf44 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -72,6 +72,7 @@
 #include "GPU_draw.h"
 #include "GPU_extensions.h"
 #include "GPU_glew.h"
+#include "GPU_buffers.h"
 
 #include "CCGSubSurf.h"
 
@@ -1743,9 +1744,112 @@ static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d)
 	glNormal3fv(no);
 }
 
+static void ccgDM_copy_gpu_data(DerivedMesh *dm, int type, float *varray, int *index,
+                         int *mat_orig_to_new, void *user_data)
+{
+	
+}
+
+
+static GPUDrawObject *ccgDM_GPUObjectNew(DerivedMesh *dm) {
+	GPUBufferMaterial *mat;
+	int *mat_orig_to_new;
+	CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
+	CCGSubSurf *ss = ccgdm->ss;
+	GPUDrawObject *gdo;
+	DMFlagMat *faceFlags = ccgdm->faceFlags;
+	int gridSize = ccgSubSurf_getGridSize(ss);
+	int gridFaces = gridSize - 1;
+	int totmat = (faceFlags) ? dm->totmat : 1;
+	int *points_per_mat;
+	int i, curmat, curpoint, totface;
+
+	/* object contains at least one material (default included) so zero means uninitialized dm */
+	BLI_assert(totmat != 0);
+
+	totface = ccgSubSurf_getNumFaces(ss);
+
+	points_per_mat = MEM_callocN(sizeof(*points_per_mat) * totmat, "GPU_drawobject_new.mat_orig_to_new");
+	
+	if (faceFlags) {
+		for (i = 0; i < totface; i++) {
+			CCGFace *f = ccgdm->faceMap[i].face;
+			int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
+			int new_matnr = faceFlags[index].mat_nr;
+			points_per_mat[new_matnr] += gridFaces * gridFaces * 6;
+		}
+	}
+	else {
+		for (i = 0; i < totface; i++) {
+			points_per_mat[0] += gridFaces * gridFaces * 6;
+		}
+	}
+	
+	/* create the GPUDrawObject */
+	gdo = MEM_callocN(sizeof(GPUDrawObject), "GPUDrawObject");
+	gdo->totvert = totface * gridSize * gridSize;
+	gdo->totedge = totface * 2 * gridFaces * gridFaces;
+
+	/* count the number of materials used by this DerivedMesh */
+	for (i = 0; i < totmat; i++) {
+		if (points_per_mat[i] > 0)
+			gdo->totmaterial++;
+	}
+
+	/* allocate an array of materials used by this DerivedMesh */
+	gdo->materials = MEM_mallocN(sizeof(GPUBufferMaterial) * gdo->totmaterial,
+	                             "GPUDrawObject.materials");
+
+	/* initialize the materials array */
+	for (i = 0, curmat = 0, curpoint = 0; i < totmat; i++) {
+		if (points_per_mat[i] > 0) {
+			gdo->materials[curmat].start = curpoint;
+			gdo->materials[curmat].totpoint = 0;
+			gdo->materials[curmat].mat_nr = i;
+
+			curpoint += points_per_mat[i];
+			curmat++;
+		}
+	}
+
+	/* store total number of points used for triangles */
+	gdo->tot_triangle_point = curpoint;
+
+	mat_orig_to_new = MEM_callocN(sizeof(*mat_orig_to_new) * totmat,
+	                                             "GPUDrawObject.mat_orig_to_new");
+
+	/* build a map from the original material indices to the new
+	 * GPUBufferMaterial indices */
+	for (i = 0; i < gdo->totmaterial; i++)
+		mat_orig_to_new[gdo->materials[i].mat_nr] = i;
+
+	for (i = 0; i < totface; i++) {
+		CCGFace *f = ccgdm->faceMap[i].face;
+		int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
+		int new_matnr = faceFlags[index].mat_nr;
+	
+		mat = &gdo->materials[mat_orig_to_new[new_matnr]];
+
+		/* add triangle */
+		mat->totpoint += gridFaces * gridFaces * 6;
+	}
+
+
+	MEM_freeN(mat_orig_to_new);
+	MEM_freeN(points_per_mat);
+
+	return gdo;
+}
+
 /* Only used by non-editmesh types */
 static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)[4], bool fast, DMSetMaterial setMaterial)
 {
+	GPU_vertex_setup(dm);
+	
+	GPU_buffer_unbind();
+
+#if 0
+	
 	CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
 	CCGSubSurf *ss = ccgdm->ss;
 	CCGKey key;
@@ -1868,6 +1972,8 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)
 			}
 		}
 	}
+
+#endif
 }
 
 static void ccgdm_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert)
@@ -3544,6 +3650,8 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
 
 	ccgdm->dm.drawMappedEdgesInterp = ccgDM_drawMappedEdgesInterp;
 	ccgdm->dm.drawMappedEdges = ccgDM_drawMappedEdges;
+	ccgdm->dm.gpuObjectNew = ccgDM_GPUObjectNew;
+	ccgdm->dm.copy_gpu_data = ccgDM_copy_gpu_data;
 	
 	ccgdm->dm.release = ccgDM_release;
 	
diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h
index 308d4cf..4a43b2c 100644
--- a/source/blender/gpu/GPU_buffers.h
+++ b/source/blender/gpu/GPU_buffers.h
@@ -50,6 +50,9 @@ struct GSet;
 struct GPUVertPointLink;
 struct PBVH;
 
+typedef void (*GPUBufferCopyFunc)(DerivedMesh *dm, float *varray, int *index,
+                                  int *mat_orig_to_new, void *user_data);
+
 typedef struct GPUBuffer {
 	int size;	/* in bytes */
 	void *pointer;	/* used with vertex arrays */
@@ -135,7 +138,6 @@ void GPU_global_buffer_pool_free_unused(void);
 GPUBuffer *GPU_buffer_alloc(int size, bool force_vertex_arrays);
 void GPU_buffer_free(GPUBuffer *buffer);
 
-GPUDrawObject *GPU_drawobject_new(struct DerivedMesh *dm);
 void GPU_drawobject_free(struct DerivedMesh *dm);
 
 /* called before drawing */
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index 1272b39..06d274b 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -69,6 +69,46 @@ typedef enum {
 	GPU_BUFFER_ELEMENT_STATE = (1 << 5),
 } GPUBufferState;
 
+typedef enum {
+	GPU_BUFFER_VERTEX = 0,
+	GPU_BUFFER_NORMAL,
+	GPU_BUFFER_COLOR,
+	GPU_BUFFER_UV,
+	GPU_BUFFER_UV_TEXPAINT,
+	GPU_BUFFER_EDGE,
+	GPU_BUFFER_UVEDGE,
+	GPU_BUFFER_FACEMAP
+} GPUBufferType;
+
+typedef struct {
+	GPUBufferCopyFunc copy;
+	GLenum gl_buffer_type;
+	int vector_size;
+} GPUBufferTypeSettings;
+
+static void GPU_buffer_copy_vertex(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *user);
+static void GPU_buffer_copy_normal(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *user);
+static void GPU_buffer_copy_mcol(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *user);
+static void GPU_buffer_copy_uv(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *user);
+static void GPU_buffer_copy_uv_texpaint(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *user);
+static void GPU_buffer_copy_edge(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *user);
+static void GPU_buffer_copy_uvedge(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *user);
+static void GPU_buffer_copy_facemap(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *user);
+
+static int gpu_buffer_size_from_type(DerivedMesh *dm, GPUBufferType type);
+
+const GPUBufferTypeSettings gpu_buffer_type_settings[] = {
+	{GPU_buffer_copy_vertex, GL_ARRAY_BUFFER_ARB, 3},
+	{GPU_buffer_copy_normal, GL_ARRAY_BUFFER_ARB, 3},
+	{GPU_buffer_copy_mcol, GL_ARRAY_BUFFER_ARB, 3},
+	{GPU_buffer_copy_uv, GL_ARRAY_BUFFER_ARB, 2},
+    {GPU_buffer_copy_uv_texpaint, GL_ARRAY_BUFFER_ARB, 4},
+	{GPU_buffer_copy_edge, GL_ELEMENT_ARRAY_BUFFER_ARB, 2},
+	{GPU_buffer_copy_uvedge, GL_ELEMENT_ARRAY_BUFFER_ARB, 4},
+	{GPU_buffer_copy_facemap, GL_ELEMENT_ARRAY_BUFFER_ARB, 4}
+};
+
+
 #define MAX_GPU_ATTRIB_DATA 32
 
 #define BUFFER_OFFSET(n) ((GLubyte *)NULL + (n))
@@ -501,7 +541,7 @@ static void gpu_drawobject_init_vert_points(GPUDrawObject *gdo, MFace *f, int to
 
 /* see GPUDrawObject's structure definition for a description of the
  * data being initialized here */
-GPUDrawObject *GPU_drawobject_new(DerivedMesh *dm)
+static GPUDrawObject *GPU_drawobject_new(DerivedMesh *dm)
 {
 	GPUDrawObject *gdo;
 	MFace *mface;
@@ -605,8 +645,7 @@ typedef void (*GPUBufferCopyFunc)(DerivedMesh *dm, float *varray, int *index,
                                   int *mat_orig_to_new, void *user_data);
 
 static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
-                                   int vector_size, int size, GLenum target,
-                                   void *user, GPUBufferCopyFunc copy_f)
+                                   int type, void *user)
 {
 	GPUBufferPool *pool;
 	GPUBuffer *buffer;
@@ -614,6 +653,10 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
 	int *mat_orig_to_new;
 	int *cur_index_per_mat;
 	int i;
+	const GPUBufferTypeSettings *ts = &gpu_buffer_type_settings[type];
+	GLenum target = ts->gl_buffer_type;
+	int vector_size = ts->vector_size;
+	int size = gpu_buffer_size_from_type(dm, type);
 	bool use_VBOs = (GLEW_ARB_vertex_buffer_object) && !(U.gameflags & USER_DISABLE_VBO);
 	GLboolean uploaded;
 
@@ -670,7 +713,10 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
 			uploaded = GL_FALSE;
 			/* attempt to upload the data to the VBO */
 			while (uploaded == GL_FALSE) {
-				(*copy_f)(dm, varray, cur_index_per_mat, mat_orig_to_new, user);
+				if (dm->copy_gpu_data)
+					dm->copy_gpu_data(dm, type, varray, cur_index_per_mat, mat_orig_to_new, user);
+				else
+					ts->copy(dm, varray, cur_index_per_mat, mat_orig_to_new, user);
 				/* glUnmapBuffer returns GL_FALSE if
 				 * the data store is corrupted; retry
 				 * in that case */
@@ -687,7 +733,10 @@ static GPUBuffer *gpu_buffer_setup(D

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list