[Bf-blender-cvs] [c62468a] master: VBO implementation for GLSL subsurfed meshes (non-mapped case)

Antony Riakiotakis noreply at git.blender.org
Thu Oct 15 22:21:52 CEST 2015


Commit: c62468aabbdeae2c8e55ee5bfe86c73d98a123b2
Author: Antony Riakiotakis
Date:   Thu Oct 15 22:24:40 2015 +0300
Branches: master
https://developer.blender.org/rBc62468aabbdeae2c8e55ee5bfe86c73d98a123b2

VBO implementation for GLSL subsurfed meshes (non-mapped case)

As with cdderivedmesh, performance here is still CPU-limited if material
needs tangents/UVs/vcolors. Draw calls have much less overhead though.
Also, as with derivedmesh, kept an exception for old drawing for NVIDIA
+OSX+VBO off or setDrawOptions callback not being NULL.

setDrawOptions should be ommitable and fully VBOfialbe (?) in the
future, usually those just check for hidden flag of poly or similar.

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

M	source/blender/blenkernel/intern/subsurf_ccg.c

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

diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index f351ce0..a2c625a 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -2705,6 +2705,13 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)
 	GPU_buffers_unbind();
 }
 
+typedef struct {
+	DMVertexAttribs attribs;
+	int numdata;
+
+	GPUAttrib datatypes[GPU_MAX_ATTRIB]; /* TODO, messing up when switching materials many times - [#21056]*/
+} GPUMaterialConv;
+
 /* Only used by non-editmesh types */
 static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm,
                                       DMSetMaterial setMaterial,
@@ -2715,14 +2722,15 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm,
 	CCGSubSurf *ss = ccgdm->ss;
 	CCGKey key;
 	GPUVertexAttribs gattribs;
-	DMVertexAttribs attribs = {{{NULL}}};
-	/* MTFace *tf = dm->getTessFaceDataArray(dm, CD_MTFACE); */ /* UNUSED */
+	int a, b, do_draw, new_matnr;
+	DMFlagMat *faceFlags = ccgdm->faceFlags;
+	unsigned char *varray;
+	size_t max_element_size = 0;
+	int tot_loops = 0;
+	int totpoly = ccgSubSurf_getNumFaces(ss);
 	int gridSize = ccgSubSurf_getGridSize(ss);
 	int gridFaces = gridSize - 1;
 	int edgeSize = ccgSubSurf_getEdgeSize(ss);
-	DMFlagMat *faceFlags = ccgdm->faceFlags;
-	const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
-	int a, i, do_draw, numVerts, matnr, new_matnr, totface;
 
 #ifdef WITH_OPENSUBDIV
 	if (ccgdm->useGpuBackend) {
@@ -2791,154 +2799,358 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm,
 	}
 #endif
 
+	glShadeModel(GL_SMOOTH);
+
 	CCG_key_top_level(&key, ss);
 	ccgdm_pbvh_update(ccgdm);
 
-	do_draw = 0;
-	matnr = -1;
+	/* workaround for NVIDIA GPUs on Mac not supporting vertex arrays + interleaved formats, see T43342 */
+	if ((GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_MAC, GPU_DRIVER_ANY) && (U.gameflags & USER_DISABLE_VBO)) ||
+	        setDrawOptions != NULL)
+	{
+		const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
+		DMVertexAttribs attribs = {{{NULL}}};
+		int i;
+		int matnr = -1;
+		do_draw = 0;
 
 #define PASSATTRIB(dx, dy, vert) {                                            \
 	if (attribs.totorco)                                                      \
 		index = getFaceIndex(ss, f, S, x + dx, y + dy, edgeSize, gridSize);   \
 	else                                                                      \
 		index = 0;                                                            \
-	DM_draw_attrib_vertex(&attribs, a, index, vert, ((a) * 4) + vert);          \
+	DM_draw_attrib_vertex(&attribs, a, index, vert, ((a) * 4) + vert);        \
 } (void)0
 
