[Bf-blender-cvs] [107e344] master: Display optimizations part 1.

Antony Riakiotakis noreply at git.blender.org
Tue Jul 14 16:54:29 CEST 2015


Commit: 107e34407d0ae4120cc7a12fdb208986a0b47d8e
Author: Antony Riakiotakis
Date:   Tue Jul 14 16:48:23 2015 +0200
Branches: master
https://developer.blender.org/rB107e34407d0ae4120cc7a12fdb208986a0b47d8e

Display optimizations part 1.

This patch changes the way we draw meshes by introducing
indexed drawing. This makes it possible to easily
upload and rearrange faces ad lib according to any criteria.

Currently we use material sorting but textured sorting and
hiding will be added to optimize textured drawing and skip
per face testing.

It also adds support for vertex buffers for subsurf
modifiers (Except from GLSL drawing), making drawing of
subsurf much faster without need for bogus modifiers.

Tests show that we gain approximately 20-25% performance
by that for solid mode drawing with up to 50% gains for
material drawing. Textured drawing should also have a
small performance gain, but more substantial optimizations
are possible there.

Reviewers: campbellbarton

Differential Revision: https://developer.blender.org/D1406

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

M	source/blender/blenkernel/BKE_DerivedMesh.h
M	source/blender/blenkernel/BKE_pbvh.h
M	source/blender/blenkernel/intern/cdderivedmesh.c
M	source/blender/blenkernel/intern/pbvh.c
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 984147d..881b233 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -463,6 +463,9 @@ 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 *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/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 0832e24..fbaf91d 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -112,7 +112,7 @@ void BKE_pbvh_raycast_project_ray_root(
 
 void BKE_pbvh_node_draw(PBVHNode *node, void *data);
 void BKE_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3],
-                   int (*setMaterial)(int matnr, void *attribs), bool wireframe);
+                   int (*setMaterial)(int matnr, void *attribs), bool wireframe, bool fast);
 
 /* PBVH Access */
 typedef enum {
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index 37c3376..4752332 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -341,8 +341,8 @@ static void cdDM_update_normals_from_pbvh(DerivedMesh *dm)
 static void cdDM_drawVerts(DerivedMesh *dm)
 {
 	GPU_vertex_setup(dm);
-	if (dm->drawObject->tot_triangle_point)
-		glDrawArrays(GL_POINTS, 0, dm->drawObject->tot_triangle_point);
+	if (dm->drawObject->tot_loop_verts)
+		glDrawArrays(GL_POINTS, 0, dm->drawObject->tot_loop_verts);
 	else
 		glDrawArrays(GL_POINTS, 0, dm->drawObject->tot_loose_point);
 	GPU_buffer_unbind();
@@ -391,7 +391,7 @@ static void cdDM_drawEdges(DerivedMesh *dm, bool drawLooseEdges, bool drawAllEdg
 	if (cddm->pbvh && cddm->pbvh_draw &&
 	    BKE_pbvh_type(cddm->pbvh) == PBVH_BMESH)
 	{
-		BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, true);
+		BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, true, false);
 
 		return;
 	}
@@ -442,7 +442,7 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm,
 			float (*face_nors)[3] = CustomData_get_layer(&dm->faceData, CD_NORMAL);
 
 			BKE_pbvh_draw(cddm->pbvh, partial_redraw_planes, face_nors,
-			              setMaterial, false);
+			              setMaterial, false, false);
 			glShadeModel(GL_FLAT);
 		}
 
@@ -451,11 +451,11 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm,
 	
 	GPU_vertex_setup(dm);
 	GPU_normal_setup(dm);
+	GPU_triangle_setup(dm);
 	glShadeModel(GL_SMOOTH);
 	for (a = 0; a < dm->drawObject->totmaterial; a++) {
 		if (!setMaterial || setMaterial(dm->drawObject->materials[a].mat_nr + 1, NULL)) {
-			glDrawArrays(GL_TRIANGLES, dm->drawObject->materials[a].start,
-			             dm->drawObject->materials[a].totpoint);
+			GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES, dm->drawObject->materials[a].start, dm->drawObject->materials[a].totelements);
 		}
 	}
 	GPU_buffer_unbind();
