[Bf-blender-cvs] [2c2abcc] opensubdiv-modifier: OpenSubdiv: Support GPU tessellation in edit mode

Sergey Sharybin noreply at git.blender.org
Wed Jul 30 18:25:57 CEST 2014


Commit: 2c2abcc9c5d4216b6d73b5429ea7a481ad2ff360
Author: Sergey Sharybin
Date:   Wed Jul 30 22:24:19 2014 +0600
Branches: opensubdiv-modifier
https://developer.blender.org/rB2c2abcc9c5d4216b6d73b5429ea7a481ad2ff360

OpenSubdiv: Support GPU tessellation in edit mode

This should speed up deformation-only modifications in edit
mode very well (assuming subsurf is the last modifier in the
stack).

This is so-called "seems to work" commit, requires much deeper
tests, mainly shading/texturing-wise.

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

M	source/blender/blenkernel/intern/DerivedMesh.c
M	source/blender/blenkernel/intern/subsurf_ccg.c
M	source/blender/gpu/intern/gpu_draw.c
M	source/blender/modifiers/intern/MOD_subsurf.c

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

diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 76a8831..1c5ff8c 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -2029,6 +2029,17 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
 	const bool do_loop_normals = (((Mesh *)(ob->data))->flag & ME_AUTOSMOOTH);
 	const float loop_normals_split_angle = ((Mesh *)(ob->data))->smoothresh;
 
+#ifdef WITH_OPENSUBDIV
+	{
+		ModifierData *last_md = ob->modifiers.last;
+		if (last_md != NULL &&
+		    last_md->type == eModifierType_Subsurf)
+		{
+			dataMask &= ~CD_MASK_ORCO;
+		}
+	}
+#endif
+
 	modifiers_clearErrors(ob);
 
 	if (cage_r && cageIndex == -1) {
@@ -2164,9 +2175,9 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
 			}
 
 			if (mti->applyModifierEM)
-				ndm = modwrap_applyModifierEM(md, ob, em, dm, MOD_APPLY_USECACHE);
+				ndm = modwrap_applyModifierEM(md, ob, em, dm, MOD_APPLY_USECACHE | MOD_APPLY_ALLOW_GPU);
 			else
-				ndm = modwrap_applyModifier(md, ob, dm, MOD_APPLY_USECACHE);
+				ndm = modwrap_applyModifier(md, ob, dm, MOD_APPLY_USECACHE | MOD_APPLY_ALLOW_GPU);
 			ASSERT_IS_VALID_DM(ndm);
 
 			if (ndm) {
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 4bfc918..4811362 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -1778,7 +1778,10 @@ static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d)
 }
 
 /* Only used by non-editmesh types */
