[Bf-blender-cvs] [c1ce838] opensubdiv-modifier: Made evaluator persistent in memory
Sergey Sharybin
noreply at git.blender.org
Mon May 12 20:08:56 CEST 2014
Commit: c1ce838be5bb34f9e1aa3b11b5cccad394e3d411
Author: Sergey Sharybin
Date: Sat May 10 17:45:21 2014 +0200
https://developer.blender.org/rBc1ce838be5bb34f9e1aa3b11b5cccad394e3d411
Made evaluator persistent in memory
Now OpenSubdiv evaluator descriptor will only be re-created
if mesh topology changes.
Apparently don't see huge speed raise with CPU evaluation,
but this change lands a bit of a basis for further changes.
Requires changes made in OpenSubdiv's C-API which are currently
only there:
https://github.com/Nazg-Gul/OpenSubdiv/tree/dev
===================================================================
M source/blender/blenkernel/intern/CCGSubSurf.c
M source/blender/blenkernel/intern/subsurf_ccg.c
===================================================================
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c
index bb75bc4..a1afba6 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf.c
@@ -2369,24 +2369,82 @@ static bool opensubdiv_initEvaluator(CCGSubSurf *ss)
return openSubdiv_finishEvaluatorDescr(ss->osd_evaluator, ss->subdivLevels) != 0;
}
+static bool check_topology_changed(CCGSubSurf *ss)
+{
+ int num_vertices,
+ refinement_level,
+ num_indices,
+ num_nverts;
+ int *indices, *nverts;
+ int i, index, osd_vert_index, osd_face_index;
+
+ BLI_assert(ss->osd_evaluator != NULL);
+
+ /* Set an osd_index member in each one so we have consistent indexing.
+ *
+ * TODO(sergey): Currently here's a duplicated logic happens, make it
+ * so osd_indices are only calculated once.
+ */
+ for (i = 0, osd_vert_index = 0; i < ss->vMap->curSize; ++i) {
+ CCGVert *vert = (CCGVert *) ss->vMap->buckets[i];
+ for (; vert; vert = vert->next, ++osd_vert_index) {
+ vert->osd_index = osd_vert_index;
+ }
+ }
+
+ /* Get the topology from existing evaluator. */
+ openSubdiv_getEvaluatorTopology(ss->osd_evaluator,
+ &num_vertices,
+ &refinement_level,
+ &num_indices,
+ &indices,
+ &num_nverts,
+ &nverts);
+
+ /* Quick tests based on the number of subdiv level, verts and facces. */
+ if (refinement_level != ss->subdivLevels ||
+ num_vertices != ss->vMap->numEntries ||
+ num_nverts != ss->fMap->numEntries)
+ {
+ return true;
+ }
+
+ /* Rather slow check for faces topology change. */
+ for (i = 0, osd_face_index = 0, index = 0;
+ i < ss->fMap->curSize;
+ i++)
+ {
+ CCGFace *face = (CCGFace *) ss->fMap->buckets[i];
+ for (; face; face = face->next, ++osd_face_index) {
+ int S;
+
+ if (face->numVerts != nverts[osd_face_index]) {
+ return true;
+ }
+
+ for (S = 0; S < face->numVerts; ++S) {
+ if (FACE_getVerts(face)[S]->osd_index != indices[index++]) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
static bool opensubdiv_ensureEvaluator(CCGSubSurf *ss)
{
bool evaluator_needs_init = false;
if (ss->osd_evaluator != NULL) {
- /* TODO(dirk, sergey): Need to check that the existing evaluator has matching:
- * - Number of vertices
- * - Face topology
- * - Subdivision level
- *
- * If not we need to blow away and recreate the evaluator.
- *
- * For now we always re-create the evaluator to be sure edit mode works all
- * fine and no topology changes caused by the previous modifiers are screwing
- * us up.
- */
- openSubdiv_deleteEvaluatorDescr(ss->osd_evaluator);
- ss->osd_evaluator = NULL;
+ if (check_topology_changed(ss)) {
+ /* If topology changes then we are to re-create evaluator
+ * from the very scratch.
+ */
+ openSubdiv_deleteEvaluatorDescr(ss->osd_evaluator);
+ ss->osd_evaluator = NULL;
+ }
}
if (ss->osd_evaluator == NULL) {
int num_basis_verts = ss->vMap->numEntries;
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index a9eba54..57aca4f 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -3918,16 +3918,31 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
}
else {
CCGFlags ccg_flags = useSimple | CCG_USE_ARENA | CCG_CALC_NORMALS;
-
+ CCGSubSurf *prevSS = NULL;
+
if (smd->mCache && (flags & SUBSURF_IS_FINAL_CALC)) {
+#ifdef WITH_OPENSUBDIV
+ /* With OpenSubdiv enabled we always tries to re-use previos
+ * subsurf structure in order to save computation time since
+ * re-creation is rather a complicated business.
+ *
+ * TODO(sergey): There was a good eason why final calculation
+ * used to free entirely cached subsurf structure. reason of
+ * this is to be investiated still to be sure we don't have
+ * regressions here.
+ */
+ prevSS = smd->mCache;
+#else
ccgSubSurf_free(smd->mCache);
smd->mCache = NULL;
+#endif
}
+
if (flags & SUBSURF_ALLOC_PAINT_MASK)
ccg_flags |= CCG_ALLOC_MASK;
- ss = _getSubSurf(NULL, levels, 3, ccg_flags);
+ ss = _getSubSurf(prevSS, levels, 3, ccg_flags);
ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple);
result = getCCGDerivedMesh(ss, drawInteriorEdges, useSubsurfUv, dm);
More information about the Bf-blender-cvs
mailing list