@@ -473,12 +473,13 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
 	const MFace *mf = DM_get_tessface_data_layer(dm, CD_MFACE);
 	MTexPoly *mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY);
 	MCol *mcol;
-	int i;
-	int colType, startFace = 0;
+	int i, orig;
+	int colType, start_element;
 	bool use_tface = (uvflag & DM_DRAW_USE_ACTIVE_UV) != 0;
-	int tottri;
+	int totpoly;
 	int next_actualFace;
-	
+	int mat_index;
+	int tot_element;
 
 	/* double lookup */
 	const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
@@ -497,7 +498,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
 	if (cddm->pbvh && cddm->pbvh_draw && BKE_pbvh_type(cddm->pbvh) == PBVH_BMESH) {
 		if (BKE_pbvh_has_faces(cddm->pbvh)) {
 			GPU_set_tpage(NULL, false, false);
-			BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, false);
+			BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, false, false);
 		}
 
 		return;
@@ -518,6 +519,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
 	
 	GPU_vertex_setup(dm);
 	GPU_normal_setup(dm);
+	GPU_triangle_setup(dm);
 	if (uvflag & DM_DRAW_USE_TEXPAINT_UV)
 		GPU_texpaint_uv_setup(dm);
 	else
@@ -525,76 +527,84 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
 	if (mcol) {
 		GPU_color_setup(dm, colType);
 	}
-	
-	tottri = dm->drawObject->tot_triangle_point / 3;
-	next_actualFace = dm->drawObject->triangle_to_mface[0];
-	
+		
 	glShadeModel(GL_SMOOTH);
 	/* lastFlag = 0; */ /* UNUSED */