-static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)[4], bool fast, DMSetMaterial setMaterial)
+static void ccgDM_drawFacesSolid(DerivedMesh *dm,
+                                 float (*partial_redraw_planes)[4],
+                                 bool fast,
+                                 DMSetMaterial setMaterial)
 {
 	CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
 	CCGSubSurf *ss = ccgdm->ss;
@@ -2300,6 +2303,13 @@ static void ccgDM_drawMappedFacesMat(DerivedMesh *dm,
 	short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
 	int a, i, numVerts, matnr, new_matnr, totface;
 
+#ifdef WITH_OPENSUBDIV
+	if (ccgdm->useGpuBackend) {
+		BLI_assert(!"Not currently supported");
+		return;
+	}
+#endif
+
 	CCG_key_top_level(&key, ss);
 	ccgdm_pbvh_update(ccgdm);
 
@@ -2472,6 +2482,9 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
 	int gridOffset = 0;
 	int mat_nr_cache = -1;
 
+	/* TODO(sergey): Not currently supported, might lead to some wrong
+	 * shading/texturing artifacts due to batching in OpenSubdiv.
+	 */
 	(void) compareDrawOptions;
 
 #ifdef WITH_OPENSUBDIV
@@ -2489,9 +2502,6 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
 		 * this we'll need to pass proper compareDrawOptions.
 		 */
 
-		/* If it happens we've got compare callback let us know. */
-		BLI_assert(compareDrawOptions == NULL);
-
 		if (ccgSubSurf_prepareGLMesh(ss, true) == false) {
 			return;
 		}
@@ -2807,6 +2817,93 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm,
 	int useColors = flag & DM_DRAW_USE_COLORS;
 	int gridFaces = gridSize - 1, totface;
 
+#ifdef WITH_OPENSUBDIV
+	if (ccgdm->useGpuBackend) {
+		int i, matnr = -1, shademodel = -1;
+		CCGFaceIterator *fi;
+		int start_partition = 0, num_partitions = 0;
+		DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL;
+
+		if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, true) == false)) {
+			return;
+		}
+
+		for (fi = ccgSubSurf_getFaceIterator(ss), i = 0;
+		     !ccgFaceIterator_isStopped(fi);
+		     ccgFaceIterator_next(fi), ++i)
+		{
+			CCGFace *f = ccgFaceIterator_getCurrent(fi);
+			int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
+			int origIndex = ccgDM_getFaceMapIndex(ss, f);
+			int new_matnr, new_shademodel;
+
+			if (faceFlags) {
+				new_shademodel = (lnors || (faceFlags[index].flag & ME_SMOOTH))
+					? GL_SMOOTH
+					: GL_FLAT;
+				new_matnr = faceFlags[index].mat_nr + 1;
+			}
+			else {
+				new_shademodel = GL_SMOOTH;
+				new_matnr = 1;
+			}
+
+			if (new_shademodel != shademodel || new_matnr != matnr) {
+				if (num_partitions) {
+					ccgSubSurf_drawGLMesh(ss, true,
+					                      start_partition, num_partitions);
+				}
+
+				start_partition = i;
+				num_partitions = 0;
+
+				/* Update material settings for the next partitions batch. */
+				if (new_shademodel != shademodel) {
+					glShadeModel(new_shademodel);
+				}
+
+				if (new_matnr != matnr) {
+					if (index == ORIGINDEX_NONE) {
+						/* XXX, no faceFlags no material */
+						draw_option = setMaterial(faceFlags ? faceFlags[origIndex].mat_nr + 1 : 1, NULL);
+					}
+					else if (setDrawOptions) {
+						draw_option = setDrawOptions(userData, index);
+					}
+				}
+
+				/* Cache settings. */
+				shademodel = new_shademodel;
+				matnr = new_matnr;
+			}
+
+			/* TODO(sergey): This isn't actually tested.. */
+			if (draw_option == DM_DRAW_OPTION_SKIP) {
+				if (num_partitions) {
+					ccgSubSurf_drawGLMesh(ss, true,
+					                      start_partition, num_partitions);
+				}
+
+				start_partition = i;
+				num_partitions = 0;
+
+				continue;
+			}
+
+			num_partitions++;
+		}
+		ccgFaceIterator_free(fi);
+
+		/* Draw residual tail of the partitions. */
+		if (num_partitions) {
+			ccgSubSurf_drawGLMesh(ss, true, start_partition, num_partitions);
+		}
+
+		/* We're done with drawing if drawing happens using OpenSubdiv. */
+		return;
+	}
+#endif
+
 	CCG_key_top_level(&key, ss);
 
 	/* currently unused -- each original face is handled separately */
@@ -2969,6 +3066,13 @@ static void ccgDM_drawMappedEdges(DerivedMesh *dm,
 	CCGKey key;
 	int i, useAging, edgeSize = ccgSubSurf_getEdgeSize(ss);
 
+#ifdef WITH_OPENSUBDIV
+	if (ccgdm->useGpuBackend) {
+		BLI_assert(!"Not currently supported");
+		return;
+	}
+#endif
+
 	CCG_key_top_level(&key, ss);
 	ccgSubSurf_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL);
 
@@ -3006,6 +3110,13 @@ static void ccgDM_drawMappedEdgesInterp(DerivedMesh *dm,
 	CCGEdgeIterator *ei;
 	int i, useAging, edgeSize = ccgSubSurf_getEdgeSize(ss);
 
+#ifdef WITH_OPENSUBDIV
+	if (ccgdm->useGpuBackend) {
+		BLI_assert(!"Not currently supported");
+		return;
+	}
+#endif
+
 	CCG_key_top_level(&key, ss);
 	ccgSubSurf_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL);
 
@@ -4213,14 +4324,34 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
 	/* note: editmode calculation can only run once per
 	 * modifier stack evaluation (uses freed cache) [#36299] */
 	if (flags & SUBSURF_FOR_EDIT_MODE) {
+		bool use_gpu_backend = false;
 		int levels = (smd->modifier.scene) ? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels) : smd->levels;
 
