forked from bartvdbraak/blender
Use the generic task scheduler for threaded particle tasks, i.e.
distribution and path caching for child particles. This gives a significant improvement of viewport playback performance with higher child particle counts. Particles previously used their own threads and had a rather high limit for threading. Also threading apparently was disabled because only 1 thread was being used ...
This commit is contained in:
parent
c1f4542f0f
commit
fe8fad54b1
@ -160,11 +160,11 @@ typedef struct ParticleThreadContext {
|
||||
float *vg_effector;
|
||||
} ParticleThreadContext;
|
||||
|
||||
typedef struct ParticleThread {
|
||||
typedef struct ParticleTask {
|
||||
ParticleThreadContext *ctx;
|
||||
struct RNG *rng, *rng_path;
|
||||
int num, tot;
|
||||
} ParticleThread;
|
||||
int begin, end;
|
||||
} ParticleTask;
|
||||
|
||||
typedef struct ParticleBillboardData {
|
||||
struct Object *ob;
|
||||
@ -347,8 +347,9 @@ void psys_get_dupli_texture(struct ParticleSystem *psys, struct ParticleSettings
|
||||
void psys_get_dupli_path_transform(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ChildParticle *cpa,
|
||||
struct ParticleCacheKey *cache, float mat[4][4], float *scale);
|
||||
|
||||
ParticleThread *psys_threads_create(struct ParticleSimulationData *sim);
|
||||
void psys_threads_free(ParticleThread *threads);
|
||||
void psys_thread_context_init(struct ParticleThreadContext *ctx, struct ParticleSimulationData *sim);
|
||||
void psys_tasks_create(struct ParticleThreadContext *ctx, int totpart, struct ParticleTask **r_tasks, int *r_numtasks);
|
||||
void psys_tasks_free(struct ParticleTask *tasks, int numtasks);
|
||||
|
||||
void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3], float zvec[3], float center[3]);
|
||||
void psys_apply_hair_lattice(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys);
|
||||
|
@ -53,6 +53,7 @@
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_kdtree.h"
|
||||
#include "BLI_rand.h"
|
||||
#include "BLI_task.h"
|
||||
#include "BLI_threads.h"
|
||||
#include "BLI_linklist.h"
|
||||
|
||||
@ -2441,17 +2442,15 @@ static void get_strand_normal(Material *ma, const float surfnor[3], float surfdi
|
||||
copy_v3_v3(nor, vnor);
|
||||
}
|
||||
|
||||
static int psys_threads_init_path(ParticleThread *threads, Scene *scene, float cfra, int editupdate)
|
||||
static bool psys_thread_context_init_path(ParticleThreadContext *ctx, ParticleSimulationData *sim, Scene *scene, float cfra, int editupdate)
|
||||
{
|
||||
ParticleThreadContext *ctx = threads[0].ctx;
|
||||
/* Object *ob = ctx->sim.ob; */
|
||||
ParticleSystem *psys = ctx->sim.psys;
|
||||
ParticleSystem *psys = sim->psys;
|
||||
ParticleSettings *part = psys->part;
|
||||
/* ParticleEditSettings *pset = &scene->toolsettings->particle; */
|
||||
int totparent = 0, between = 0;
|
||||
int steps = (int)pow(2.0, (double)part->draw_step);
|
||||
int steps = 1 << part->draw_step;
|
||||
int totchild = psys->totchild;
|
||||
int i, seed, totthread = threads[0].tot;
|
||||
|
||||
psys_thread_context_init(ctx, sim);
|
||||
|
||||
/*---start figuring out what is actually wanted---*/
|
||||
if (psys_in_edit_mode(scene, psys)) {
|
||||
@ -2460,7 +2459,7 @@ static int psys_threads_init_path(ParticleThread *threads, Scene *scene, float c
|
||||
if (psys->renderdata == 0 && (psys->edit == NULL || pset->flag & PE_DRAW_PART) == 0)
|
||||
totchild = 0;
|
||||
|
||||
steps = (int)pow(2.0, (double)pset->draw_step);
|
||||
steps = 1 << pset->draw_step;
|
||||
}
|
||||
|
||||
if (totchild && part->childtype == PART_CHILD_FACES) {
|
||||
@ -2480,18 +2479,8 @@ static int psys_threads_init_path(ParticleThread *threads, Scene *scene, float c
|
||||
totparent = MIN2(totparent, totchild);
|
||||
}
|
||||
|
||||
if (totchild == 0) return 0;
|
||||
|
||||
/* init random number generator */
|
||||
seed = 31415926 + ctx->sim.psys->seed;
|
||||
|
||||
if (ctx->editupdate || totchild < 10000)
|
||||
totthread = 1;
|
||||
|
||||
for (i = 0; i < totthread; i++) {
|
||||
threads[i].rng_path = BLI_rng_new(seed);
|
||||
threads[i].tot = totthread;
|
||||
}
|
||||
if (totchild == 0)
|
||||
return false;
|
||||
|
||||
/* fill context values */
|
||||
ctx->between = between;
|
||||
@ -2514,21 +2503,21 @@ static int psys_threads_init_path(ParticleThread *threads, Scene *scene, float c
|
||||
if (psys->part->flag & PART_CHILD_EFFECT)
|
||||
ctx->vg_effector = psys_cache_vgroup(ctx->dm, psys, PSYS_VG_EFFECTOR);
|
||||
|
||||
/* set correct ipo timing */
|
||||
#if 0 // XXX old animation system
|
||||
if (part->flag & PART_ABS_TIME && part->ipo) {
|
||||
calc_ipo(part->ipo, cfra);
|
||||
execute_ipo((ID *)part, part->ipo);
|
||||
}
|
||||
#endif // XXX old animation system
|
||||
return true;
|
||||
}
|
||||
|
||||
return 1;
|
||||
static void psys_task_init_path(ParticleTask *task, ParticleSimulationData *sim)
|
||||
{
|
||||
/* init random number generator */
|
||||
int seed = 31415926 + sim->psys->seed;
|
||||
|
||||
task->rng_path = BLI_rng_new(seed);
|
||||
}
|
||||
|
||||
/* note: this function must be thread safe, except for branching! */
|
||||
static void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, ParticleCacheKey *child_keys, int i)
|
||||
static void psys_thread_create_path(ParticleTask *task, struct ChildParticle *cpa, ParticleCacheKey *child_keys, int i)
|
||||
{
|
||||
ParticleThreadContext *ctx = thread->ctx;
|
||||
ParticleThreadContext *ctx = task->ctx;
|
||||
Object *ob = ctx->sim.ob;
|
||||
ParticleSystem *psys = ctx->sim.psys;
|
||||
ParticleSettings *part = psys->part;
|
||||
@ -2794,47 +2783,41 @@ static void psys_thread_create_path(ParticleThread *thread, struct ChildParticle
|
||||
child_keys->steps = -1;
|
||||
}
|
||||
|
||||
static void *exec_child_path_cache(void *data)
|
||||
static void exec_child_path_cache(TaskPool *UNUSED(pool), void *taskdata, int UNUSED(threadid))
|
||||
{
|
||||
ParticleThread *thread = (ParticleThread *)data;
|
||||
ParticleThreadContext *ctx = thread->ctx;
|
||||
ParticleTask *task = taskdata;
|
||||
ParticleThreadContext *ctx = task->ctx;
|
||||
ParticleSystem *psys = ctx->sim.psys;
|
||||
ParticleCacheKey **cache = psys->childcache;
|
||||
ChildParticle *cpa;
|
||||
int i, totchild = ctx->totchild, first = 0;
|
||||
int i;
|
||||
|
||||
if (thread->tot > 1) {
|
||||
first = ctx->parent_pass ? 0 : ctx->totparent;
|
||||
totchild = ctx->parent_pass ? ctx->totparent : ctx->totchild;
|
||||
cpa = psys->child + task->begin;
|
||||
for (i = task->begin; i < task->end; ++i, ++cpa) {
|
||||
psys_thread_create_path(task, cpa, cache[i], i);
|
||||
}
|
||||
|
||||
cpa = psys->child + first + thread->num;
|
||||
for (i = first + thread->num; i < totchild; i += thread->tot, cpa += thread->tot)
|
||||
psys_thread_create_path(thread, cpa, cache[i], i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void psys_cache_child_paths(ParticleSimulationData *sim, float cfra, int editupdate)
|
||||
{
|
||||
ParticleThread *pthreads;
|
||||
ParticleThreadContext *ctx;
|
||||
ListBase threads;
|
||||
int i, totchild, totparent, totthread;
|
||||
TaskScheduler *task_scheduler;
|
||||
TaskPool *task_pool;
|
||||
ParticleThreadContext ctx;
|
||||
ParticleTask *tasks_parent, *tasks_child;
|
||||
int numtasks_parent, numtasks_child;
|
||||
int i, totchild, totparent;
|
||||
|
||||
if (sim->psys->flag & PSYS_GLOBAL_HAIR)
|
||||
return;
|
||||
|
||||
pthreads = psys_threads_create(sim);
|
||||
|
||||
if (!psys_threads_init_path(pthreads, sim->scene, cfra, editupdate)) {
|
||||
psys_threads_free(pthreads);
|
||||
/* create a task pool for child path tasks */
|
||||
if (!psys_thread_context_init_path(&ctx, sim, sim->scene, cfra, editupdate))
|
||||
return;
|
||||
}
|
||||
|
||||
ctx = pthreads[0].ctx;
|
||||
totchild = ctx->totchild;
|
||||
totparent = ctx->totparent;
|
||||
task_scheduler = BLI_task_scheduler_get();
|
||||
task_pool = BLI_task_pool_create(task_scheduler, &ctx);
|
||||
totchild = ctx.totchild;
|
||||
totparent = ctx.totparent;
|
||||
|
||||
if (editupdate && sim->psys->childcache && totchild == sim->psys->totchildcache) {
|
||||
; /* just overwrite the existing cache */
|
||||
@ -2842,41 +2825,38 @@ void psys_cache_child_paths(ParticleSimulationData *sim, float cfra, int editupd
|
||||
else {
|
||||
/* clear out old and create new empty path cache */
|
||||
free_child_path_cache(sim->psys);
|
||||
sim->psys->childcache = psys_alloc_path_cache_buffers(&sim->psys->childcachebufs, totchild, ctx->steps + 1);
|
||||
sim->psys->childcache = psys_alloc_path_cache_buffers(&sim->psys->childcachebufs, totchild, ctx.steps + 1);
|
||||
sim->psys->totchildcache = totchild;
|
||||
}
|
||||
|
||||
totthread = pthreads[0].tot;
|
||||
/* cache parent paths */
|
||||
ctx.parent_pass = 1;
|
||||
psys_tasks_create(&ctx, totparent, &tasks_parent, &numtasks_parent);
|
||||
for (i = 0; i < numtasks_parent; ++i) {
|
||||
ParticleTask *task = &tasks_parent[i];
|
||||
|
||||
if (totthread > 1) {
|
||||
|
||||
/* make virtual child parents thread safe by calculating them first */
|
||||
if (totparent) {
|
||||
BLI_init_threads(&threads, exec_child_path_cache, totthread);
|
||||
|
||||
for (i = 0; i < totthread; i++) {
|
||||
pthreads[i].ctx->parent_pass = 1;
|
||||
BLI_insert_thread(&threads, &pthreads[i]);
|
||||
psys_task_init_path(task, sim);
|
||||
BLI_task_pool_push(task_pool, exec_child_path_cache, task, false, TASK_PRIORITY_LOW);
|
||||
}
|
||||
BLI_task_pool_work_and_wait(task_pool);
|
||||
|
||||
BLI_end_threads(&threads);
|
||||
/* cache child paths */
|
||||
ctx.parent_pass = 0;
|
||||
psys_tasks_create(&ctx, totchild, &tasks_child, &numtasks_child);
|
||||
for (i = 0; i < numtasks_child; ++i) {
|
||||
ParticleTask *task = &tasks_child[i];
|
||||
|
||||
for (i = 0; i < totthread; i++)
|
||||
pthreads[i].ctx->parent_pass = 0;
|
||||
psys_task_init_path(task, sim);
|
||||
BLI_task_pool_push(task_pool, exec_child_path_cache, task, false, TASK_PRIORITY_LOW);
|
||||
}
|
||||
BLI_task_pool_work_and_wait(task_pool);
|
||||
|
||||
BLI_init_threads(&threads, exec_child_path_cache, totthread);
|
||||
BLI_task_pool_free(task_pool);
|
||||
|
||||
for (i = 0; i < totthread; i++)
|
||||
BLI_insert_thread(&threads, &pthreads[i]);
|
||||
|
||||
BLI_end_threads(&threads);
|
||||
}
|
||||
else
|
||||
exec_child_path_cache(&pthreads[0]);
|
||||
|
||||
psys_threads_free(pthreads);
|
||||
psys_tasks_free(tasks_parent, numtasks_parent);
|
||||
psys_tasks_free(tasks_child, numtasks_child);
|
||||
}
|
||||
|
||||
/* figure out incremental rotations along path starting from unit quat */
|
||||
static void cache_key_incremental_rotation(ParticleCacheKey *key0, ParticleCacheKey *key1, ParticleCacheKey *key2, float *prev_tangent, int i)
|
||||
{
|
||||
|
@ -68,6 +68,7 @@
|
||||
#include "BLI_kdtree.h"
|
||||
#include "BLI_kdopbvh.h"
|
||||
#include "BLI_sort.h"
|
||||
#include "BLI_task.h"
|
||||
#include "BLI_threads.h"
|
||||
#include "BLI_linklist.h"
|
||||
|
||||
@ -789,7 +790,7 @@ static int distribute_binary_search(float *sum, int n, float value)
|
||||
|
||||
/* note: this function must be thread safe, for from == PART_FROM_CHILD */
|
||||
#define ONLY_WORKING_WITH_PA_VERTS 0
|
||||
static void distribute_threads_exec(ParticleThread *thread, ParticleData *pa, ChildParticle *cpa, int p)
|
||||
static void distribute_threads_exec(ParticleTask *thread, ParticleData *pa, ChildParticle *cpa, int p)
|
||||
{
|
||||
ParticleThreadContext *ctx= thread->ctx;
|
||||
Object *ob= ctx->sim.ob;
|
||||
@ -979,36 +980,40 @@ static void distribute_threads_exec(ParticleThread *thread, ParticleData *pa, Ch
|
||||
BLI_rng_skip(thread->rng, rng_skip_tot);
|
||||
}
|
||||
|
||||
static void *distribute_threads_exec_cb(void *data)
|
||||
static void exec_distribute_parent(TaskPool *UNUSED(pool), void *taskdata, int UNUSED(threadid))
|
||||
{
|
||||
ParticleThread *thread= (ParticleThread*)data;
|
||||
ParticleSystem *psys= thread->ctx->sim.psys;
|
||||
ParticleTask *task = taskdata;
|
||||
ParticleSystem *psys= task->ctx->sim.psys;
|
||||
ParticleData *pa;
|
||||
int p;
|
||||
|
||||
pa= psys->particles + task->begin;
|
||||
for (p = task->begin; p < task->end; ++p, ++pa)
|
||||
distribute_threads_exec(task, pa, NULL, p);
|
||||
}
|
||||
|
||||
static void exec_distribute_child(TaskPool *UNUSED(pool), void *taskdata, int UNUSED(threadid))
|
||||
{
|
||||
ParticleTask *task = taskdata;
|
||||
ParticleSystem *psys = task->ctx->sim.psys;
|
||||
ChildParticle *cpa;
|
||||
int p, totpart;
|
||||
int p;
|
||||
|
||||
if (thread->ctx->from == PART_FROM_CHILD) {
|
||||
totpart= psys->totchild;
|
||||
cpa= psys->child;
|
||||
/* RNG skipping at the beginning */
|
||||
cpa = psys->child;
|
||||
for (p = 0; p < task->begin; ++p, ++cpa) {
|
||||
if (task->ctx->skip) /* simplification skip */
|
||||
BLI_rng_skip(task->rng, PSYS_RND_DIST_SKIP * task->ctx->skip[p]);
|
||||
|
||||
for (p=0; p<totpart; p++, cpa++) {
|
||||
if (thread->ctx->skip) /* simplification skip */
|
||||
BLI_rng_skip(thread->rng, PSYS_RND_DIST_SKIP * thread->ctx->skip[p]);
|
||||
|
||||
if ((p+thread->num) % thread->tot == 0)
|
||||
distribute_threads_exec(thread, NULL, cpa, p);
|
||||
else /* thread skip */
|
||||
BLI_rng_skip(thread->rng, PSYS_RND_DIST_SKIP);
|
||||
}
|
||||
}
|
||||
else {
|
||||
totpart= psys->totpart;
|
||||
pa= psys->particles + thread->num;
|
||||
for (p=thread->num; p<totpart; p+=thread->tot, pa+=thread->tot)
|
||||
distribute_threads_exec(thread, pa, NULL, p);
|
||||
BLI_rng_skip(task->rng, PSYS_RND_DIST_SKIP);
|
||||
}
|
||||
|
||||
return 0;
|
||||
for (; p < task->end; ++p, ++cpa) {
|
||||
if (task->ctx->skip) /* simplification skip */
|
||||
BLI_rng_skip(task->rng, PSYS_RND_DIST_SKIP * task->ctx->skip[p]);
|
||||
|
||||
distribute_threads_exec(task, NULL, cpa, p);
|
||||
}
|
||||
}
|
||||
|
||||
static int distribute_compare_orig_index(const void *p1, const void *p2, void *user_data)
|
||||
@ -1061,18 +1066,19 @@ static void distribute_invalid(Scene *scene, ParticleSystem *psys, int from)
|
||||
|
||||
/* Creates a distribution of coordinates on a DerivedMesh */
|
||||
/* This is to denote functionality that does not yet work with mesh - only derived mesh */
|
||||
static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, DerivedMesh *finaldm, int from)
|
||||
static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, ParticleSimulationData *sim, int from)
|
||||
{
|
||||
ParticleThreadContext *ctx= threads[0].ctx;
|
||||
Object *ob= ctx->sim.ob;
|
||||
ParticleSystem *psys= ctx->sim.psys;
|
||||
Scene *scene = sim->scene;
|
||||
DerivedMesh *finaldm = sim->psmd->dm;
|
||||
Object *ob = sim->ob;
|
||||
ParticleSystem *psys= sim->psys;
|
||||
ParticleData *pa=0, *tpars= 0;
|
||||
ParticleSettings *part;
|
||||
ParticleSeam *seams= 0;
|
||||
KDTree *tree=0;
|
||||
DerivedMesh *dm= NULL;
|
||||
float *jit= NULL;
|
||||
int i, seed, p=0, totthread= threads[0].tot;
|
||||
int i, p=0;
|
||||
int cfrom=0;
|
||||
int totelem=0, totpart, *particle_element=0, children=0, totseam=0;
|
||||
int jitlevel= 1, distr;
|
||||
@ -1093,6 +1099,8 @@ static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, D
|
||||
return 0;
|
||||
}
|
||||
|
||||
psys_thread_context_init(ctx, sim);
|
||||
|
||||
/* First handle special cases */
|
||||
if (from == PART_FROM_CHILD) {
|
||||
/* Simple children */
|
||||
@ -1392,52 +1400,54 @@ static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, D
|
||||
alloc_child_particles(psys, totpart);
|
||||
}
|
||||
|
||||
if (!children || psys->totchild < 10000)
|
||||
totthread= 1;
|
||||
|
||||
seed= 31415926 + ctx->sim.psys->seed;
|
||||
for (i=0; i<totthread; i++) {
|
||||
threads[i].rng= BLI_rng_new(seed);
|
||||
threads[i].tot= totthread;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void psys_task_init_distribute(ParticleTask *task, ParticleSimulationData *sim)
|
||||
{
|
||||
/* init random number generator */
|
||||
int seed = 31415926 + sim->psys->seed;
|
||||
|
||||
task->rng = BLI_rng_new(seed);
|
||||
}
|
||||
|
||||
static void distribute_particles_on_dm(ParticleSimulationData *sim, int from)
|
||||
{
|
||||
TaskScheduler *task_scheduler;
|
||||
TaskPool *task_pool;
|
||||
ParticleThreadContext ctx;
|
||||
ParticleTask *tasks;
|
||||
DerivedMesh *finaldm = sim->psmd->dm;
|
||||
ListBase threads;
|
||||
ParticleThread *pthreads;
|
||||
ParticleThreadContext *ctx;
|
||||
int i, totthread;
|
||||
int i, totpart, numtasks;
|
||||
|
||||
pthreads= psys_threads_create(sim);
|
||||
|
||||
if (!distribute_threads_init_data(pthreads, sim->scene, finaldm, from)) {
|
||||
psys_threads_free(pthreads);
|
||||
/* create a task pool for distribution tasks */
|
||||
if (!psys_thread_context_init_distribute(&ctx, sim, from))
|
||||
return;
|
||||
}
|
||||
|
||||
totthread= pthreads[0].tot;
|
||||
if (totthread > 1) {
|
||||
BLI_init_threads(&threads, distribute_threads_exec_cb, totthread);
|
||||
task_scheduler = BLI_task_scheduler_get();
|
||||
task_pool = BLI_task_pool_create(task_scheduler, &ctx);
|
||||
|
||||
for (i=0; i<totthread; i++)
|
||||
BLI_insert_thread(&threads, &pthreads[i]);
|
||||
totpart = (from == PART_FROM_CHILD ? sim->psys->totchild : sim->psys->totpart);
|
||||
psys_tasks_create(&ctx, totpart, &tasks, &numtasks);
|
||||
for (i = 0; i < numtasks; ++i) {
|
||||
ParticleTask *task = &tasks[i];
|
||||
|
||||
BLI_end_threads(&threads);
|
||||
}
|
||||
psys_task_init_distribute(task, sim);
|
||||
if (from == PART_FROM_CHILD)
|
||||
BLI_task_pool_push(task_pool, exec_distribute_child, task, false, TASK_PRIORITY_LOW);
|
||||
else
|
||||
distribute_threads_exec_cb(&pthreads[0]);
|
||||
BLI_task_pool_push(task_pool, exec_distribute_parent, task, false, TASK_PRIORITY_LOW);
|
||||
}
|
||||
BLI_task_pool_work_and_wait(task_pool);
|
||||
|
||||
BLI_task_pool_free(task_pool);
|
||||
|
||||
psys_calc_dmcache(sim->ob, finaldm, sim->psys);
|
||||
|
||||
ctx= pthreads[0].ctx;
|
||||
if (ctx->dm != finaldm)
|
||||
ctx->dm->release(ctx->dm);
|
||||
if (ctx.dm != finaldm)
|
||||
ctx.dm->release(ctx.dm);
|
||||
|
||||
psys_threads_free(pthreads);
|
||||
psys_tasks_free(tasks, numtasks);
|
||||
}
|
||||
|
||||
/* ready for future use, to emit particles without geometry */
|
||||
@ -1470,35 +1480,55 @@ static void distribute_particles(ParticleSimulationData *sim, int from)
|
||||
}
|
||||
|
||||
/* threaded child particle distribution and path caching */
|
||||
ParticleThread *psys_threads_create(ParticleSimulationData *sim)
|
||||
void psys_thread_context_init(ParticleThreadContext *ctx, ParticleSimulationData *sim)
|
||||
{
|
||||
ParticleThread *threads;
|
||||
ParticleThreadContext *ctx;
|
||||
int i, totthread = BKE_scene_num_threads(sim->scene);
|
||||
|
||||
threads= MEM_callocN(sizeof(ParticleThread)*totthread, "ParticleThread");
|
||||
ctx= MEM_callocN(sizeof(ParticleThreadContext), "ParticleThreadContext");
|
||||
|
||||
memset(ctx, 0, sizeof(ParticleThreadContext));
|
||||
ctx->sim = *sim;
|
||||
ctx->dm= ctx->sim.psmd->dm;
|
||||
ctx->ma= give_current_material(sim->ob, sim->psys->part->omat);
|
||||
|
||||
memset(threads, 0, sizeof(ParticleThread)*totthread);
|
||||
|
||||
for (i=0; i<totthread; i++) {
|
||||
threads[i].ctx= ctx;
|
||||
threads[i].num= i;
|
||||
threads[i].tot= totthread;
|
||||
}
|
||||
|
||||
return threads;
|
||||
ctx->dm = ctx->sim.psmd->dm;
|
||||
ctx->ma = give_current_material(sim->ob, sim->psys->part->omat);
|
||||
}
|
||||
|
||||
void psys_threads_free(ParticleThread *threads)
|
||||
{
|
||||
ParticleThreadContext *ctx= threads[0].ctx;
|
||||
int i, totthread= threads[0].tot;
|
||||
#define MAX_PARTICLES_PER_TASK 256 /* XXX arbitrary - maybe use at least number of points instead for better balancing? */
|
||||
|
||||
BLI_INLINE int ceil_ii(int a, int b)
|
||||
{
|
||||
return (a + b - 1) / b;
|
||||
}
|
||||
|
||||
void psys_tasks_create(ParticleThreadContext *ctx, int totpart, ParticleTask **r_tasks, int *r_numtasks)
|
||||
{
|
||||
ParticleTask *tasks;
|
||||
int numtasks = ceil_ii(totpart, MAX_PARTICLES_PER_TASK);
|
||||
float particles_per_task = (float)totpart / (float)numtasks, p, pnext;
|
||||
int i;
|
||||
|
||||
tasks = MEM_callocN(sizeof(ParticleTask) * numtasks, "ParticleThread");
|
||||
*r_numtasks = numtasks;
|
||||
*r_tasks = tasks;
|
||||
|
||||
printf("made %d tasks:\n", numtasks);
|
||||
p = 0.0f;
|
||||
printf(" %d", (int)p);
|
||||
for (i = 0; i < numtasks; i++, p = pnext) {
|
||||
pnext = p + particles_per_task;
|
||||
|
||||
tasks[i].ctx = ctx;
|
||||
tasks[i].begin = (int)p;
|
||||
tasks[i].end = min_ii((int)pnext, totpart);
|
||||
printf("..%d", tasks[i].end);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void psys_tasks_free(ParticleTask *tasks, int numtasks)
|
||||
{
|
||||
ParticleThreadContext *ctx;
|
||||
int i;
|
||||
|
||||
if (numtasks == 0)
|
||||
return;
|
||||
|
||||
ctx = tasks[0].ctx;
|
||||
/* path caching */
|
||||
if (ctx->vg_length)
|
||||
MEM_freeN(ctx->vg_length);
|
||||
@ -1529,15 +1559,14 @@ void psys_threads_free(ParticleThread *threads)
|
||||
BLI_kdtree_free(ctx->tree);
|
||||
|
||||
/* threads */
|
||||
for (i=0; i<totthread; i++) {
|
||||
if (threads[i].rng)
|
||||
BLI_rng_free(threads[i].rng);
|
||||
if (threads[i].rng_path)
|
||||
BLI_rng_free(threads[i].rng_path);
|
||||
for (i = 0; i < numtasks; ++i) {
|
||||
if (tasks[i].rng)
|
||||
BLI_rng_free(tasks[i].rng);
|
||||
if (tasks[i].rng_path)
|
||||
BLI_rng_free(tasks[i].rng_path);
|
||||
}
|
||||
|
||||
MEM_freeN(ctx);
|
||||
MEM_freeN(threads);
|
||||
MEM_freeN(tasks);
|
||||
}
|
||||
|
||||
static void initialize_particle_texture(ParticleSimulationData *sim, ParticleData *pa, int p)
|
||||
|
Loading…
Reference in New Issue
Block a user