-	for (i = 0; i < tottri; i++) {
-		int actualFace = next_actualFace;
-		DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL;
-		int flush = 0;
-		
-		if (i != tottri - 1)
-			next_actualFace = dm->drawObject->triangle_to_mface[i + 1];
-
-		if (drawParams) {
-			MTexPoly *tp = NULL;
-			if (use_tface && mtexpoly && index_mf_to_mpoly) {
-				int actualFace_poly = index_mf_to_mpoly[actualFace];
-				if (actualFace_poly != ORIGINDEX_NONE) {
-					tp = &mtexpoly[actualFace_poly];
+	for (mat_index = 0; mat_index < dm->drawObject->totmaterial; mat_index++) {
+		GPUBufferMaterial *bufmat = dm->drawObject->materials + mat_index;
+		next_actualFace = bufmat->polys[0];
+		totpoly = bufmat->totpolys;
+
+		tot_element = 0;
+		start_element = bufmat->start;
+
+		for (i = 0; i < totpoly; i++) {
+			int actualFace = bufmat->polys[i];
+			DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL;
+			int flush = 0;
+
+			if (i != totpoly - 1)
+				next_actualFace = bufmat->polys[i + 1];
+
+			if (drawParams) {
+				MTexPoly *tp = NULL;
+				if (use_tface && mtexpoly && index_mf_to_mpoly) {
+					int actualFace_poly = index_mf_to_mpoly[actualFace];
+					if (actualFace_poly != ORIGINDEX_NONE) {
+						tp = &mtexpoly[actualFace_poly];
+					}
 				}
-			}
 
-			draw_option = drawParams(tp, (mcol != NULL), mf[actualFace].mat_nr);
-		}
-		else {
-			if (index_mf_to_mpoly) {
-				const int orig = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, actualFace);
-				if (orig == ORIGINDEX_NONE) {
-					/* XXX, this is not really correct
-							 * it will draw the previous faces context for this one when we don't know its settings.
-							 * but better then skipping it altogether. - campbell */
-					draw_option = DM_DRAW_OPTION_NORMAL;
+				draw_option = drawParams(tp, (mcol != NULL), mf[actualFace].mat_nr);
+			}
+			else {
+				if (index_mf_to_mpoly) {
+					orig = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, actualFace);
+					if (orig == ORIGINDEX_NONE) {
+						/* XXX, this is not really correct
+						 * it will draw the previous faces context for this one when we don't know its settings.
+						 * but better then skipping it altogether. - campbell */
+						draw_option = DM_DRAW_OPTION_NORMAL;
+					}
+					else if (drawParamsMapped) {
+						draw_option = drawParamsMapped(userData, orig, mf[actualFace].mat_nr);
+					}
 				}
 				else if (drawParamsMapped) {
-					draw_option = drawParamsMapped(userData, orig, mf[actualFace].mat_nr);
+					draw_option = drawParamsMapped(userData, actualFace, mf[actualFace].mat_nr);
 				}
 			}
-			else if (drawParamsMapped) {
-				draw_option = drawParamsMapped(userData, actualFace, mf[actualFace].mat_nr);
+
+			/* flush buffer if current triangle isn't drawable or it's last triangle */
+			flush = (draw_option == DM_DRAW_OPTION_SKIP) || (i == totpoly - 1);
+
+			if (!flush && compareDrawOptions) {
+				/* also compare draw options and flush buffer if they're different
+				 * need for face selection highlight in edit mode */
+				flush |= compareDrawOptions(userData, actualFace, next_actualFace) == 0;
 			}
-		}
-		
-		/* flush buffer if current triangle isn't drawable or it's last triangle */
-		flush = (draw_option == DM_DRAW_OPTION_SKIP) || (i == tottri - 1);
-		
-		if (!flush && compareDrawOptions) {
-			/* also compare draw options and flush buffer if they're different
-					 * need for face selection highlight in edit mode */
-			flush |= compareDrawOptions(userData, actualFace, next_actualFace) == 0;
-		}
-		
-		if (flush) {
-			int first = startFace * 3;
-			/* Add one to the length if we're drawing at the end of the array */
-			int count = (i - startFace + (draw_option != DM_DRAW_OPTION_SKIP ? 1 : 0)) * 3;
-			
-			if (count) {
-				if (mcol && draw_option != DM_DRAW_OPTION_NO_MCOL)
-					GPU_color_switch(1);
-				else
-					GPU_color_switch(0);
-				
-				glDrawArrays(GL_TRIANGLES, first, count);
+
+			if (flush) {
+				if (draw_option != DM_DRAW_OPTION_SKIP)
+					tot_element += mf[actualFace].v4 ? 6 : 3;
+
+				if (tot_element) {
+					if (mcol && draw_option != DM_DRAW_OPTION_NO_MCOL)
+						GPU_color_switch(1);
+					else
+						GPU_color_switch(0);
+
+					GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES, start_element, tot_element);
+				}
+
+				start_element = tot_element;
+			}
+			else {
+				tot_element += mf[actualFace].v4 ? 6 : 3;
 			}
-			
-			startFace = i + 1;
 		}
 	}
-	
+
 	GPU_buffer_unbind();
 	glShadeModel(GL_FLAT);
 	
@@ -747,87 +757,92 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm,
 		}
 	}
 	else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
-		int prevstart = 0;
+		int start_element = 0, tot_element;
+		int totpoly;
 		int tottri;
+		int mat_index;
 		
 		GPU_vertex_setup(dm);
 		GPU_normal_setup(dm);
+		GPU_triangle_setup(dm);
 		if (useColors && mcol) {
 			GPU_color_setup(dm, colType);
 		}
-		tottri = dm->drawObject->tot_triangle_point / 3;
 		glShadeModel(GL_SMOOTH);
 		
+		tottri = dm->drawObject->tot_triangle_point / 3;
+
 		if (tottri == 0) {
 			/* avoid buffer problems in following code */
 		}
 		else if (setDrawOptions == NULL) {
 			/* just draw the entire face array */
-			glDrawArrays(GL_TRIANGLES, 0, (tottri) * 3);
+			GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES, 0, 3 * tottri);
 		}
-		else {
-			/* we need to check if the

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list