diff options
author | Lukas Tönne <lukas.toenne@gmail.com> | 2014-03-07 13:25:56 +0400 |
---|---|---|
committer | Lukas Tönne <lukas.toenne@gmail.com> | 2014-03-07 14:20:45 +0400 |
commit | 08444518e62b4c7154c1428c33adab842774aa30 (patch) | |
tree | 17a55f7dae3b1b877e3f6a2d3c0a6d6cdd213c46 /source/blender/blenkernel/BKE_particle.h | |
parent | 98abc80dcf52e6711d20f7e5738e5a8797567f24 (diff) |
Removing ParticleSystem->frand arrays to avoid memory corruption issues
in threaded depgraph updates and effector list construction.
Gathering effectors during depgraph updates will call the
psys_check_enabled function. This in turn contained a DNA alloc call
for the psys->frand RNG arrays, which is really bad because data must be
immutable during these effector constructions.
To avoid such allocs the frand array is now global for all particle
systems. To avoid correlation of pseudo-random numbers the psys->seed
value is complemented with random offset and multiplier for the actual
float array. This is not ideal, but work sufficiently well (given that
random numbers were already really limited and show repetition quite
easily for particle counts > PSYS_FRAND_COUNT).
Diffstat (limited to 'source/blender/blenkernel/BKE_particle.h')
-rw-r--r-- | source/blender/blenkernel/BKE_particle.h | 33 |
1 files changed, 30 insertions, 3 deletions
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index b6be72fadd3..d87b2090712 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -34,6 +34,8 @@ * \ingroup bke */ +#include "BLI_utildefines.h" + #include "DNA_particle_types.h" #include "DNA_object_types.h" @@ -70,9 +72,6 @@ struct EdgeHash; /* OpenMP: Can only advance one variable within loop definition. */ #define LOOP_DYNAMIC_PARTICLES for (p = 0; p < psys->totpart; p++) if ((pa = psys->particles + p)->state.time > 0.0f) -#define PSYS_FRAND_COUNT 1024 -#define PSYS_FRAND(seed) psys->frand[(seed) % PSYS_FRAND_COUNT] - /* fast but sure way to get the modifier*/ #define PARTICLE_PSMD ParticleSystemModifierData * psmd = sim->psmd ? sim->psmd : psys_get_modifier(sim->ob, sim->psys) @@ -247,6 +246,34 @@ typedef struct ParticleDrawData { #define PARTICLE_DRAW_DATA_UPDATED 1 +#define PSYS_FRAND_COUNT 1024 +unsigned int PSYS_FRAND_SEED_OFFSET[PSYS_FRAND_COUNT]; +unsigned int PSYS_FRAND_SEED_MULTIPLIER[PSYS_FRAND_COUNT]; +float PSYS_FRAND_BASE[PSYS_FRAND_COUNT]; + +void psys_init_rng(void); + +BLI_INLINE float psys_frand(ParticleSystem *psys, unsigned int seed) +{ + /* XXX far from ideal, this simply scrambles particle random numbers a bit + * to avoid obvious correlations. + * Can't use previous psys->frand arrays because these require initialization + * inside psys_check_enabled, which wreaks havok in multithreaded depgraph updates. + */ + unsigned int offset = PSYS_FRAND_SEED_OFFSET[psys->seed % PSYS_FRAND_COUNT]; + unsigned int multiplier = PSYS_FRAND_SEED_MULTIPLIER[psys->seed % PSYS_FRAND_COUNT]; + return PSYS_FRAND_BASE[(offset + seed * multiplier) % PSYS_FRAND_COUNT]; +} + +BLI_INLINE void psys_frand_vec(ParticleSystem *psys, unsigned int seed, float vec[3]) +{ + unsigned int offset = PSYS_FRAND_SEED_OFFSET[psys->seed % PSYS_FRAND_COUNT]; + unsigned int multiplier = PSYS_FRAND_SEED_MULTIPLIER[psys->seed % PSYS_FRAND_COUNT]; + vec[0] = PSYS_FRAND_BASE[(offset + (seed + 0) * multiplier) % PSYS_FRAND_COUNT]; + vec[1] = PSYS_FRAND_BASE[(offset + (seed + 1) * multiplier) % PSYS_FRAND_COUNT]; + vec[2] = PSYS_FRAND_BASE[(offset + (seed + 2) * multiplier) % PSYS_FRAND_COUNT]; +} + /* ----------- functions needed outside particlesystem ---------------- */ /* particle.c */ int count_particles(struct ParticleSystem *psys); |