Fix T47971: rigid body baking crash due to thread race condition.
This commit is contained in:
parent
b03ff0bbf8
commit
74e40663da
@ -190,7 +190,7 @@ typedef struct PTCacheBaker {
|
||||
int render;
|
||||
int anim_init;
|
||||
int quick_step;
|
||||
struct PTCacheID *pid;
|
||||
struct PTCacheID pid;
|
||||
|
||||
void (*update_progress)(void *data, float progress, int *cancel);
|
||||
void *bake_job;
|
||||
|
@ -3508,15 +3508,13 @@ void BKE_ptcache_quick_cache_all(Main *bmain, Scene *scene)
|
||||
{
|
||||
PTCacheBaker baker;
|
||||
|
||||
baker.bake=0;
|
||||
baker.pid=NULL;
|
||||
baker.render=0;
|
||||
memset(&baker, 0, sizeof(baker));
|
||||
baker.main = bmain;
|
||||
baker.scene = scene;
|
||||
baker.bake = 0;
|
||||
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;
|
||||
baker.quick_step = scene->physics_settings.quick_cache_step;
|
||||
|
||||
BKE_ptcache_bake(&baker);
|
||||
}
|
||||
@ -3541,7 +3539,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
|
||||
Scene *sce_iter; /* SETLOOPER macro only */
|
||||
Base *base;
|
||||
ListBase pidlist;
|
||||
PTCacheID *pid = baker->pid;
|
||||
PTCacheID *pid = &baker->pid;
|
||||
PointCache *cache = NULL;
|
||||
float frameleno = scene->r.framelen;
|
||||
int cfrao = CFRA;
|
||||
@ -3552,7 +3550,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
|
||||
G.is_break = false;
|
||||
|
||||
/* set caches to baking mode and figure out start frame */
|
||||
if (pid) {
|
||||
if (pid->ob) {
|
||||
/* cache/bake a single object */
|
||||
cache = pid->cache;
|
||||
if ((cache->flag & PTCACHE_BAKED)==0) {
|
||||
|
@ -30,6 +30,7 @@
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
@ -57,12 +58,7 @@
|
||||
|
||||
static int ptcache_bake_all_poll(bContext *C)
|
||||
{
|
||||
Scene *scene= CTX_data_scene(C);
|
||||
|
||||
if (!scene)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
return CTX_data_scene(C) != NULL;
|
||||
}
|
||||
|
||||
static int ptcache_poll(bContext *C)
|
||||
@ -77,14 +73,11 @@ typedef struct PointCacheJob {
|
||||
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);
|
||||
}
|
||||
@ -149,7 +142,7 @@ static void ptcache_job_endjob(void *customdata)
|
||||
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);
|
||||
WM_main_add_notifier(NC_OBJECT | ND_POINTCACHE, job->baker->pid.ob);
|
||||
}
|
||||
|
||||
static void ptcache_free_bake(PointCache *cache)
|
||||
@ -166,32 +159,60 @@ static void ptcache_free_bake(PointCache *cache)
|
||||
}
|
||||
}
|
||||
|
||||
static int ptcache_bake_all_exec(bContext *C, wmOperator *op)
|
||||
static PTCacheBaker *ptcache_baker_create(bContext *C, wmOperator *op, bool all)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
PTCacheBaker *baker = MEM_callocN(sizeof(PTCacheBaker), "PTCacheBaker");
|
||||
|
||||
PTCacheBaker *baker = MEM_mallocN(sizeof(PTCacheBaker), "PTCacheBaker");
|
||||
|
||||
baker->main = bmain;
|
||||
baker->scene = scene;
|
||||
baker->pid = NULL;
|
||||
baker->main = CTX_data_main(C);
|
||||
baker->scene = CTX_data_scene(C);
|
||||
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;
|
||||
|
||||
if (!all) {
|
||||
PointerRNA ptr = CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
|
||||
Object *ob = ptr.id.data;
|
||||
PointCache *cache = ptr.data;
|
||||
|
||||
ListBase pidlist;
|
||||
BKE_ptcache_ids_from_object(&pidlist, ob, baker->scene, MAX_DUPLI_RECUR);
|
||||
|
||||
for (PTCacheID *pid = pidlist.first; pid; pid = pid->next) {
|
||||
if (pid->cache == cache) {
|
||||
baker->pid = *pid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BLI_freelistN(&pidlist);
|
||||
}
|
||||
|
||||
return baker;
|
||||
}
|
||||
|
||||
static int ptcache_bake_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
bool all = STREQ(op->type->idname, "PTCACHE_OT_bake_all");
|
||||
|
||||
PTCacheBaker *baker = ptcache_baker_create(C, op, all);
|
||||
BKE_ptcache_bake(baker);
|
||||
MEM_freeN(baker);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static int ptcache_bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
|
||||
{
|
||||
bool all = STREQ(op->type->idname, "PTCACHE_OT_bake_all");
|
||||
|
||||
PointCacheJob *job = MEM_mallocN(sizeof(PointCacheJob), "PointCacheJob");
|
||||
job->baker = baker;
|
||||
job->ob = NULL;
|
||||
job->pidlist.first = NULL;
|
||||
job->pidlist.last = NULL;
|
||||
job->baker = ptcache_baker_create(C, op, all);
|
||||
job->baker->bake_job = job;
|
||||
job->baker->update_progress = ptcache_job_update;
|
||||
|
||||
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);
|
||||
wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), CTX_data_scene(C),
|
||||
"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);
|
||||
@ -201,7 +222,33 @@ static int ptcache_bake_all_exec(bContext *C, wmOperator *op)
|
||||
|
||||
WM_jobs_start(CTX_wm_manager(C), wm_job);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
WM_event_add_modal_handler(C, op);
|
||||
|
||||
/* we must run modal until the bake job is done, otherwise the undo push
|
||||
* happens before the job ends, which can lead to race conditions between
|
||||
* the baking and file writing code */
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
static int ptcache_bake_modal(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
|
||||
{
|
||||
Scene *scene = (Scene *) op->customdata;
|
||||
|
||||
/* no running blender, remove handler and pass through */
|
||||
if (0 == WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_POINTCACHE)) {
|
||||
return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
|
||||
}
|
||||
|
||||
return OPERATOR_PASS_THROUGH;
|
||||
}
|
||||
|
||||
static void ptcache_bake_cancel(bContext *C, wmOperator *op)
|
||||
{
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
Scene *scene = (Scene *) op->customdata;
|
||||
|
||||
/* kill on cancel, because job is using op->reports */
|
||||
WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_POINTCACHE);
|
||||
}
|
||||
|
||||
static int ptcache_free_bake_all_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
@ -236,7 +283,10 @@ void PTCACHE_OT_bake_all(wmOperatorType *ot)
|
||||
ot->idname = "PTCACHE_OT_bake_all";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = ptcache_bake_all_exec;
|
||||
ot->exec = ptcache_bake_exec;
|
||||
ot->invoke = ptcache_bake_invoke;
|
||||
ot->modal = ptcache_bake_modal;
|
||||
ot->cancel = ptcache_bake_cancel;
|
||||
ot->poll = ptcache_bake_all_poll;
|
||||
|
||||
/* flags */
|
||||
@ -259,53 +309,6 @@ void PTCACHE_OT_free_bake_all(wmOperatorType *ot)
|
||||
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);
|
||||
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->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_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
|
||||
@ -339,6 +342,9 @@ void PTCACHE_OT_bake(wmOperatorType *ot)
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = ptcache_bake_exec;
|
||||
ot->invoke = ptcache_bake_invoke;
|
||||
ot->modal = ptcache_bake_modal;
|
||||
ot->cancel = ptcache_bake_cancel;
|
||||
ot->poll = ptcache_poll;
|
||||
|
||||
/* flags */
|
||||
@ -441,7 +447,7 @@ void PTCACHE_OT_add(wmOperatorType *ot)
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = ptcache_add_new_exec;
|
||||
ot->poll = ptcache_poll; // ptcache_bake_all_poll;
|
||||
ot->poll = ptcache_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
|
@ -3074,15 +3074,13 @@ static void update_physics_cache(Render *re, Scene *scene, int UNUSED(anim_init)
|
||||
{
|
||||
PTCacheBaker baker;
|
||||
|
||||
memset(&baker, 0, sizeof(baker));
|
||||
baker.main = re->main;
|
||||
baker.scene = scene;
|
||||
baker.pid = NULL;
|
||||
baker.bake = 0;
|
||||
baker.render = 1;
|
||||
baker.anim_init = 1;
|
||||
baker.quick_step = 1;
|
||||
baker.update_progress = NULL;
|
||||
baker.bake_job = NULL;
|
||||
|
||||
BKE_ptcache_bake(&baker);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user