diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index ce2f9e878f8..4641cc47b14 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -612,3 +612,25 @@ void BKE_modifier_blend_read_lib(struct BlendLibReader *reader, struct Object *o #ifdef __cplusplus } #endif + +#ifdef __cplusplus + +namespace blender::bke { + +/** + * A convenience class that can be used to set `ModifierData::execution_time` based on the lifetime + * of this class. + */ +class ScopedModifierTimer { + private: + ModifierData &md_; + double start_time_; + + public: + ScopedModifierTimer(ModifierData &md); + ~ScopedModifierTimer(); +}; + +} // namespace blender::bke + +#endif diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc index 565009fe08f..c3d535a3e9d 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.cc +++ b/source/blender/blenkernel/intern/DerivedMesh.cc @@ -760,6 +760,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, } if (mti->type == eModifierTypeType_OnlyDeform && !sculpt_dyntopo) { + blender::bke::ScopedModifierTimer modifier_timer{*md}; if (!deformed_verts) { deformed_verts = BKE_mesh_vert_coords_alloc(mesh_input, &num_deformed_verts); } @@ -846,6 +847,8 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, continue; } + blender::bke::ScopedModifierTimer modifier_timer{*md}; + /* Add orco mesh as layer if needed by this modifier. */ if (mesh_final && mesh_orco && mti->requiredDataMask) { CustomData_MeshMasks mask = {0}; @@ -1323,6 +1326,8 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, continue; } + blender::bke::ScopedModifierTimer modifier_timer{*md}; + /* Add an orco mesh as layer if needed by this modifier. */ if (mesh_final && mesh_orco && mti->requiredDataMask) { CustomData_MeshMasks mask = {0}; diff --git a/source/blender/blenkernel/intern/curves.cc b/source/blender/blenkernel/intern/curves.cc index 1519c0addd2..3003d014b4f 100644 --- a/source/blender/blenkernel/intern/curves.cc +++ b/source/blender/blenkernel/intern/curves.cc @@ -314,6 +314,8 @@ static void curves_evaluate_modifiers(struct Depsgraph *depsgraph, continue; } + blender::bke::ScopedModifierTimer modifier_timer{*md}; + if (mti->modifyGeometrySet != nullptr) { mti->modifyGeometrySet(md, &mectx, &geometry_set); } diff --git a/source/blender/blenkernel/intern/displist.cc b/source/blender/blenkernel/intern/displist.cc index 8cdcb85a033..e51a2c3d85c 100644 --- a/source/blender/blenkernel/intern/displist.cc +++ b/source/blender/blenkernel/intern/displist.cc @@ -613,6 +613,8 @@ void BKE_curve_calc_modifiers_pre(Depsgraph *depsgraph, continue; } + blender::bke::ScopedModifierTimer modifier_timer{*md}; + if (!deformedVerts) { deformedVerts = BKE_curve_nurbs_vert_coords_alloc(source_nurb, &numVerts); } @@ -733,6 +735,8 @@ static GeometrySet curve_calc_modifiers_post(Depsgraph *depsgraph, continue; } + blender::bke::ScopedModifierTimer modifier_timer{*md}; + if (!geometry_set.has_mesh()) { geometry_set.replace_mesh(BKE_mesh_new_nomain(0, 0, 0, 0, 0)); } diff --git a/source/blender/blenkernel/intern/modifier.cc b/source/blender/blenkernel/intern/modifier.cc index 508c1fe2331..d0ccdedc136 100644 --- a/source/blender/blenkernel/intern/modifier.cc +++ b/source/blender/blenkernel/intern/modifier.cc @@ -11,6 +11,7 @@ #define DNA_DEPRECATED_ALLOW #include +#include #include #include #include @@ -1514,3 +1515,28 @@ void BKE_modifier_blend_read_lib(BlendLibReader *reader, Object *ob) } } } + +namespace blender::bke { + +using Clock = std::chrono::high_resolution_clock; + +static double get_current_time_in_seconds() +{ + return std::chrono::duration( + Clock::now().time_since_epoch()) + .count(); +} + +ScopedModifierTimer::ScopedModifierTimer(ModifierData &md) : md_(md) +{ + start_time_ = get_current_time_in_seconds(); +} + +ScopedModifierTimer::~ScopedModifierTimer() +{ + const double end_time = get_current_time_in_seconds(); + const double duration = end_time - start_time_; + md_.execution_time = duration; +} + +} // namespace blender::bke diff --git a/source/blender/blenkernel/intern/pointcloud.cc b/source/blender/blenkernel/intern/pointcloud.cc index aa3c2593f34..2fee1f4f4d3 100644 --- a/source/blender/blenkernel/intern/pointcloud.cc +++ b/source/blender/blenkernel/intern/pointcloud.cc @@ -380,6 +380,8 @@ static void pointcloud_evaluate_modifiers(struct Depsgraph *depsgraph, continue; } + blender::bke::ScopedModifierTimer modifier_timer{*md}; + if (mti->modifyGeometrySet) { mti->modifyGeometrySet(md, &mectx, &geometry_set); } diff --git a/source/blender/blenkernel/intern/volume.cc b/source/blender/blenkernel/intern/volume.cc index bad2e844cc0..b2f62dd0d9d 100644 --- a/source/blender/blenkernel/intern/volume.cc +++ b/source/blender/blenkernel/intern/volume.cc @@ -1108,6 +1108,8 @@ static void volume_evaluate_modifiers(struct Depsgraph *depsgraph, continue; } + blender::bke::ScopedModifierTimer modifier_timer{*md}; + if (mti->modifyGeometrySet) { mti->modifyGeometrySet(md, &mectx, &geometry_set); } diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index fe35fea77ed..7af83f8f888 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -105,7 +105,8 @@ typedef struct ModifierData { struct ModifierData *next, *prev; int type, mode; - char _pad0[4]; + /** Time in seconds that the modifier took to evaluate. This is only set on evaluated objects. */ + float execution_time; short flag; /** An "expand" bit for each of the modifier's (sub)panels (#uiPanelDataExpansion). */ short ui_expand_flag; diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index aa7b1ae01dc..b86e202a791 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -7355,6 +7355,14 @@ void RNA_def_modifier(BlenderRNA *brna) RNA_def_property_ui_icon(prop, ICON_SURFACE_DATA, 0); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "execution_time", PROP_FLOAT, PROP_TIME_ABSOLUTE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text( + prop, + "Execution Time", + "Time in seconds that the modifier took to evaluate. This is only set on evaluated objects. " + "If multiple modifiers run in parallel, execution time is not a reliable metric"); + /* types */ rna_def_modifier_subsurf(brna); rna_def_modifier_lattice(brna);