-	totface = ccgSubSurf_getNumFaces(ss);
-	for (a = 0, i = 0; i < totface; i++) {
-		CCGFace *f = ccgdm->faceMap[i].face;
-		const float (*ln)[3] = NULL;
-		int S, x, y, drawSmooth;
-		int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
-		int origIndex = ccgDM_getFaceMapIndex(ss, f);
-		
-		numVerts = ccgSubSurf_getFaceNumVerts(f);
-
-		if (faceFlags) {
-			drawSmooth = (lnors || (faceFlags[index].flag & ME_SMOOTH));
-			new_matnr = faceFlags[index].mat_nr + 1;
-		}
-		else {
-			drawSmooth = 1;
-			new_matnr = 1;
-		}
-
-		if (lnors) {
-			ln = lnors;
-			lnors += (gridFaces * gridFaces * numVerts) * 4;
-		}
+		totpoly = ccgSubSurf_getNumFaces(ss);
+		for (a = 0, i = 0; i < totpoly; i++) {
+			CCGFace *f = ccgdm->faceMap[i].face;
+			const float (*ln)[3] = NULL;
+			int S, x, y, drawSmooth;
+			int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
+			int origIndex = ccgDM_getFaceMapIndex(ss, f);
 
-		if (new_matnr != matnr) {
-			do_draw = setMaterial(matnr = new_matnr, &gattribs);
-			if (do_draw)
-				DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
-		}
+			int numVerts = ccgSubSurf_getFaceNumVerts(f);
 
-		if (!do_draw || (setDrawOptions && (origIndex != ORIGINDEX_NONE) &&
-		                (setDrawOptions(userData, origIndex) == DM_DRAW_OPTION_SKIP)))
-		{
-			a += gridFaces * gridFaces * numVerts;
-			continue;
-		}
+			if (faceFlags) {
+				drawSmooth = (lnors || (faceFlags[index].flag & ME_SMOOTH));
+				new_matnr = faceFlags[index].mat_nr + 1;
+			}
+			else {
+				drawSmooth = 1;
+				new_matnr = 1;
+			}
 
-		glShadeModel(drawSmooth ? GL_SMOOTH : GL_FLAT);
-		for (S = 0; S < numVerts; S++) {
-			CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
-			CCGElem *vda, *vdb;
+			if (lnors) {
+				ln = lnors;
+				lnors += (gridFaces * gridFaces * numVerts) * 4;
+			}
 
-			if (ln) {
-				glBegin(GL_QUADS);
-				for (y = 0; y < gridFaces; y++) {
-					for (x = 0; x < gridFaces; x++) {
-						float *aco = CCG_grid_elem_co(&key, faceGridData, x, y);
-						float *bco = CCG_grid_elem_co(&key, faceGridData, x + 1, y);
-						float *cco = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
-						float *dco = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
+			if (new_matnr != matnr) {
+				do_draw = setMaterial(matnr = new_matnr, &gattribs);
+				if (do_draw)
+					DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
+			}
 
-						PASSATTRIB(0, 1, 1);
-						glNormal3fv(ln[1]);
-						glVertex3fv(dco);
-						PASSATTRIB(1, 1, 2);
-						glNormal3fv(ln[2]);
-						glVertex3fv(cco);
-						PASSATTRIB(1, 0, 3);
-						glNormal3fv(ln[3]);
-						glVertex3fv(bco);
-						PASSATTRIB(0, 0, 0);
-						glNormal3fv(ln[0]);
-						glVertex3fv(aco);
+			if (!do_draw || (setDrawOptions && (origIndex != ORIGINDEX_NONE) &&
+			                (setDrawOptions(userData, origIndex) == DM_DRAW_OPTION_SKIP)))
+			{
+				a += gridFaces * gridFaces * numVerts;
+				continue;
+			}
 
-						ln += 4;
-						a++;
+			glShadeModel(drawSmooth ? GL_SMOOTH : GL_FLAT);
+			for (S = 0; S < numVerts; S++) {
+				CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
+				CCGElem *vda, *vdb;
+
+				if (ln) {
+					glBegin(GL_QUADS);
+					for (y = 0; y < gridFaces; y++) {
+						for (x = 0; x < gridFaces; x++) {
+							float *aco = CCG_grid_elem_co(&key, faceGridData, x, y);
+							float *bco = CCG_grid_elem_co(&key, faceGridData, x + 1, y);
+							float *cco = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
+							float *dco = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
+
+							PASSATTRIB(0, 1, 1);
+							glNormal3fv(ln[1]);
+							glVertex3fv(dco);
+							PASSATTRIB(1, 1, 2);
+							glNormal3fv(ln[2]);
+							glVertex3fv(cco);
+							PASSATTRIB(1, 0, 3);
+							glNormal3fv(ln[3]);
+							glVertex3fv(bco);
+							PASSATTRIB(0, 0, 0);
+							glNormal3fv(ln[0]);
+							glVertex3fv(aco);
+
+							ln += 4;
+							a++;
+						}
 					}
+					glEnd();
 				}
-				glEnd();
-			}
-			else if (drawSmooth) {
-				for (y = 0; y < gridFaces; y++) {
-					glBegin(GL_QUAD_STRIP);
-					for (x = 0; x < gridFaces; x++) {
+				else if (drawSmooth) {
+					for (y = 0; y < gridFaces; y++) {
+						glBegin(GL_QUAD_STRIP);
+						for (x = 0; x < gridFaces; x++) {
+							vda = CCG_grid_elem(&key, faceGridData, x, y + 0);
+							vdb = CCG_grid_elem(&key, faceGridData, x, y + 1);
+
+							PASSATTRIB(0, 0, 0);
+							glNormal3fv(CCG_elem_no(&key, vda));
+							glVertex3fv(CCG_elem_co(&key, vda));
+
+							PASSATTRIB(0, 1, 1);
+							glNormal3fv(CCG_elem_no(&key, vdb));
+							glVertex3fv(CCG_elem_co(&key, vdb));
+
+							if (x != gridFaces - 1)
+								a++;
+						}
+
 						vda = CCG_grid_elem(&key, faceGridData, x, y + 0);
 						vdb = CCG_grid_elem(&key, faceGridData, x, y + 1);
-						
-						PASSATTRIB(0, 0, 0);
+
+						PASSATTRIB(0, 0, 3);
 						glNormal3fv(CCG_elem_no(&key, vda));
 						glVertex3fv(CCG_elem_co(&key, vda));
 
-						PASSATTRIB(0, 1, 1);
+						PASSATTRIB(0, 1, 2);
 						glNormal3fv(CCG_elem_no(&key, vdb));
 						glVertex3fv(CCG_elem_co(&key, vdb));
 
-						if (x != gridFaces - 1)
+						glEnd();
+
+						a++;
+					}
+				}
+				else {
+					glBegin(GL_QUADS);
+					for (y = 0; y < gridFaces; y++) {
+						for (x = 0; x < gridFaces; x++) {
+							float *aco = CCG_grid_elem_co(&key, faceGridData, x, y);
+							float *bco = CCG_grid_elem_co(&key, faceGridData, x + 1, y);
+							float *cco = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
+							float *dco = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
+
+							ccgDM_glNormalFast(aco, bco, cco, dco);
+
+							PASSATTRIB(0, 1, 1);
+							glVertex3fv(dco);
+							PASSATTRIB(1, 1, 2);
+							glVertex3fv(cco);
+							PASSATTRIB(1, 0, 3);
+							glVertex3fv(bco);
+							PASSATTRIB(0, 0, 0);
+							glVertex3fv(aco);
+
 							a++;
+						}
 					}
+					glEnd();
+				}
+			}
+		}
 
-					vda = CCG_grid_elem(&key, faceGridData, x, y + 0);
-					vdb = CCG_grid_elem(&key, faceGridData, x, y + 1);
+#undef PASSATTRIB
+	}
+	else {
+		GPUMaterialConv *matconv;
+		size_t offset;
+		int *mat_orig_to_new;
+		int tot_active_mat;
+		GPUBuffer *buffer = NULL;
 
-					PASSATTRIB(0, 0, 3);
-					glNormal3fv(CCG_elem_no(&key, vda));
-					glVertex3fv(CCG_elem_co(&key, vda));
+		GPU_vertex_setup(dm);
+		GPU_normal_setup(dm);
+		GPU_triangle_setup(dm);
 
-					PASSATTRIB(0, 1, 2);
-					glNormal3fv(CCG_elem_no(&key, vdb));
-					glVertex3fv(CCG_elem_co(&key, vdb));
+		tot_active_mat = dm->drawObject->totmaterial;
 
-					glEnd();
+		matconv = MEM_callocN(sizeof(*matconv) * tot_active_mat,
+		                      "cdDM_drawMappedFacesGLSL.matconv");
+		mat_orig_to_new = MEM_mallocN(sizeof(*mat_orig_to_new) * dm->totmat,
+		                              "cdDM_drawMappedFacesGLSL.mat_orig_to_new");
 
-					a++;
+		/* part one, check what attributes are needed per material */
+		for (a = 0; a < tot_active_mat; a++) {
+			new_matnr = dm->drawObject->materials[a].mat_nr;
+
+			/* map from original material index to new
+			 * GPUBufferMaterial index */
+			mat_orig_to_new[new_matnr] = a;
+			do_draw = setMaterial(new_matnr + 1, &gattribs);
+
+			if (do_draw) {
+				int numdata = 0;
+				DM_vertex_attributes_from_gpu(dm, &gattribs, &matconv[a].attribs);
+
+				if (matconv[a].attribs.totorco && matconv[a].attribs.orco.array) {
+					matconv[a].datatypes[numdata].index = matconv[a].attribs.orco.gl_index;
+					matconv[a].datatypes[numdata].size = 3;
+					matconv[a].

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list