+		/* TODO(sergey): Same as emCache below. */
+		if ((flags & SUBSURF_IN_EDIT_MODE) && smd->mCache) {
+			ccgSubSurf_free(smd->mCache);
+			smd->mCache = NULL;
+		}
+
 		smd->emCache = _getSubSurf(smd->emCache, levels, 3, useSimple | useAging | CCG_CALC_NORMALS);
+
+#ifdef WITH_OPENSUBDIV
+		use_gpu_backend = (flags & SUBSURF_USE_GPU_BACKEND) != 0 &&
+			openSubdiv_supportGPUDisplay() &&
+			U.opensubdiv_compute_type != USER_OPENSUBDIV_COMPUTE_NONE;
+
+		ccgSubSurf_setSkipGrids(smd->emCache, use_gpu_backend);
+#endif
+
 		ss_sync_from_derivedmesh(smd->emCache, dm, vertCos, useSimple);
 
 		result = getCCGDerivedMesh(smd->emCache,
 		                           drawInteriorEdges,
-		                           useSubsurfUv, dm, false);
+		                           useSubsurfUv, dm, use_gpu_backend);
+
+#ifdef WITH_OPENSUBDIV
+		ccgSubSurf_setUVCoordsFromDM(smd->emCache, dm, useSubsurfUv);
+#endif
 	}
 	else if (flags & SUBSURF_USE_RENDER_PARAMS) {
 		/* Do not use cache in render mode. */
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index c0e7778..5be7295 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -82,6 +82,9 @@
 #include "smoke_API.h"
 
 #ifdef WITH_OPENSUBDIV
+#  include "DNA_mesh_types.h"
+#  include "BKE_editmesh.h"
+
 #  include "gpu_codegen.h"
 #endif
 
@@ -1452,11 +1455,25 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O
 	const bool use_matcap = (v3d->flag2 & V3D_SHOW_SOLID_MATCAP) != 0;  /* assumes v3d->defmaterial->preview is set */
 	bool use_opensubdiv = false;
 
-	/* TODO(sergey): What to do if there's no derived final? */
-	if (ob->derivedFinal != NULL) {
-		CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) ob->derivedFinal;
-		use_opensubdiv = ccgdm->useGpuBackend;
+#ifdef WITH_OPENSUBDIV
+	{
+		DerivedMesh *derivedFinal = NULL;
+		Mesh *me = ob->data;
+		BMEditMesh *em = me->edit_btmesh;
+
+		if (em != NULL) {
+			derivedFinal = em->derivedFinal;
+		}
+		else {
+			derivedFinal = ob->derivedFinal;
+		}
+
+		if (derivedFinal != NULL && derivedFinal->type == DM_TYPE_CCGDM) {
+			CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) derivedFinal;
+			use_opensubdiv = ccgdm->useGpuBackend;
+		}
 	}
+#endif
 
 #ifdef WITH_GAMEENGINE
 	if (rv3d->rflag & RV3D_IS_GAME_ENGINE) {
diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c
index 7d7c0cd..c846f2b 100644
--- a/source/blender/modifiers/intern/MOD_subsurf.c
+++ b/source/blender/modifiers/intern/MOD_subsurf.c
@@ -138,6 +138,12 @@ static DerivedMesh *applyModifierEM(ModifierData *md, Object *UNUSED(ob),
 	DerivedMesh *result;
 	/* 'orco' using editmode flags would cause cache to be used twice in editbmesh_calc_modifiers */
 	SubsurfFlags ss_flags = (flag & MOD_APPLY_ORCO) ? 0 : (SUBSURF_FOR_EDIT_MODE | SUBSURF_IN_EDIT_MODE);
+	const bool allow_gpu = (flag & MOD_APPLY_ALLOW_GPU) != 0;
+
+	/* TODO(sergey): Not entirely correct, only good for purposes of test. */
+	if (md->next == NULL && allow_gpu) {
+		ss_flags |= SUBSURF_USE_GPU_BACKEND;
+	}
 
 	result = subsurf_make_derived_from_derived(derivedData, smd, NULL, ss_flags);




More information about the Bf-blender-cvs mailing list