Faster Motion Path calculations using Depsgraph Filtering

This commit makes the motion path calculations use the
new Depsgraph Filtering API to obtain a more streamlined
copy of the full scene dependency graph, allowing for
faster calculations (as less data needs to be evaluated
for each frame being baked).

For example, in 01_020_A.anim.blend from the Spring production
files, the time needed to calculate paths on several bones
on Autumn went from  39.84 seconds (!) down to 9.90 seconds!

Currently, this works by just replacing the depsgraph instance
passed to the motion path calculation function. This filtered
instance contains just the ID's needed to evaluate the graph
to evaluate a specified target (i.e. the Object owning the pose).

Notes:
* By default, the filtering is not performed unless debug mode 555
  is activated. Having a debug switch here allows comparing
  performance and disabling it should thing it start crashing.

* It is necessary to pass in the original Scene instance (not the
  COW one owned by the filtered depsgraph), otherwise changing the
  current frame had no effect, due to the COW flushing from original
  Scene to the new Scene overwriting the CFRA changes we make.

* The code here still needs cleaning up to debugging instrumentation, etc.
  and also to optimise further (e.g. caching the filtered depsgraph
  for faster updates when animating on existing paths, or fine-tuning
  the exact set of nodes needed).  I'm just committing this first,
  since this was the quickly hacked-together test code I've been using
  to check that this is all working.

* Further improvements could also be made to the time needed to
  build the full graph instance (about 3.3 sec), by allowing partial
  builds (e.g. by making a filtering proxy/wrapper around existing builders)
This commit is contained in:
Joshua Leung 2018-08-23 15:41:08 +12:00
parent 0e44cf5d78
commit bd801e7a68
2 changed files with 31 additions and 2 deletions

View File

@ -466,7 +466,10 @@ static void motionpaths_calc_bake_targets(ListBase *targets, int cframe)
}
/* calculate path over requested range */
printf("Calculating Paths over Frame Range:\n");
for (CFRA = sfra; CFRA <= efra; CFRA++) {
printf(" Frame %d\n", CFRA);
/* update relevant data for new frame */
motionpaths_calc_update_scene(bmain, depsgraph);
@ -475,9 +478,8 @@ static void motionpaths_calc_bake_targets(ListBase *targets, int cframe)
}
/* reset original environment */
// XXX: Soon to be obsolete
CFRA = cfra;
motionpaths_calc_update_scene(bmain, depsgraph);
motionpaths_calc_update_scene(bmain, depsgraph); // XXX: Soon to be obsolete
/* clear recalc flags from targets */
for (mpt = targets->first; mpt; mpt = mpt->next) {

View File

@ -46,12 +46,15 @@
#include "BKE_armature.h"
#include "BKE_context.h"
#include "BKE_deform.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_report.h"
#include "BKE_layer.h"
#include "BKE_scene.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
#include "RNA_access.h"
#include "RNA_define.h"
@ -196,12 +199,36 @@ void ED_pose_recalculate_paths(bContext *C, Scene *scene, Object *ob)
Depsgraph *depsgraph = CTX_data_depsgraph(C);
ListBase targets = {NULL, NULL};
/* Override depsgraph with a filtered, simpler copy */
if (G.debug_value == 555) {
TIMEIT_START(filter_pose_depsgraph);
DEG_FilterQuery query = {0};
DEG_FilterTarget *dft_ob = MEM_callocN(sizeof(DEG_FilterTarget), "DEG_FilterTarget");
dft_ob->id = &ob->id;
BLI_addtail(&query.targets, dft_ob);
depsgraph = DEG_graph_filter(depsgraph, bmain, &query);
MEM_freeN(dft_ob);
TIMEIT_END(filter_pose_depsgraph);
TIMEIT_START(filter_pose_update);
BKE_scene_graph_update_tagged(depsgraph, bmain);
TIMEIT_END(filter_pose_update);
//scene = DEG_get_evaluated_scene(depsgraph); /* NOTE: Don't pass in evaluated scene, or else COW will keep overwriting the cfra */
}
/* set flag to force recalc, then grab the relevant bones to target */
ob->pose->avs.recalc |= ANIMVIZ_RECALC_PATHS;
animviz_get_object_motionpaths(ob, &targets);
/* recalculate paths, then free */
TIMEIT_START(pose_path_calc);
animviz_calc_motionpaths(depsgraph, bmain, scene, &targets);
TIMEIT_END(pose_path_calc);
BLI_freelistN(&targets);
/* tag armature object for copy on write - so paths will draw/redraw */