Fix T39180: Particle with fluid physics unstable.
authorLukas Tönne <lukas.toenne@gmail.com>
Tue, 18 Mar 2014 12:36:24 +0000 (13:36 +0100)
committerLukas Tönne <lukas.toenne@gmail.com>
Tue, 18 Mar 2014 12:39:13 +0000 (13:39 +0100)
Fluid sims have a very nasty feature for interaction, in which a psys
can directly update the bvhtree for //another object's psys//. This
breaks with threaded depsgraph evaluation and is generally a no-go.

To avoid crashes for now, use a global mutex to avoid concurrent writes
to an object psys' bvhtree.

source/blender/blenkernel/intern/particle_system.c
source/blender/makesdna/DNA_particle_types.h

index 32f8ba920e64c4d4aa22809552a41ed46675e83d..0e02f30a26e9cfd9e45214ddb2c0ce74b66a77c5 100644 (file)
 
 #endif // WITH_MOD_FLUID
 
+static ThreadMutex psys_bvhtree_rwlock = BLI_RWLOCK_INITIALIZER;
+
 /************************************************/
 /*                     Reacting to system events                       */
 /************************************************/
@@ -2209,15 +2211,22 @@ static void psys_update_particle_bvhtree(ParticleSystem *psys, float cfra)
        if (psys) {
                PARTICLE_P;
                int totpart = 0;
+               bool need_rebuild;
 
-               if (!psys->bvhtree || psys->bvhtree_frame != cfra) {
+               BLI_rw_mutex_lock(&psys_bvhtree_rwlock, THREAD_LOCK_READ);
+               need_rebuild = !psys->bvhtree || psys->bvhtree_frame != cfra;
+               BLI_rw_mutex_unlock(&psys_bvhtree_rwlock);
+               
+               if (need_rebuild) {
                        LOOP_SHOWN_PARTICLES {
                                totpart++;
                        }
                        
+                       BLI_rw_mutex_lock(&psys_bvhtree_rwlock, THREAD_LOCK_WRITE);
+                       
                        BLI_bvhtree_free(psys->bvhtree);
                        psys->bvhtree = BLI_bvhtree_new(totpart, 0.0, 4, 6);
-
+                       
                        LOOP_SHOWN_PARTICLES {
                                if (pa->alive == PARS_ALIVE) {
                                        if (pa->state.time == cfra)
@@ -2227,8 +2236,10 @@ static void psys_update_particle_bvhtree(ParticleSystem *psys, float cfra)
                                }
                        }
                        BLI_bvhtree_balance(psys->bvhtree);
-
+                       
                        psys->bvhtree_frame = cfra;
+                       
+                       BLI_rw_mutex_unlock(&psys_bvhtree_rwlock);
                }
        }
 }
@@ -2546,7 +2557,11 @@ static void sph_evaluate_func(BVHTree *tree, ParticleSystem **psys, float co[3],
                        break;
                }
                else {
+                       BLI_rw_mutex_lock(&psys_bvhtree_rwlock, THREAD_LOCK_READ);
+                       
                        BLI_bvhtree_range_query(psys[i]->bvhtree, co, interaction_radius, callback, pfr);
+                       
+                       BLI_rw_mutex_unlock(&psys_bvhtree_rwlock);
                }
        }
 }
index 7b06f2a46db947e3079321ac84d80c8255db3dc3..a2a724b6a32693c0a8d03d8326fb792dd68dcb8a 100644 (file)
@@ -304,8 +304,8 @@ typedef struct ParticleSystem {
        ParticleSpring *fluid_springs;
        int tot_fluidsprings, alloc_fluidsprings;
 
-       struct KDTree *tree;                                                            /* used for interactions with self and other systems */
-       struct BVHTree *bvhtree;                                                                /* used for interactions with self and other systems */
+       struct KDTree *tree;                                    /* used for interactions with self and other systems */
+       struct BVHTree *bvhtree;                                /* used for interactions with self and other systems */
 
        struct ParticleDrawData *pdd;