[Bf-blender-cvs] [81ce3801bf0] master: Animation: Refactor storage usage during fcurve modifier evaluation

Jacques Lucke noreply at git.blender.org
Wed Apr 17 18:16:00 CEST 2019


Commit: 81ce3801bf0a876b73b73817ca1a61b4e81b214d
Author: Jacques Lucke
Date:   Wed Apr 17 18:09:33 2019 +0200
Branches: master
https://developer.blender.org/rB81ce3801bf0a876b73b73817ca1a61b4e81b214d

Animation: Refactor storage usage during fcurve modifier evaluation

Previously, when a fcurve modifier used storage,
many heap allocations were done.
This caused major slowdowns as described in T63656.

Furthermore, the storage usage was a special case only
used by the Cycles modifier. This refactor makes
storage usage the "normal" case.
That reduces the overall complexity.

The storage is stack allocated now.

The framerate on the provided test scene went up from ~5 fps to ~16 fps.

Reviewers: angavrilov

Differential Revision: https://developer.blender.org/D4701

===================================================================

M	source/blender/blenkernel/BKE_fcurve.h
M	source/blender/blenkernel/intern/anim_sys.c
M	source/blender/blenkernel/intern/fcurve.c
M	source/blender/blenkernel/intern/fmodifier.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h
index 52a4d00b117..5e45faf1d0b 100644
--- a/source/blender/blenkernel/BKE_fcurve.h
+++ b/source/blender/blenkernel/BKE_fcurve.h
@@ -115,8 +115,6 @@ float evaluate_driver(struct PathResolvedRNA *anim_rna,
 
 /* ************** F-Curve Modifiers *************** */
 
-typedef struct GHash FModifierStackStorage;
-
 /* F-Curve Modifier Type-Info (fmi):
  *  This struct provides function pointers for runtime, so that functions can be
  *  written more generally (with fewer/no special exceptions for various modifiers).
@@ -136,6 +134,7 @@ typedef struct FModifierTypeInfo {
   short requires;      /* eFMI_Requirement_Flags */
   char name[64];       /* name of modifier in interface */
   char structName[64]; /* name of struct for SDNA */
+  uint storage_size;   /* size of buffer that can be reused between time and value evaluation */
 
   /* data management function pointers - special handling */
   /* free any data that is allocated separately (optional) */
@@ -149,27 +148,11 @@ typedef struct FModifierTypeInfo {
 
   /* evaluation */
   /* evaluate time that the modifier requires the F-Curve to be evaluated at */
-  float (*evaluate_modifier_time)(struct FCurve *fcu,
-                                  struct FModifier *fcm,
-                                  float cvalue,
-                                  float evaltime);
+  float (*evaluate_modifier_time)(
+      struct FCurve *fcu, struct FModifier *fcm, float cvalue, float evaltime, void *storage);
   /* evaluate the modifier for the given time and 'accumulated' value */
-  void (*evaluate_modifier)(struct FCurve *fcu,
-                            struct FModifier *fcm,
-                            float *cvalue,
-                            float evaltime);
-
-  /* Same as above but for modifiers which requires storage */
-  float (*evaluate_modifier_time_storage)(FModifierStackStorage *storage,
-                                          struct FCurve *fcu,
-                                          struct FModifier *fcm,
-                                          float cvalue,
-                                          float evaltime);
-  void (*evaluate_modifier_storage)(FModifierStackStorage *storage,
-                                    struct FCurve *fcu,
-                                    struct FModifier *fcm,
-                                    float *cvalue,
-                                    float evaltime);
+  void (*evaluate_modifier)(
+      struct FCurve *fcu, struct FModifier *fcm, float *cvalue, float evaltime, void *storage);
 } FModifierTypeInfo;
 
 /* Values which describe the behavior of a FModifier Type */
@@ -194,9 +177,6 @@ typedef enum eFMI_Requirement_Flags {
   FMI_REQUIRES_NOTHING = (1 << 1),
   /* refer to modifier instance */
   FMI_REQUIRES_RUNTIME_CHECK = (1 << 2),
-
-  /* Requires to store data shared between time and valua evaluation */
-  FMI_REQUIRES_STORAGE = (1 << 3),
 } eFMI_Requirement_Flags;
 
 /* Function Prototypes for FModifierTypeInfo's */
@@ -216,14 +196,19 @@ void set_active_fmodifier(ListBase *modifiers, struct FModifier *fcm);
 
 bool list_has_suitable_fmodifier(ListBase *modifiers, int mtype, short acttype);
 
-FModifierStackStorage *evaluate_fmodifiers_storage_new(ListBase *modifiers);
-void evaluate_fmodifiers_storage_free(FModifierStackStorage *storage);
-float evaluate_time_fmodifiers(FModifierStackStorage *storage,
+typedef struct FModifiersStackStorage {
+  uint modifier_count;
+  uint size_per_modifier;
+  void *buffer;
+} FModifiersStackStorage;
+
+uint evaluate_fmodifiers_storage_size_per_modifier(ListBase *modifiers);
+float evaluate_time_fmodifiers(FModifiersStackStorage *storage,
                                ListBase *modifiers,
                                struct FCurve *fcu,
                                float cvalue,
                                float evaltime);
-void evaluate_value_fmodifiers(FModifierStackStorage *storage,
+void evaluate_value_fmodifiers(FModifiersStackStorage *storage,
                                ListBase *modifiers,
                                struct FCurve *fcu,
                                float *cvalue,
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 75244a8ba8a..de92077b052 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -2965,7 +2965,6 @@ static void nlastrip_evaluate_actionclip(PointerRNA *ptr,
                                          NlaEvalStrip *nes,
                                          NlaEvalSnapshot *snapshot)
 {
-  FModifierStackStorage *storage;
   ListBase tmp_modifiers = {NULL, NULL};
   NlaStrip *strip = nes->strip;
   FCurve *fcu;
@@ -2986,8 +2985,12 @@ static void nlastrip_evaluate_actionclip(PointerRNA *ptr,
   nlaeval_fmodifiers_join_stacks(&tmp_modifiers, &strip->modifiers, modifiers);
 
   /* evaluate strip's modifiers which modify time to evaluate the base curves at */
-  storage = evaluate_fmodifiers_storage_new(&tmp_modifiers);
-  evaltime = evaluate_time_fmodifiers(storage, &tmp_modifiers, NULL, 0.0f, strip->strip_time);
+  FModifiersStackStorage storage;
+  storage.modifier_count = BLI_listbase_count(&tmp_modifiers);
+  storage.size_per_modifier = evaluate_fmodifiers_storage_size_per_modifier(&tmp_modifiers);
+  storage.buffer = alloca(storage.modifier_count * storage.size_per_modifier);
+
+  evaltime = evaluate_time_fmodifiers(&storage, &tmp_modifiers, NULL, 0.0f, strip->strip_time);
 
   NlaBlendData blend = {
       .snapshot = snapshot,
@@ -3013,7 +3016,7 @@ static void nlastrip_evaluate_actionclip(PointerRNA *ptr,
     /* apply strip's F-Curve Modifiers on this value
      * NOTE: we apply the strip's original evaluation time not the modified one (as per standard F-Curve eval)
      */
-    evaluate_value_fmodifiers(storage, &tmp_modifiers, fcu, &value, strip->strip_time);
+    evaluate_value_fmodifiers(&storage, &tmp_modifiers, fcu, &value, strip->strip_time);
 
     /* get an NLA evaluation channel to work with, and accumulate the evaluated value with the value(s)
      * stored in this channel if it has been used already
@@ -3025,9 +3028,6 @@ static void nlastrip_evaluate_actionclip(PointerRNA *ptr,
 
   nlaeval_blend_flush(&blend);
 
-  /* free temporary storage */
-  evaluate_fmodifiers_storage_free(storage);
-
   /* unlink this strip's modifiers from the parent's modifiers again */
   nlaeval_fmodifiers_split_stacks(&strip->modifiers, modifiers);
 }
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index 4a2a610918c..f93a5e65845 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -2851,12 +2851,15 @@ static float fcurve_eval_samples(FCurve *fcu, FPoint *fpts, float evaltime)
  */
 static float evaluate_fcurve_ex(FCurve *fcu, float evaltime, float cvalue)
 {
-  FModifierStackStorage *storage;
   float devaltime;
 
   /* evaluate modifiers which modify time to evaluate the base curve at */
-  storage = evaluate_fmodifiers_storage_new(&fcu->modifiers);
-  devaltime = evaluate_time_fmodifiers(storage, &fcu->modifiers, fcu, cvalue, evaltime);
+  FModifiersStackStorage storage;
+  storage.modifier_count = BLI_listbase_count(&fcu->modifiers);
+  storage.size_per_modifier = evaluate_fmodifiers_storage_size_per_modifier(&fcu->modifiers);
+  storage.buffer = alloca(storage.modifier_count * storage.size_per_modifier);
+
+  devaltime = evaluate_time_fmodifiers(&storage, &fcu->modifiers, fcu, cvalue, evaltime);
 
   /* evaluate curve-data
    * - 'devaltime' instead of 'evaltime', as this is the time that the last time-modifying
@@ -2868,9 +2871,7 @@ static float evaluate_fcurve_ex(FCurve *fcu, float evaltime, float cvalue)
     cvalue = fcurve_eval_samples(fcu, fcu->fpt, devaltime);
 
   /* evaluate modifiers */
-  evaluate_value_fmodifiers(storage, &fcu->modifiers, fcu, &cvalue, devaltime);
-
-  evaluate_fmodifiers_storage_free(storage);
+  evaluate_value_fmodifiers(&storage, &fcu->modifiers, fcu, &cvalue, devaltime);
 
   /* if curve can only have integral values, perform truncation (i.e. drop the decimal part)
    * here so that the curve can be sampled correctly
diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c
index 3cecfb8aa17..3cb941e1f93 100644
--- a/source/blender/blenkernel/intern/fmodifier.c
+++ b/source/blender/blenkernel/intern/fmodifier.c
@@ -48,11 +48,6 @@ static CLG_LogRef LOG = {"bke.fmodifier"};
 
 /* ******************************** F-Modifiers ********************************* */
 
-/* Forward declarations. */
-void fmodifiers_storage_put(FModifierStackStorage *storage, FModifier *fcm, void *data);
-void fmodifiers_storage_remove(FModifierStackStorage *storage, FModifier *fcm);
-void *fmodifiers_storage_get(FModifierStackStorage *storage, FModifier *fcm);
-
 /* Info ------------------------------- */
 
 /* F-Modifiers are modifiers which operate on F-Curves. However, they can also be defined
@@ -75,7 +70,7 @@ void *fmodifiers_storage_get(FModifierStackStorage *storage, FModifier *fcm);
  *   for such cases, just use NULL
  * - these should be defined after all the functions have been defined, so that
  *   forward-definitions/prototypes don't need to be used!
- * - keep this copy #if-def'd so that future constraints can get based off this
+ * - keep this copy #if-def'd so that future modifier can get based off this
  */
 #if 0
 static FModifierTypeInfo FMI_MODNAME = {
@@ -85,6 +80,7 @@ static FModifierTypeInfo FMI_MODNAME = {
     FMI_REQUIRES_SOME_REQUIREMENT, /* requirements */
     "Modifier Name",               /* name */
     "FMod_ModName",                /* struct name */
+    0,                             /* storage size */
     fcm_modname_free,              /* free data */
     fcm_modname_relink,            /* relink data */
     fcm_modname_copy,              /* copy data */
@@ -92,8 +88,6 @@ static FModifierTypeInfo FMI_MODNAME = {
     fcm_modname_verify,            /* verify */
     fcm_modname_time,              /* evaluate time */
     fcm_modname_ev

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list