[Bf-blender-cvs] [769c57b38a7] blender2.8: SoftBody: share point cache between CoW copies

Sybren A. Stüvel noreply at git.blender.org
Wed Jul 4 11:45:33 CEST 2018


Commit: 769c57b38a707397ac7fdda15b1deb561194b66c
Author: Sybren A. Stüvel
Date:   Wed Jul 4 11:22:15 2018 +0200
Branches: blender2.8
https://developer.blender.org/rB769c57b38a707397ac7fdda15b1deb561194b66c

SoftBody: share point cache between CoW copies

This is the same approach as 98a0bcd4252e952fa5438e9d1b69b0204f8a8746
applied to soft body simulation. In short, CoW copies share the point cache,
and treat it as read-only except when the depsgraph is active.

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

M	source/blender/blenkernel/intern/bpath.c
M	source/blender/blenkernel/intern/object.c
M	source/blender/blenkernel/intern/pointcache.c
M	source/blender/blenkernel/intern/softbody.c
M	source/blender/blenloader/intern/readfile.c
M	source/blender/blenloader/intern/versioning_280.c
M	source/blender/blenloader/intern/writefile.c
M	source/blender/makesdna/DNA_object_force_types.h
M	source/blender/makesrna/intern/rna_modifier.c

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

diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c
index 7c9e57b039e..34f54704f75 100644
--- a/source/blender/blenkernel/intern/bpath.c
+++ b/source/blender/blenkernel/intern/bpath.c
@@ -513,7 +513,7 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int
 			}
 
 			if (ob->soft) {
-				BPATH_TRAVERSE_POINTCACHE(ob->soft->ptcaches);
+				BPATH_TRAVERSE_POINTCACHE(ob->soft->shared->ptcaches);
 			}
 
 			for (psys = ob->particlesystem.first; psys; psys = psys->next) {
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 3f5464156c5..61d38a4e937 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -834,6 +834,7 @@ void BKE_object_copy_softbody(struct Object *ob_dst, const struct Object *ob_src
 {
 	SoftBody *sb = ob_src->soft;
 	SoftBody *sbn;
+	bool tagged_no_main = ob_dst->id.tag & LIB_TAG_NO_MAIN;
 
 	ob_dst->softflag = ob_src->softflag;
 	if (sb == NULL) {
@@ -872,7 +873,10 @@ void BKE_object_copy_softbody(struct Object *ob_dst, const struct Object *ob_src
 
 	sbn->scratch = NULL;
 
-	sbn->pointcache = BKE_ptcache_copy_list(&sbn->ptcaches, &sb->ptcaches, flag);
+	if (tagged_no_main == 0) {
+		sbn->shared = MEM_dupallocN(sb->shared);
+		sbn->shared->pointcache = BKE_ptcache_copy_list(&sbn->shared->ptcaches, &sb->shared->ptcaches, flag);
+	}
 
 	if (sb->effector_weights)
 		sbn->effector_weights = MEM_dupallocN(sb->effector_weights);
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index a8c6091124a..17e90d688a2 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -1389,9 +1389,9 @@ void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb)
 	pid->ob= ob;
 	pid->calldata= sb;
 	pid->type= PTCACHE_TYPE_SOFTBODY;
-	pid->cache= sb->pointcache;
-	pid->cache_ptr= &sb->pointcache;
-	pid->ptcaches= &sb->ptcaches;
+	pid->cache= sb->shared->pointcache;
+	pid->cache_ptr= &sb->shared->pointcache;
+	pid->ptcaches= &sb->shared->ptcaches;
 	pid->totpoint= pid->totwrite= ptcache_softbody_totpoint;
 	pid->error					= ptcache_softbody_error;
 
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index 4960714b47c..d3429622573 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -3276,7 +3276,8 @@ SoftBody *sbNew(Scene *scene)
 	sb->shearstiff = 1.0f;
 	sb->solverflags |= SBSO_OLDERR;
 
-	sb->pointcache = BKE_ptcache_add(&sb->ptcaches);
+	sb->shared = MEM_callocN(sizeof(*sb->shared), "SoftBody_Shared");
+	sb->shared->pointcache = BKE_ptcache_add(&sb->shared->ptcaches);
 
 	if (!sb->effector_weights)
 		sb->effector_weights = BKE_add_effector_weights(NULL);
@@ -3295,8 +3296,13 @@ void sbFree(Object *ob)
 	}
 
 	free_softbody_intern(sb);
-	BKE_ptcache_free_list(&sb->ptcaches);
-	sb->pointcache = NULL;
+
+	if ((ob->id.tag & LIB_TAG_COPIED_ON_WRITE) == 0) {
+		/* Only free shared data on non-CoW copies */
+		BKE_ptcache_free_list(&sb->shared->ptcaches);
+		sb->shared->pointcache = NULL;
+		MEM_freeN(sb->shared);
+	}
 	if (sb->effector_weights)
 		MEM_freeN(sb->effector_weights);
 	MEM_freeN(sb);
@@ -3608,7 +3614,7 @@ void sbObjectStep(struct Depsgraph *depsgraph, Scene *scene, Object *ob, float c
 	float dtime, timescale;
 	int framedelta, framenr, startframe, endframe;
 	int cache_result;
-	cache= sb->pointcache;
+	cache= sb->shared->pointcache;
 
 	framenr= (int)cfra;
 	framedelta= framenr - cache->simframe;
@@ -3676,7 +3682,8 @@ void sbObjectStep(struct Depsgraph *depsgraph, Scene *scene, Object *ob, float c
 	}
 
 	/* try to read from cache */
-	bool can_simulate = (framenr == sb->last_frame + 1) && !(cache->flag & PTCACHE_BAKED);
+	bool can_write_cache = DEG_is_active(depsgraph);
+	bool can_simulate = (framenr == sb->last_frame + 1) && !(cache->flag & PTCACHE_BAKED) && can_write_cache;
 
 	cache_result = BKE_ptcache_read(&pid, (float)framenr+scene->r.subframe, can_simulate);
 
@@ -3687,7 +3694,7 @@ void sbObjectStep(struct Depsgraph *depsgraph, Scene *scene, Object *ob, float c
 
 		BKE_ptcache_validate(cache, framenr);
 
-		if (cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED)
+		if (cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED && can_write_cache)
 			BKE_ptcache_write(&pid, framenr);
 
 		sb->last_frame = framenr;
@@ -3699,7 +3706,9 @@ void sbObjectStep(struct Depsgraph *depsgraph, Scene *scene, Object *ob, float c
 	}
 	else if (/*ob->id.lib || */(cache->flag & PTCACHE_BAKED)) { /* "library linking & pointcaches" has to be solved properly at some point */
 		/* if baked and nothing in cache, do nothing */
-		BKE_ptcache_invalidate(cache);
+		if (can_write_cache) {
+			BKE_ptcache_invalidate(cache);
+		}
 		return;
 	}
 
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 79a552a5b86..2a48bf8fc5a 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -5437,7 +5437,18 @@ static void direct_link_object(FileData *fd, Object *ob)
 		if (!sb->effector_weights)
 			sb->effector_weights = BKE_add_effector_weights(NULL);
 
-		direct_link_pointcache_list(fd, &sb->ptcaches, &sb->pointcache, 0);
+		sb->shared = newdataadr(fd, sb->shared);
+		if (sb->shared == NULL) {
+			/* Link deprecated caches if they exist, so we can use them for versioning.
+			 * We should only do this when sb->shared == NULL, because those pointers
+			 * are always set (for compatibility with older Blenders). We mustn't link
+			 * the same pointcache twice. */
+			direct_link_pointcache_list(fd, &sb->ptcaches, &sb->pointcache, false);
+		}
+		else {
+			/* link caches */
+			direct_link_pointcache_list(fd, &sb->shared->ptcaches, &sb->shared->pointcache, false);
+		}
 	}
 	ob->fluidsimSettings= newdataadr(fd, ob->fluidsimSettings); /* NT */
 
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index 3fa059989a3..757e17ce82b 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -1559,5 +1559,24 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
 			}
 		}
 
+		if (!DNA_struct_elem_find(fd->filesdna, "SoftBody", "SoftBody_Shared", "*shared")) {
+			for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
+				SoftBody *sb = ob->soft;
+				if (sb == NULL) {
+					continue;
+				}
+				if (sb->shared == NULL) {
+					sb->shared = MEM_callocN(sizeof(*sb->shared), "SoftBody_Shared");
+				}
+
+				/* Move shared pointers from deprecated location to current location */
+				sb->shared->pointcache = sb->pointcache;
+				sb->shared->ptcaches = sb->ptcaches;
+
+				sb->pointcache = NULL;
+				BLI_listbase_clear(&sb->ptcaches);
+			}
+		}
+
 	}
 }
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index e7bca4c7e5b..146494e6196 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -1816,9 +1816,13 @@ static void write_object(WriteData *wd, Object *ob)
 		write_motionpath(wd, ob->mpath);
 
 		writestruct(wd, DATA, PartDeflect, 1, ob->pd);
