diff options
author | Kévin Dietrich <kevin.dietrich@mailoo.org> | 2016-01-17 04:01:41 +0300 |
---|---|---|
committer | Kévin Dietrich <kevin.dietrich@mailoo.org> | 2016-01-17 04:01:41 +0300 |
commit | 45b6893e7045f0f2ce02e2b97a877fd54c2078b9 (patch) | |
tree | d22e089c61f44e3a14647ad8e9a5b073db26b112 /source/blender | |
parent | 75cfc81ec39ac9953f25eb0ae5f9e70d3c24ee7e (diff) |
Point Cache: use job system for bake operators.
Reviewers: brecht
Differential Revision: https://developer.blender.org/D1731
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/BKE_pointcache.h | 8 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/pointcache.c | 168 | ||||
-rw-r--r-- | source/blender/editors/physics/physics_pointcache.c | 222 | ||||
-rw-r--r-- | source/blender/render/intern/source/pipeline.c | 5 | ||||
-rw-r--r-- | source/blender/windowmanager/WM_api.h | 1 |
5 files changed, 203 insertions, 201 deletions
diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index a3ffad1f66b..d1b8aa672c5 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -178,11 +178,9 @@ typedef struct PTCacheBaker { int anim_init; int quick_step; struct PTCacheID *pid; - int (*break_test)(void *data); - void *break_data; - void (*progressbar)(void *data, int num); - void (*progressend)(void *data); - void *progresscontext; + + void (*update_progress)(void *data, float progress, int *cancel); + void *bake_job; } PTCacheBaker; /* PTCacheEditKey->flag */ diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 4eb3af6bbcf..7009b4b0ce2 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -3111,33 +3111,18 @@ void BKE_ptcache_quick_cache_all(Main *bmain, Scene *scene) PTCacheBaker baker; baker.bake=0; - baker.break_data=NULL; - baker.break_test=NULL; baker.pid=NULL; - baker.progressbar=NULL; - baker.progressend=NULL; - baker.progresscontext=NULL; baker.render=0; baker.anim_init = 0; baker.main=bmain; baker.scene=scene; baker.quick_step=scene->physics_settings.quick_cache_step; + baker.update_progress = NULL; + baker.bake_job = NULL; BKE_ptcache_bake(&baker); } -/* Simulation thread, no need for interlocks as data written in both threads - * are only unitary integers (I/O assumed to be atomic for them) */ -typedef struct { - int break_operation; - int thread_ended; - int endframe; - int step; - int *cfra_ptr; - Main *main; - Scene *scene; -} ptcache_bake_data; - static void ptcache_dt_to_str(char *str, double dtime) { if (dtime > 60.0) { @@ -3150,52 +3135,6 @@ static void ptcache_dt_to_str(char *str, double dtime) sprintf(str, "%is", ((int)dtime) % 60); } -static void *ptcache_bake_thread(void *ptr) -{ - bool use_timer = false; - int sfra, efra; - double stime, ptime, ctime, fetd; - char run[32], cur[32], etd[32]; - - ptcache_bake_data *data = (ptcache_bake_data*)ptr; - - stime = ptime = PIL_check_seconds_timer(); - sfra = *data->cfra_ptr; - efra = data->endframe; - - for (; (*data->cfra_ptr <= data->endframe) && !data->break_operation; *data->cfra_ptr+=data->step) { - BKE_scene_update_for_newframe(G.main->eval_ctx, data->main, data->scene, data->scene->lay); - if (G.background) { - printf("bake: frame %d :: %d\n", (int)*data->cfra_ptr, data->endframe); - } - else { - ctime = PIL_check_seconds_timer(); - - fetd = (ctime-ptime)*(efra-*data->cfra_ptr)/data->step; - - if (use_timer || fetd > 60.0) { - use_timer = true; - - ptcache_dt_to_str(cur, ctime-ptime); - ptcache_dt_to_str(run, ctime-stime); - ptcache_dt_to_str(etd, fetd); - - printf("Baked for %s, current frame: %i/%i (%.3fs), ETC: %s\r", run, *data->cfra_ptr-sfra+1, efra-sfra+1, ctime-ptime, etd); - } - ptime = ctime; - } - } - - if (use_timer) { - /* start with newline because of \r above */ - ptcache_dt_to_str(run, PIL_check_seconds_timer()-stime); - printf("\nBake %s %s (%i frames simulated).\n", (data->break_operation ? "canceled after" : "finished in"), run, *data->cfra_ptr-sfra); - } - - data->thread_ended = true; - return NULL; -} - /* if bake is not given run simulations to current frame */ void BKE_ptcache_bake(PTCacheBaker *baker) { @@ -3208,19 +3147,10 @@ void BKE_ptcache_bake(PTCacheBaker *baker) PointCache *cache = NULL; float frameleno = scene->r.framelen; int cfrao = CFRA; - int startframe = MAXFRAME; + int startframe = MAXFRAME, endframe = MAXFRAME; int bake = baker->bake; int render = baker->render; - ListBase threads; - ptcache_bake_data thread_data; - int progress, old_progress; - thread_data.endframe = baker->anim_init ? scene->r.sfra : CFRA; - thread_data.step = baker->quick_step; - thread_data.cfra_ptr = &CFRA; - thread_data.scene = baker->scene; - thread_data.main = baker->main; - G.is_break = false; /* set caches to baking mode and figure out start frame */ @@ -3261,11 +3191,11 @@ void BKE_ptcache_bake(PTCacheBaker *baker) startframe = MAX2(cache->last_exact, cache->startframe); if (bake) { - thread_data.endframe = cache->endframe; + endframe = cache->endframe; cache->flag |= PTCACHE_BAKING; } else { - thread_data.endframe = MIN2(thread_data.endframe, cache->endframe); + endframe = MIN2(endframe, cache->endframe); } cache->flag &= ~PTCACHE_BAKED; @@ -3300,7 +3230,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker) cache->flag |= PTCACHE_BAKING; if (bake) - thread_data.endframe = MAX2(thread_data.endframe, cache->endframe); + endframe = MAX2(endframe, cache->endframe); } cache->flag &= ~PTCACHE_BAKED; @@ -3313,46 +3243,63 @@ void BKE_ptcache_bake(PTCacheBaker *baker) CFRA = startframe; scene->r.framelen = 1.0; - thread_data.break_operation = false; - thread_data.thread_ended = false; - old_progress = -1; - WM_cursor_wait(1); - - if (G.background) { - ptcache_bake_thread((void*)&thread_data); - } - else { - BLI_init_threads(&threads, ptcache_bake_thread, 1); - BLI_insert_thread(&threads, (void*)&thread_data); + /* bake */ - while (thread_data.thread_ended == false) { + bool use_timer = false; + double stime, ptime, ctime, fetd; + char run[32], cur[32], etd[32]; + int cancel = 0; - if (bake) - progress = (int)(100.0f * (float)(CFRA - startframe)/(float)(thread_data.endframe-startframe)); - else - progress = CFRA; + stime = ptime = PIL_check_seconds_timer(); - /* NOTE: baking should not redraw whole ui as this slows things down */ - if ((baker->progressbar) && (progress != old_progress)) { - baker->progressbar(baker->progresscontext, progress); - old_progress = progress; - } + for (int fr = CFRA; fr <= endframe; fr += baker->quick_step, CFRA = fr) { + BKE_scene_update_for_newframe(G.main->eval_ctx, bmain, scene, scene->lay); + + if (baker->update_progress) { + float progress = ((float)(CFRA - startframe)/(float)(endframe - startframe)); + baker->update_progress(baker->bake_job, progress, &cancel); + } + + if (G.background) { + printf("bake: frame %d :: %d\n", CFRA, endframe); + } + else { + ctime = PIL_check_seconds_timer(); + + fetd = (ctime - ptime) * (endframe - CFRA) / baker->quick_step; + + if (use_timer || fetd > 60.0) { + use_timer = true; - /* Delay to lessen CPU load from UI thread */ - PIL_sleep_ms(200); + ptcache_dt_to_str(cur, ctime - ptime); + ptcache_dt_to_str(run, ctime - stime); + ptcache_dt_to_str(etd, fetd); - /* NOTE: breaking baking should leave calculated frames in cache, not clear it */ - if (blender_test_break() && !thread_data.break_operation) { - thread_data.break_operation = true; - if (baker->progressend) - baker->progressend(baker->progresscontext); - WM_cursor_wait(1); + printf("Baked for %s, current frame: %i/%i (%.3fs), ETC: %s\r", + run, CFRA - startframe + 1, endframe - startframe + 1, ctime - ptime, etd); } + + ptime = ctime; + } + + /* Delay to lessen CPU load from UI thread */ + PIL_sleep_ms(200); + + /* NOTE: breaking baking should leave calculated frames in cache, not clear it */ + if ((cancel || G.is_break)) { + break; } - BLI_end_threads(&threads); + CFRA += 1; } + + if (use_timer) { + /* start with newline because of \r above */ + ptcache_dt_to_str(run, PIL_check_seconds_timer()-stime); + printf("\nBake %s %s (%i frames simulated).\n", (cancel ? "canceled after" : "finished in"), run, CFRA - startframe); + } + /* clear baking flag */ if (pid) { cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED); @@ -3375,7 +3322,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker) cache = pid->cache; - if (thread_data.step > 1) + if (baker->quick_step > 1) cache->flag &= ~(PTCACHE_BAKING|PTCACHE_OUTDATED); else cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED); @@ -3399,13 +3346,6 @@ void BKE_ptcache_bake(PTCacheBaker *baker) BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, scene->lay); } - if (thread_data.break_operation) - WM_cursor_wait(0); - else if (baker->progressend) - baker->progressend(baker->progresscontext); - - WM_cursor_wait(0); - /* TODO: call redraw all windows somehow */ } /* Helpers */ diff --git a/source/blender/editors/physics/physics_pointcache.c b/source/blender/editors/physics/physics_pointcache.c index 71e5e23b5f1..406b5892234 100644 --- a/source/blender/editors/physics/physics_pointcache.c +++ b/source/blender/editors/physics/physics_pointcache.c @@ -31,12 +31,15 @@ #include <stdlib.h> +#include "MEM_guardedalloc.h" + #include "BLI_blenlib.h" #include "BLI_utildefines.h" #include "DNA_scene_types.h" #include "BKE_context.h" +#include "BKE_screen.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_particle.h" @@ -52,10 +55,6 @@ #include "physics_intern.h" -static int cache_break_test(void *UNUSED(cbd)) -{ - return (G.is_break == true); -} static int ptcache_bake_all_poll(bContext *C) { Scene *scene= CTX_data_scene(C); @@ -72,15 +71,85 @@ static int ptcache_poll(bContext *C) return (ptr.data && ptr.id.data); } -static void bake_console_progress(void *UNUSED(arg), int nr) +typedef struct PointCacheJob { + void *owner; + short *stop, *do_update; + float *progress; + + PTCacheBaker *baker; + Object *ob; + ListBase pidlist; +} PointCacheJob; + +static void ptcache_job_free(void *customdata) +{ + PointCacheJob *job = customdata; + BLI_freelistN(&job->pidlist); + MEM_freeN(job->baker); + MEM_freeN(job); +} + +static int ptcache_job_break(void *customdata) +{ + PointCacheJob *job = customdata; + + if (G.is_break) { + return 1; + } + + if (job->stop && *(job->stop)) { + return 1; + } + + return 0; +} + +static void ptcache_job_update(void *customdata, float progress, int *cancel) +{ + PointCacheJob *job = customdata; + + if (ptcache_job_break(job)) { + *cancel = 1; + } + + *(job->do_update) = true; + *(job->progress) = progress; +} + +static void ptcache_job_startjob(void *customdata, short *stop, short *do_update, float *progress) { - printf("\rbake: %3i%%", nr); - fflush(stdout); + PointCacheJob *job = customdata; + + job->stop = stop; + job->do_update = do_update; + job->progress = progress; + + G.is_break = false; + + /* XXX annoying hack: needed to prevent data corruption when changing + * scene frame in separate threads + */ + G.is_rendering = true; + BKE_spacedata_draw_locks(true); + + BKE_ptcache_bake(job->baker); + + *do_update = true; + *stop = 0; } -static void bake_console_progress_end(void *UNUSED(arg)) +static void ptcache_job_endjob(void *customdata) { - printf("\rbake: done!\n"); + PointCacheJob *job = customdata; + Scene *scene = job->baker->scene; + + G.is_rendering = false; + BKE_spacedata_draw_locks(false); + + WM_set_locked_interface(G.main->wm.first, false); + + WM_main_add_notifier(NC_SCENE | ND_FRAME, scene); + WM_main_add_notifier(NC_OBJECT | ND_POINTCACHE, job->ob); } static void ptcache_free_bake(PointCache *cache) @@ -100,41 +169,41 @@ static void ptcache_free_bake(PointCache *cache) static int ptcache_bake_all_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); - Scene *scene= CTX_data_scene(C); - wmWindow *win = G.background ? NULL : CTX_wm_window(C); - PTCacheBaker baker; - - baker.main = bmain; - baker.scene = scene; - baker.pid = NULL; - baker.bake = RNA_boolean_get(op->ptr, "bake"); - baker.render = 0; - baker.anim_init = 0; - baker.quick_step = 1; - baker.break_test = cache_break_test; - baker.break_data = NULL; - - /* Disabled for now as this doesn't work properly, - * and pointcache baking will be reimplemented with - * the job system soon anyways. */ - if (win) { - baker.progressbar = (void (*)(void *, int))WM_cursor_time; - baker.progressend = (void (*)(void *))WM_cursor_modal_restore; - baker.progresscontext = win; - } - else { - baker.progressbar = bake_console_progress; - baker.progressend = bake_console_progress_end; - baker.progresscontext = NULL; - } + Scene *scene = CTX_data_scene(C); - BKE_ptcache_bake(&baker); + PTCacheBaker *baker = MEM_mallocN(sizeof(PTCacheBaker), "PTCacheBaker"); - WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene); - WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, NULL); + baker->main = bmain; + baker->scene = scene; + baker->pid = NULL; + baker->bake = RNA_boolean_get(op->ptr, "bake"); + baker->render = 0; + baker->anim_init = 0; + baker->quick_step = 1; + baker->update_progress = ptcache_job_update; + + PointCacheJob *job = MEM_mallocN(sizeof(PointCacheJob), "PointCacheJob"); + job->baker = baker; + job->ob = NULL; + job->pidlist.first = NULL; + job->pidlist.last = NULL; + + baker->bake_job = job; + + wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Point Cache", + WM_JOB_PROGRESS, WM_JOB_TYPE_POINTCACHE); + + WM_jobs_customdata_set(wm_job, job, ptcache_job_free); + WM_jobs_timer(wm_job, 0.1, NC_OBJECT | ND_POINTCACHE, NC_OBJECT | ND_POINTCACHE); + WM_jobs_callbacks(wm_job, ptcache_job_startjob, NULL, NULL, ptcache_job_endjob); + + WM_set_locked_interface(CTX_wm_manager(C), true); + + WM_jobs_start(CTX_wm_manager(C), wm_job); return OPERATOR_FINISHED; } + static int ptcache_free_bake_all_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene= CTX_data_scene(C); @@ -189,59 +258,54 @@ void PTCACHE_OT_free_bake_all(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; } + static int ptcache_bake_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - wmWindow *win = G.background ? NULL : CTX_wm_window(C); - PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache); - Object *ob= ptr.id.data; - PointCache *cache= ptr.data; - PTCacheBaker baker; - PTCacheID *pid; - ListBase pidlist; - - BKE_ptcache_ids_from_object(&pidlist, ob, scene, MAX_DUPLI_RECUR); - - for (pid=pidlist.first; pid; pid=pid->next) { - if (pid->cache == cache) + PointerRNA ptr = CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache); + Object *ob = ptr.id.data; + PointCache *cache = ptr.data; + + PTCacheBaker *baker = MEM_mallocN(sizeof(PTCacheBaker), "PTCacheBaker"); + baker->main = bmain; + baker->scene = scene; + baker->bake = RNA_boolean_get(op->ptr, "bake"); + baker->render = 0; + baker->anim_init = 0; + baker->quick_step = 1; + baker->update_progress = ptcache_job_update; + baker->pid = NULL; + + PointCacheJob *job = MEM_mallocN(sizeof(PointCacheJob), "PointCacheJob"); + job->baker = baker; + job->ob = ob; + + BKE_ptcache_ids_from_object(&job->pidlist, ob, scene, MAX_DUPLI_RECUR); + + for (PTCacheID *pid = job->pidlist.first; pid; pid = pid->next) { + if (pid->cache == cache) { + baker->pid = pid; break; + } } - baker.main = bmain; - baker.scene = scene; - baker.pid = pid; - baker.bake = RNA_boolean_get(op->ptr, "bake"); - baker.render = 0; - baker.anim_init = 0; - baker.quick_step = 1; - baker.break_test = cache_break_test; - baker.break_data = NULL; - - /* Disabled for now as this doesn't work properly, - * and pointcache baking will be reimplemented with - * the job system soon anyways. */ - if (win) { - baker.progressbar = (void (*)(void *, int))WM_cursor_time; - baker.progressend = (void (*)(void *))WM_cursor_modal_restore; - baker.progresscontext = win; - } - else { - printf("\n"); /* empty first line before console reports */ - baker.progressbar = bake_console_progress; - baker.progressend = bake_console_progress_end; - baker.progresscontext = NULL; - } + baker->bake_job = job; - BKE_ptcache_bake(&baker); + wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Point Cache", + WM_JOB_PROGRESS, WM_JOB_TYPE_POINTCACHE); - BLI_freelistN(&pidlist); + WM_jobs_customdata_set(wm_job, job, ptcache_job_free); + WM_jobs_timer(wm_job, 0.1, NC_OBJECT | ND_POINTCACHE, NC_OBJECT | ND_POINTCACHE); + WM_jobs_callbacks(wm_job, ptcache_job_startjob, NULL, NULL, ptcache_job_endjob); - WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene); - WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob); + WM_set_locked_interface(CTX_wm_manager(C), true); + + WM_jobs_start(CTX_wm_manager(C), wm_job); return OPERATOR_FINISHED; } + static int ptcache_free_bake_exec(bContext *C, wmOperator *UNUSED(op)) { PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache); diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 44337098970..3f7cfa8c690 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -3050,9 +3050,8 @@ static void update_physics_cache(Render *re, Scene *scene, int UNUSED(anim_init) baker.render = 1; baker.anim_init = 1; baker.quick_step = 1; - baker.break_test = re->test_break; - baker.break_data = re->tbh; - baker.progressbar = NULL; + baker.update_progress = NULL; + baker.bake_job = NULL; BKE_ptcache_bake(&baker); } diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 7100a46b622..fa7fde22611 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -442,6 +442,7 @@ enum { WM_JOB_TYPE_CLIP_PREFETCH, WM_JOB_TYPE_SEQ_BUILD_PROXY, WM_JOB_TYPE_SEQ_BUILD_PREVIEW, + WM_JOB_TYPE_POINTCACHE, /* add as needed, screencast, seq proxy build * if having hard coded values is a problem */ }; |