-		writestruct(wd, DATA, SoftBody, 1, ob->soft);
 		if (ob->soft) {
-			write_pointcaches(wd, &ob->soft->ptcaches);
+			/* Set deprecated pointers to prevent crashes of older Blenders */
+			ob->soft->pointcache = ob->soft->shared->pointcache;
+			ob->soft->ptcaches = ob->soft->shared->ptcaches;
+			writestruct(wd, DATA, SoftBody, 1, ob->soft);
+			writestruct(wd, DATA, SoftBody_Shared, 1, ob->soft->shared);
+			write_pointcaches(wd, &(ob->soft->shared->ptcaches));
 			writestruct(wd, DATA, EffectorWeights, 1, ob->soft->effector_weights);
 		}
 
diff --git a/source/blender/makesdna/DNA_object_force_types.h b/source/blender/makesdna/DNA_object_force_types.h
index ac7c969a810..3538abcff1a 100644
--- a/source/blender/makesdna/DNA_object_force_types.h
+++ b/source/blender/makesdna/DNA_object_force_types.h
@@ -37,6 +37,7 @@ extern "C" {
 #endif
 
 #include "DNA_listBase.h"
+#include "DNA_defs.h"
 
 /* pd->forcefield:  Effector Fields types */
 typedef enum ePFieldType {
@@ -218,6 +219,15 @@ typedef struct SBVertex {
 	float vec[4];
 } SBVertex;
 
+/* Container for data that is shared among CoW copies.
+ *
+ * This is placed in a separate struct so that values can be changed
+ * without having to update all CoW copies. */
+typedef struct SoftBody_Shared {
+	struct PointCache *pointcache;
+	struct ListBase ptcaches;
+} SoftBody_Shared;
+
 typedef struct SoftBody {
 	/* dynamic data */
 	int totpoint, totspring;
@@ -289,8 +299,9 @@ typedef struct SoftBody {
 	float shearstiff;
 	float inpush;
 
-	struct PointCache *pointcache;
-	struct ListBase ptcaches;
+	struct SoftBody_Shared *shared;
+	struct PointCache *pointcache DNA_DEPRECATED;  /* Moved to SoftBody_Shared */
+	struct ListBase ptcaches DNA_DEPRECATED;  /* Moved to SoftBody_Shared */
 
 	struct Collection *collision_group;
 
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index f0001852da2..a2a21a194ea 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -716,7 +716,7 @@ static PointerRNA rna_SoftBodyModifier_settings_get(PointerRNA *ptr)
 static PointerRNA rna_SoftBodyModifier_point_cache_get(PointerRNA *ptr)
 {
 	Object *ob = (Object *)ptr->id.data;
-	return rna_pointer_inherit_refine(ptr, &RNA_PointCache, ob->soft->pointcache);
+	return rna_pointer_inherit_refine(ptr, &RNA_PointCache, ob->soft->shared->pointcache);
 }
 
 static PointerRNA rna_CollisionModifier_settings_get(PointerRNA *ptr)



More information about the Bf-blender-cvs mailing list