Depsgraph: Fix missing point cache reset when physics changes

Among all the lines moved around, the general idea is quite simple.
Actually, there are two ideas implemented there.

First one, is when object itself is tagged for update, we tag its
point cache component for evaluation, which makes it so point cache
is properly reset. We do it implicitly because otherwise we'll need
to go everywhere and add explicit tag in almost all the properties.

Second thing is, we link all collider and force fields to a point
cache component using special type of link. This type of link only
allows flush if change is caused by a user update. This way reset
does not happen when change is caused due to animation, but will
properly happen when user causes indirect change to the objects
which are part of physics simulation.
This commit is contained in:
Sergey Sharybin 2018-11-14 11:24:54 +01:00
parent 1d8db50538
commit d3c08b1aa6
26 changed files with 317 additions and 199 deletions

@ -245,7 +245,7 @@ void BKE_object_eval_uber_data(
struct Scene *scene, struct Scene *scene,
struct Object *ob); struct Object *ob);
void BKE_object_eval_cloth( void BKE_object_eval_ptcache_reset(
struct Depsgraph *depsgraph, struct Depsgraph *depsgraph,
struct Scene *scene, struct Scene *scene,
struct Object *object); struct Object *object);

@ -343,9 +343,9 @@ void BKE_object_eval_uber_data(Depsgraph *depsgraph,
BKE_object_batch_cache_dirty_tag(ob); BKE_object_batch_cache_dirty_tag(ob);
} }
void BKE_object_eval_cloth(Depsgraph *depsgraph, void BKE_object_eval_ptcache_reset(Depsgraph *depsgraph,
Scene *scene, Scene *scene,
Object *object) Object *object)
{ {
DEG_debug_print_eval(depsgraph, __func__, object->id.name, object); DEG_debug_print_eval(depsgraph, __func__, object->id.name, object);
BKE_ptcache_object_reset(scene, object, PTCACHE_RESET_DEPSGRAPH); BKE_ptcache_object_reset(scene, object, PTCACHE_RESET_DEPSGRAPH);

@ -147,11 +147,12 @@ typedef enum eDepsgraph_Tag {
/* Tag shading components for update. /* Tag shading components for update.
* Only parameters of material changed). * Only parameters of material changed).
*/ */
DEG_TAG_SHADING_UPDATE = (1 << 9), DEG_TAG_SHADING_UPDATE = (1 << 9),
DEG_TAG_SELECT_UPDATE = (1 << 10), DEG_TAG_SELECT_UPDATE = (1 << 10),
DEG_TAG_BASE_FLAGS_UPDATE = (1 << 11), DEG_TAG_BASE_FLAGS_UPDATE = (1 << 11),
DEG_TAG_POINT_CACHE_UPDATE = (1 << 12),
/* Only inform editors about the change. Don't modify datablock itself. */ /* Only inform editors about the change. Don't modify datablock itself. */
DEG_TAG_EDITORS_UPDATE = (1 << 12), DEG_TAG_EDITORS_UPDATE = (1 << 13),
} eDepsgraph_Tag; } eDepsgraph_Tag;
const char *DEG_update_tag_as_string(eDepsgraph_Tag flag); const char *DEG_update_tag_as_string(eDepsgraph_Tag flag);

@ -131,15 +131,15 @@ typedef enum eDepsObjectComponentType {
DEG_OB_COMP_CACHE, DEG_OB_COMP_CACHE,
} eDepsObjectComponentType; } eDepsObjectComponentType;
void DEG_add_scene_relation(struct DepsNodeHandle *node, void DEG_add_scene_relation(struct DepsNodeHandle *node_handle,
struct Scene *scene, struct Scene *scene,
eDepsSceneComponentType component, eDepsSceneComponentType component,
const char *description); const char *description);
void DEG_add_object_relation(struct DepsNodeHandle *node, void DEG_add_object_relation(struct DepsNodeHandle *node_handle,
struct Object *object, struct Object *object,
eDepsObjectComponentType component, eDepsObjectComponentType component,
const char *description); const char *description);
void DEG_add_object_relation_with_customdata(struct DepsNodeHandle *node, void DEG_add_object_relation_with_customdata(struct DepsNodeHandle *node_handle,
struct Object *object, struct Object *object,
eDepsObjectComponentType component, eDepsObjectComponentType component,
uint64_t customdata_mask, uint64_t customdata_mask,
@ -154,9 +154,18 @@ void DEG_add_object_cache_relation(struct DepsNodeHandle *handle,
eDepsObjectComponentType component, eDepsObjectComponentType component,
const char *description); const char *description);
/* Adds relations from the given component of a given object to the given node
* handle AND the component to the point cache component of the node's ID.
*/
void DEG_add_object_pointcache_relation(struct DepsNodeHandle *node_handle,
struct Object *object,
eDepsObjectComponentType component,
const char *description);
void DEG_add_special_eval_flag(struct DepsNodeHandle *handle, struct ID *id, uint32_t flag); void DEG_add_special_eval_flag(struct DepsNodeHandle *handle, struct ID *id, uint32_t flag);
struct Depsgraph *DEG_get_graph_from_handle(struct DepsNodeHandle *handle); struct ID *DEG_get_id_from_handle(struct DepsNodeHandle *node_handle);
struct Depsgraph *DEG_get_graph_from_handle(struct DepsNodeHandle *node_handle);
/* ************************************************ */ /* ************************************************ */

@ -399,7 +399,10 @@ void DepsgraphNodeBuilder::end_build()
if (op_node == NULL) { if (op_node == NULL) {
continue; continue;
} }
op_node->tag_update(graph_); /* Since the tag is coming from a saved copy of entry tags, this means
* that originally node was explicitly tagged for user update.
*/
op_node->tag_update(graph_, DEG_UPDATE_SOURCE_USER_EDIT);
} }
} }
@ -818,6 +821,22 @@ void DepsgraphNodeBuilder::build_object_constraints(Object *object)
DEG_OPCODE_TRANSFORM_CONSTRAINTS); DEG_OPCODE_TRANSFORM_CONSTRAINTS);
} }
void DepsgraphNodeBuilder::build_object_pointcache(Object *object)
{
if (!BKE_ptcache_object_has(scene_, object, 0)) {
return;
}
Scene *scene_cow = get_cow_datablock(scene_);
Object *object_cow = get_cow_datablock(object);
add_operation_node(&object->id,
DEG_NODE_TYPE_POINT_CACHE,
function_bind(BKE_object_eval_ptcache_reset,
_1,
scene_cow,
object_cow),
DEG_OPCODE_POINT_CACHE_RESET);
}
/** /**
* Build graph nodes for AnimData block * Build graph nodes for AnimData block
* \param id: ID-Block which hosts the AnimData * \param id: ID-Block which hosts the AnimData
@ -1123,15 +1142,6 @@ void DepsgraphNodeBuilder::build_particles(Object *object,
break; break;
} }
} }
/* TODO(sergey): Do we need a point cache operations here? */
add_operation_node(&object->id,
DEG_NODE_TYPE_CACHE,
function_bind(BKE_ptcache_object_reset,
scene_cow,
ob_cow,
PTCACHE_RESET_DEPSGRAPH),
DEG_OPCODE_POINT_CACHE_RESET);
} }
void DepsgraphNodeBuilder::build_particle_settings(ParticleSettings *part) { void DepsgraphNodeBuilder::build_particle_settings(ParticleSettings *part) {
@ -1147,19 +1157,6 @@ void DepsgraphNodeBuilder::build_particle_settings(ParticleSettings *part) {
DEG_OPCODE_PARTICLE_SETTINGS_EVAL); DEG_OPCODE_PARTICLE_SETTINGS_EVAL);
} }
void DepsgraphNodeBuilder::build_cloth(Object *object)
{
Scene *scene_cow = get_cow_datablock(scene_);
Object *object_cow = get_cow_datablock(object);
add_operation_node(&object->id,
DEG_NODE_TYPE_CACHE,
function_bind(BKE_object_eval_cloth,
_1,
scene_cow,
object_cow),
DEG_OPCODE_GEOMETRY_CLOTH_MODIFIER);
}
/* Shapekeys */ /* Shapekeys */
void DepsgraphNodeBuilder::build_shapekeys(Key *key) void DepsgraphNodeBuilder::build_shapekeys(Key *key)
{ {
@ -1204,13 +1201,6 @@ void DepsgraphNodeBuilder::build_object_data_geometry(
DEG_OPCODE_PLACEHOLDER, DEG_OPCODE_PLACEHOLDER,
"Eval Init"); "Eval Init");
op_node->set_as_entry(); op_node->set_as_entry();
// TODO: "Done" operation
/* Cloth modifier. */
LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
if (md->type == eModifierType_Cloth) {
build_cloth(object);
}
}
/* Materials. */ /* Materials. */
if (object->totcol != 0) { if (object->totcol != 0) {
if (object->type == OB_MESH) { if (object->type == OB_MESH) {
@ -1221,7 +1211,6 @@ void DepsgraphNodeBuilder::build_object_data_geometry(
object_cow), object_cow),
DEG_OPCODE_SHADING); DEG_OPCODE_SHADING);
} }
for (int a = 1; a <= object->totcol; a++) { for (int a = 1; a <= object->totcol; a++) {
Material *ma = give_current_material(object, a); Material *ma = give_current_material(object, a);
if (ma != NULL) { if (ma != NULL) {
@ -1229,10 +1218,9 @@ void DepsgraphNodeBuilder::build_object_data_geometry(
} }
} }
} }
/* Geometry collision. */ /* Point caches. */
if (ELEM(object->type, OB_MESH, OB_CURVE, OB_LATTICE)) { build_object_pointcache(object);
// add geometry collider relations /* Geometry. */
}
build_object_data_geometry_datablock((ID *)object->data, is_object_visible); build_object_data_geometry_datablock((ID *)object->data, is_object_visible);
} }

@ -183,6 +183,7 @@ struct DepsgraphNodeBuilder {
void build_object_data_speaker(Object *object); void build_object_data_speaker(Object *object);
void build_object_transform(Object *object); void build_object_transform(Object *object);
void build_object_constraints(Object *object); void build_object_constraints(Object *object);
void build_object_pointcache(Object *object);
void build_pose_constraints(Object *object, void build_pose_constraints(Object *object,
bPoseChannel *pchan, bPoseChannel *pchan,
int pchan_index, int pchan_index,
@ -190,7 +191,6 @@ struct DepsgraphNodeBuilder {
void build_rigidbody(Scene *scene); void build_rigidbody(Scene *scene);
void build_particles(Object *object, bool is_object_visible); void build_particles(Object *object, bool is_object_visible);
void build_particle_settings(ParticleSettings *part); void build_particle_settings(ParticleSettings *part);
void build_cloth(Object *object);
void build_animdata(ID *id); void build_animdata(ID *id);
void build_animdata_nlastrip_targets(ListBase *strips); void build_animdata_nlastrip_targets(ListBase *strips);
void build_action(bAction *action); void build_action(bAction *action);

@ -87,6 +87,7 @@ extern "C" {
#include "BKE_node.h" #include "BKE_node.h"
#include "BKE_object.h" #include "BKE_object.h"
#include "BKE_particle.h" #include "BKE_particle.h"
#include "BKE_pointcache.h"
#include "BKE_rigidbody.h" #include "BKE_rigidbody.h"
#include "BKE_shader_fx.h" #include "BKE_shader_fx.h"
#include "BKE_shrinkwrap.h" #include "BKE_shrinkwrap.h"
@ -184,9 +185,13 @@ static bool check_id_has_anim_component(ID *id)
(!BLI_listbase_is_empty(&adt->nla_tracks)); (!BLI_listbase_is_empty(&adt->nla_tracks));
} }
static eDepsOperation_Code bone_target_opcode(ID *target, const char *subtarget, ID *id, const char *component_subdata, RootPChanMap *root_map) static eDepsOperation_Code bone_target_opcode(ID *target,
const char *subtarget,
ID *id,
const char *component_subdata,
RootPChanMap *root_map)
{ {
/* same armature */ /* Same armature. */
if (target == id) { if (target == id) {
/* Using "done" here breaks in-chain deps, while using /* Using "done" here breaks in-chain deps, while using
* "ready" here breaks most production rigs instead. * "ready" here breaks most production rigs instead.
@ -197,7 +202,6 @@ static eDepsOperation_Code bone_target_opcode(ID *target, const char *subtarget,
return DEG_OPCODE_BONE_READY; return DEG_OPCODE_BONE_READY;
} }
} }
return DEG_OPCODE_BONE_DONE; return DEG_OPCODE_BONE_DONE;
} }
@ -642,6 +646,8 @@ void DepsgraphRelationBuilder::build_object(Base *base, Object *object)
if (object->dup_group != NULL) { if (object->dup_group != NULL) {
build_collection(object, object->dup_group); build_collection(object, object->dup_group);
} }
/* Point caches. */
build_object_pointcache(object);
} }
void DepsgraphRelationBuilder::build_object_flags(Base *base, Object *object) void DepsgraphRelationBuilder::build_object_flags(Base *base, Object *object)
@ -846,11 +852,47 @@ void DepsgraphRelationBuilder::build_object_parent(Object *object)
break; break;
} }
} }
}
/* exception case: parent is duplivert */ void DepsgraphRelationBuilder::build_object_pointcache(Object *object)
if ((object->type == OB_MBALL) && (object->parent->transflag & OB_DUPLIVERTS)) { {
//dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_OB, "Duplivert"); ComponentKey point_cache_key(&object->id, DEG_NODE_TYPE_POINT_CACHE);
/* Different point caches are affecting different aspects of life of the
* object. We keep track of those aspects and avoid duplicate relations. */
enum {
FLAG_TRANSFORM = (1 << 0),
FLAG_GEOMETRY = (1 << 1),
FLAG_ALL = (FLAG_TRANSFORM | FLAG_GEOMETRY),
};
ListBase ptcache_id_list;
BKE_ptcache_ids_from_object(&ptcache_id_list, object, scene_, 0);
int handled_components = 0;
LISTBASE_FOREACH (PTCacheID *, ptcache_id, &ptcache_id_list) {
/* Check which components needs the point cache. */
int flag;
if (ptcache_id->type == PTCACHE_TYPE_RIGIDBODY) {
flag = FLAG_TRANSFORM;
ComponentKey transform_key(&object->id,
DEG_NODE_TYPE_TRANSFORM);
add_relation(point_cache_key,
transform_key,
"Point Cache -> Rigid Body");
}
else {
flag = FLAG_GEOMETRY;
ComponentKey geometry_key(&object->id,
DEG_NODE_TYPE_GEOMETRY);
add_relation(point_cache_key,
geometry_key,
"Point Cache -> Geometry");
}
/* Tag that we did handle that component. */
handled_components |= flag;
if (handled_components == FLAG_ALL) {
break;
}
} }
BLI_freelistN(&ptcache_id_list);
} }
void DepsgraphRelationBuilder::build_constraints(ID *id, void DepsgraphRelationBuilder::build_constraints(ID *id,
@ -1744,12 +1786,6 @@ void DepsgraphRelationBuilder::build_particles(Object *object)
*/ */
ComponentKey transform_key(&object->id, DEG_NODE_TYPE_TRANSFORM); ComponentKey transform_key(&object->id, DEG_NODE_TYPE_TRANSFORM);
add_relation(transform_key, obdata_ubereval_key, "Partcile Eval"); add_relation(transform_key, obdata_ubereval_key, "Partcile Eval");
OperationKey point_cache_reset_key(&object->id,
DEG_NODE_TYPE_CACHE,
DEG_OPCODE_POINT_CACHE_RESET);
add_relation(transform_key, point_cache_reset_key, "Object Transform -> Point Cache Reset");
add_relation(point_cache_reset_key, obdata_ubereval_key, "Point Cache Reset -> UberEval");
} }
void DepsgraphRelationBuilder::build_particle_settings(ParticleSettings *part) void DepsgraphRelationBuilder::build_particle_settings(ParticleSettings *part)
@ -1783,19 +1819,6 @@ void DepsgraphRelationBuilder::build_particles_visualization_object(
} }
} }
void DepsgraphRelationBuilder::build_cloth(Object *object,
ModifierData * /*md*/)
{
OperationKey cache_key(&object->id,
DEG_NODE_TYPE_CACHE,
DEG_OPCODE_GEOMETRY_CLOTH_MODIFIER);
/* Cache component affects on modifier. */
OperationKey modifier_key(&object->id,
DEG_NODE_TYPE_GEOMETRY,
DEG_OPCODE_GEOMETRY_UBEREVAL);
add_relation(cache_key, modifier_key, "Cloth Cache -> Cloth");
}
/* Shapekeys */ /* Shapekeys */
void DepsgraphRelationBuilder::build_shapekeys(Key *key) void DepsgraphRelationBuilder::build_shapekeys(Key *key)
{ {
@ -1869,9 +1892,6 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object)
TimeSourceKey time_src_key; TimeSourceKey time_src_key;
add_relation(time_src_key, obdata_ubereval_key, "Time Source"); add_relation(time_src_key, obdata_ubereval_key, "Time Source");
} }
if (md->type == eModifierType_Cloth) {
build_cloth(object, md);
}
} }
} }
/* Grease Pencil Modifiers */ /* Grease Pencil Modifiers */

@ -217,6 +217,7 @@ struct DepsgraphRelationBuilder
void build_object_data_lightprobe(Object *object); void build_object_data_lightprobe(Object *object);
void build_object_data_speaker(Object *object); void build_object_data_speaker(Object *object);
void build_object_parent(Object *object); void build_object_parent(Object *object);
void build_object_pointcache(Object *object);
void build_constraints(ID *id, void build_constraints(ID *id,
eDepsNode_Type component_type, eDepsNode_Type component_type,
const char *component_subdata, const char *component_subdata,
@ -244,7 +245,6 @@ struct DepsgraphRelationBuilder
void build_particles_visualization_object(Object *object, void build_particles_visualization_object(Object *object,
ParticleSystem *psys, ParticleSystem *psys,
Object *draw_object); Object *draw_object);
void build_cloth(Object *object, ModifierData *md);
void build_ik_pose(Object *object, void build_ik_pose(Object *object,
bPoseChannel *pchan, bPoseChannel *pchan,
bConstraint *con, bConstraint *con,

@ -69,6 +69,7 @@ static const char *deg_debug_colors[] = {
"#33a02c", "#fb9a99", "#e31a1c", "#33a02c", "#fb9a99", "#e31a1c",
"#fdbf6f", "#ff7f00", "#cab2d6", "#fdbf6f", "#ff7f00", "#cab2d6",
"#6a3d9a", "#ffff99", "#b15928", "#6a3d9a", "#ffff99", "#b15928",
"#ff00ff",
}; };
#endif #endif
static const char *deg_debug_colors_light[] = { static const char *deg_debug_colors_light[] = {
@ -76,6 +77,7 @@ static const char *deg_debug_colors_light[] = {
"#fb8072", "#80b1d3", "#fdb462", "#fb8072", "#80b1d3", "#fdb462",
"#b3de69", "#fccde5", "#d9d9d9", "#b3de69", "#fccde5", "#d9d9d9",
"#bc80bd", "#ccebc5", "#ffed6f", "#bc80bd", "#ccebc5", "#ffed6f",
"#ff00ff",
}; };
#ifdef COLOR_SCHEME_NODE_TYPE #ifdef COLOR_SCHEME_NODE_TYPE
@ -84,18 +86,19 @@ static const int deg_debug_node_type_color_map[][2] = {
{DEG_NODE_TYPE_ID_REF, 1}, {DEG_NODE_TYPE_ID_REF, 1},
/* Outer Types */ /* Outer Types */
{DEG_NODE_TYPE_PARAMETERS, 2}, {DEG_NODE_TYPE_PARAMETERS, 2},
{DEG_NODE_TYPE_PROXY, 3}, {DEG_NODE_TYPE_PROXY, 3},
{DEG_NODE_TYPE_ANIMATION, 4}, {DEG_NODE_TYPE_ANIMATION, 4},
{DEG_NODE_TYPE_TRANSFORM, 5}, {DEG_NODE_TYPE_TRANSFORM, 5},
{DEG_NODE_TYPE_GEOMETRY, 6}, {DEG_NODE_TYPE_GEOMETRY, 6},
{DEG_NODE_TYPE_SEQUENCER, 7}, {DEG_NODE_TYPE_SEQUENCER, 7},
{DEG_NODE_TYPE_SHADING, 8}, {DEG_NODE_TYPE_SHADING, 8},
{DEG_NODE_TYPE_SHADING_PARAMETERS, 9}, {DEG_NODE_TYPE_SHADING_PARAMETERS, 9},
{DEG_NODE_TYPE_CACHE, 10}, {DEG_NODE_TYPE_CACHE, 10},
{DEG_NODE_TYPE_LAYER_COLLECTIONS, 11}, {DEG_NODE_TYPE_POINT_CACHE, 11},
{DEG_NODE_TYPE_COPY_ON_WRITE, 12}, {DEG_NODE_TYPE_LAYER_COLLECTIONS , 12},
{-1, 0} {DEG_NODE_TYPE_COPY_ON_WRITE, 13},
{-1, 0}
}; };
#endif #endif
@ -264,10 +267,14 @@ static void deg_debug_graphviz_relation_style(const DebugContext &ctx,
{ {
const char *style_default = "solid"; const char *style_default = "solid";
const char *style_no_flush = "dashed"; const char *style_no_flush = "dashed";
const char *style_flush_user_only = "dotted";
const char *style = style_default; const char *style = style_default;
if (rel->flag & DEPSREL_FLAG_NO_FLUSH) { if (rel->flag & DEPSREL_FLAG_NO_FLUSH) {
style = style_no_flush; style = style_no_flush;
} }
if (rel->flag & DEPSREL_FLAG_FLUSH_USER_EDIT_ONLY) {
style = style_flush_user_only;
}
deg_debug_fprintf(ctx, "%s", style); deg_debug_fprintf(ctx, "%s", style);
} }
@ -403,6 +410,7 @@ static void deg_debug_graphviz_node(const DebugContext &ctx,
case DEG_NODE_TYPE_SHADING: case DEG_NODE_TYPE_SHADING:
case DEG_NODE_TYPE_SHADING_PARAMETERS: case DEG_NODE_TYPE_SHADING_PARAMETERS:
case DEG_NODE_TYPE_CACHE: case DEG_NODE_TYPE_CACHE:
case DEG_NODE_TYPE_POINT_CACHE:
case DEG_NODE_TYPE_LAYER_COLLECTIONS: case DEG_NODE_TYPE_LAYER_COLLECTIONS:
case DEG_NODE_TYPE_EVAL_PARTICLES: case DEG_NODE_TYPE_EVAL_PARTICLES:
case DEG_NODE_TYPE_COPY_ON_WRITE: case DEG_NODE_TYPE_COPY_ON_WRITE:

@ -72,11 +72,13 @@ struct OperationDepsNode;
/* Settings/Tags on Relationship */ /* Settings/Tags on Relationship */
typedef enum eDepsRelation_Flag { typedef enum eDepsRelation_Flag {
/* "cyclic" link - when detecting cycles, this relationship was the one /* "cyclic" link - when detecting cycles, this relationship was the one
* which triggers a cyclic relationship to exist in the graph. * which triggers a cyclic relationship to exist in the graph. */
*/ DEPSREL_FLAG_CYCLIC = (1 << 0),
DEPSREL_FLAG_CYCLIC = (1 << 0),
/* Update flush will not go through this relation. */ /* Update flush will not go through this relation. */
DEPSREL_FLAG_NO_FLUSH = (1 << 1), DEPSREL_FLAG_NO_FLUSH = (1 << 1),
/* Only flush along the relation is update comes from a node which was
* affected by user input. */
DEPSREL_FLAG_FLUSH_USER_EDIT_ONLY = (1 << 2),
} eDepsRelation_Flag; } eDepsRelation_Flag;
/* B depends on A (A -> B) */ /* B depends on A (A -> B) */

@ -99,38 +99,38 @@ static DEG::eDepsNode_Type deg_build_object_component_type(
return DEG::DEG_NODE_TYPE_UNDEFINED; return DEG::DEG_NODE_TYPE_UNDEFINED;
} }
static DEG::DepsNodeHandle *get_handle(DepsNodeHandle *handle) static DEG::DepsNodeHandle *get_node_handle(DepsNodeHandle *node_handle)
{ {
return reinterpret_cast<DEG::DepsNodeHandle *>(handle); return reinterpret_cast<DEG::DepsNodeHandle *>(node_handle);
} }
void DEG_add_scene_relation(DepsNodeHandle *handle, void DEG_add_scene_relation(DepsNodeHandle *node_handle,
Scene *scene, Scene *scene,
eDepsSceneComponentType component, eDepsSceneComponentType component,
const char *description) const char *description)
{ {
DEG::eDepsNode_Type type = deg_build_scene_component_type(component); DEG::eDepsNode_Type type = deg_build_scene_component_type(component);
DEG::ComponentKey comp_key(&scene->id, type); DEG::ComponentKey comp_key(&scene->id, type);
DEG::DepsNodeHandle *deg_handle = get_handle(handle); DEG::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
deg_handle->builder->add_node_handle_relation(comp_key, deg_node_handle->builder->add_node_handle_relation(comp_key,
deg_handle, deg_node_handle,
description); description);
} }
void DEG_add_object_relation(DepsNodeHandle *handle, void DEG_add_object_relation(DepsNodeHandle *node_handle,
Object *object, Object *object,
eDepsObjectComponentType component, eDepsObjectComponentType component,
const char *description) const char *description)
{ {
DEG::eDepsNode_Type type = deg_build_object_component_type(component); DEG::eDepsNode_Type type = deg_build_object_component_type(component);
DEG::ComponentKey comp_key(&object->id, type); DEG::ComponentKey comp_key(&object->id, type);
DEG::DepsNodeHandle *deg_handle = get_handle(handle); DEG::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
deg_handle->builder->add_node_handle_relation(comp_key, deg_node_handle->builder->add_node_handle_relation(comp_key,
deg_handle, deg_node_handle,
description); description);
} }
void DEG_add_object_relation_with_customdata(DepsNodeHandle *handle, void DEG_add_object_relation_with_customdata(DepsNodeHandle *node_handle,
Object *object, Object *object,
eDepsObjectComponentType component, eDepsObjectComponentType component,
uint64_t customdata_mask, uint64_t customdata_mask,
@ -138,29 +138,29 @@ void DEG_add_object_relation_with_customdata(DepsNodeHandle *handle,
{ {
DEG::eDepsNode_Type type = deg_build_object_component_type(component); DEG::eDepsNode_Type type = deg_build_object_component_type(component);
DEG::ComponentKey comp_key(&object->id, type); DEG::ComponentKey comp_key(&object->id, type);
DEG::DepsNodeHandle *deg_handle = get_handle(handle); DEG::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
deg_handle->builder->add_node_handle_relation(comp_key, deg_node_handle->builder->add_node_handle_relation(comp_key,
deg_handle, deg_node_handle,
description); description);
if (object->type == OB_MESH) { if (object->type == OB_MESH) {
deg_handle->builder->add_customdata_mask(comp_key, customdata_mask); deg_node_handle->builder->add_customdata_mask(comp_key, customdata_mask);
} }
} }
void DEG_add_object_cache_relation(DepsNodeHandle *handle, void DEG_add_object_cache_relation(DepsNodeHandle *node_handle,
CacheFile *cache_file, CacheFile *cache_file,
eDepsObjectComponentType component, eDepsObjectComponentType component,
const char *description) const char *description)
{ {
DEG::eDepsNode_Type type = deg_build_object_component_type(component); DEG::eDepsNode_Type type = deg_build_object_component_type(component);
DEG::ComponentKey comp_key(&cache_file->id, type); DEG::ComponentKey comp_key(&cache_file->id, type);
DEG::DepsNodeHandle *deg_handle = get_handle(handle); DEG::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
deg_handle->builder->add_node_handle_relation(comp_key, deg_node_handle->builder->add_node_handle_relation(comp_key,
deg_handle, deg_node_handle,
description); description);
} }
void DEG_add_bone_relation(DepsNodeHandle *handle, void DEG_add_bone_relation(DepsNodeHandle *node_handle,
Object *object, Object *object,
const char *bone_name, const char *bone_name,
eDepsObjectComponentType component, eDepsObjectComponentType component,
@ -168,25 +168,50 @@ void DEG_add_bone_relation(DepsNodeHandle *handle,
{ {
DEG::eDepsNode_Type type = deg_build_object_component_type(component); DEG::eDepsNode_Type type = deg_build_object_component_type(component);
DEG::ComponentKey comp_key(&object->id, type, bone_name); DEG::ComponentKey comp_key(&object->id, type, bone_name);
DEG::DepsNodeHandle *deg_handle = get_handle(handle); DEG::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
/* XXX: "Geometry Eval" might not always be true, but this only gets called deg_node_handle->builder->add_node_handle_relation(comp_key,
* from modifier building now. deg_node_handle,
*/ description);
deg_handle->builder->add_node_handle_relation(comp_key,
deg_handle,
description);
} }
void DEG_add_special_eval_flag(struct DepsNodeHandle *handle, ID *id, uint32_t flag) void DEG_add_object_pointcache_relation(struct DepsNodeHandle *node_handle,
struct Object *object,
eDepsObjectComponentType component,
const char *description)
{ {
DEG::DepsNodeHandle *deg_handle = get_handle(handle); DEG::eDepsNode_Type type = deg_build_object_component_type(component);
deg_handle->builder->add_special_eval_flag(id, flag); DEG::ComponentKey comp_key(&object->id, type);
DEG::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
DEG::DepsgraphRelationBuilder *relation_builder = deg_node_handle->builder;
/* Add relation from source to the node handle. */
relation_builder->add_node_handle_relation(
comp_key, deg_node_handle, description);
/* Node deduct point cache component and connect source to it. */
ID *id = DEG_get_id_from_handle(node_handle);
DEG::ComponentKey point_cache_key(id, DEG::DEG_NODE_TYPE_POINT_CACHE);
DEG::DepsRelation *rel = relation_builder->add_relation(
comp_key, point_cache_key, "Point Cache");
rel->flag |= DEG::DEPSREL_FLAG_FLUSH_USER_EDIT_ONLY;
} }
struct Depsgraph *DEG_get_graph_from_handle(struct DepsNodeHandle *handle) void DEG_add_special_eval_flag(struct DepsNodeHandle *node_handle,
ID *id,
uint32_t flag)
{ {
DEG::DepsNodeHandle *deg_handle = get_handle(handle); DEG::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
DEG::DepsgraphRelationBuilder *relation_builder = deg_handle->builder; deg_node_handle->builder->add_special_eval_flag(id, flag);
}
struct ID *DEG_get_id_from_handle(struct DepsNodeHandle *node_handle)
{
DEG::DepsNodeHandle *deg_handle = get_node_handle(node_handle);
return deg_handle->node->owner->owner->id_orig;
}
struct Depsgraph *DEG_get_graph_from_handle(struct DepsNodeHandle *node_handle)
{
DEG::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
DEG::DepsgraphRelationBuilder *relation_builder = deg_node_handle->builder;
return reinterpret_cast<Depsgraph *>(relation_builder->getGraph()); return reinterpret_cast<Depsgraph *>(relation_builder->getGraph());
} }
@ -267,11 +292,9 @@ void DEG_graph_tag_relations_update(Depsgraph *graph)
* TODO(sergey): Try to make it so we don't flush updates * TODO(sergey): Try to make it so we don't flush updates
* to the whole depsgraph. * to the whole depsgraph.
*/ */
{ DEG::IDDepsNode *id_node = deg_graph->find_id_node(&deg_graph->scene->id);
DEG::IDDepsNode *id_node = deg_graph->find_id_node(&deg_graph->scene->id); if (id_node != NULL) {
if (id_node != NULL) { id_node->tag_update(deg_graph, DEG::DEG_UPDATE_SOURCE_RELATIONS);
id_node->tag_update(deg_graph);
}
} }
} }

@ -80,7 +80,7 @@ void DEG_evaluate_on_framechange(Main *bmain,
/* Update time on primary timesource. */ /* Update time on primary timesource. */
DEG::TimeSourceDepsNode *tsrc = deg_graph->find_time_source(); DEG::TimeSourceDepsNode *tsrc = deg_graph->find_time_source();
tsrc->cfra = ctime; tsrc->cfra = ctime;
tsrc->tag_update(deg_graph); tsrc->tag_update(deg_graph, DEG::DEG_UPDATE_SOURCE_TIME);
DEG::deg_graph_flush_updates(bmain, deg_graph); DEG::deg_graph_flush_updates(bmain, deg_graph);
/* Update time in scene. */ /* Update time in scene. */
if (deg_graph->scene_cow) { if (deg_graph->scene_cow) {

@ -122,8 +122,10 @@ void DEG_add_collision_relations(DepsNodeHandle *handle,
ob1, ob1,
modifiers_findByType(ob1, (ModifierType)modifier_type))) modifiers_findByType(ob1, (ModifierType)modifier_type)))
{ {
DEG_add_object_relation(handle, ob1, DEG_OB_COMP_TRANSFORM, name); DEG_add_object_pointcache_relation(
DEG_add_object_relation(handle, ob1, DEG_OB_COMP_GEOMETRY, name); handle, ob1, DEG_OB_COMP_TRANSFORM, name);
DEG_add_object_pointcache_relation(
handle, ob1, DEG_OB_COMP_GEOMETRY, name);
} }
} }
} }
@ -146,26 +148,25 @@ void DEG_add_forcefield_relations(DepsNodeHandle *handle,
if (relation->pd->forcefield == skip_forcefield) { if (relation->pd->forcefield == skip_forcefield) {
continue; continue;
} }
DEG_add_object_relation( DEG_add_object_pointcache_relation(
handle, relation->ob, DEG_OB_COMP_TRANSFORM, name); handle, relation->ob, DEG_OB_COMP_TRANSFORM, name);
if (relation->psys) { if (relation->psys) {
/* TODO(sergey): Consider going more granular with more dedicated /* TODO(sergey): Consider going more granular with more dedicated
* particle system operation. * particle system operation. */
*/ DEG_add_object_pointcache_relation(
DEG_add_object_relation(
handle, relation->ob, DEG_OB_COMP_GEOMETRY, name); handle, relation->ob, DEG_OB_COMP_GEOMETRY, name);
} }
if (relation->pd->forcefield == PFIELD_SMOKEFLOW && if (relation->pd->forcefield == PFIELD_SMOKEFLOW &&
relation->pd->f_source != NULL) relation->pd->f_source != NULL)
{ {
DEG_add_object_relation(handle, DEG_add_object_pointcache_relation(handle,
relation->pd->f_source, relation->pd->f_source,
DEG_OB_COMP_TRANSFORM, DEG_OB_COMP_TRANSFORM,
"Smoke Force Domain"); "Smoke Force Domain");
DEG_add_object_relation(handle, DEG_add_object_pointcache_relation(handle,
relation->pd->f_source, relation->pd->f_source,
DEG_OB_COMP_GEOMETRY, DEG_OB_COMP_GEOMETRY,
"Smoke Force Domain"); "Smoke Force Domain");
} }
if (add_absorption && (relation->pd->flag & PFIELD_VISIBILITY)) { if (add_absorption && (relation->pd->flag & PFIELD_VISIBILITY)) {
DEG_add_collision_relations(handle, DEG_add_collision_relations(handle,

@ -204,6 +204,10 @@ void depsgraph_tag_to_component_opcode(const ID *id,
depsgraph_base_flags_tag_to_component_opcode(id, depsgraph_base_flags_tag_to_component_opcode(id,
component_type, component_type,
operation_code); operation_code);
break;
case DEG_TAG_POINT_CACHE_UPDATE:
*component_type = DEG_NODE_TYPE_POINT_CACHE;
break;
case DEG_TAG_EDITORS_UPDATE: case DEG_TAG_EDITORS_UPDATE:
/* There is no such node in depsgraph, this tag is to be handled /* There is no such node in depsgraph, this tag is to be handled
* separately. * separately.
@ -249,20 +253,20 @@ void depsgraph_tag_component(Depsgraph *graph,
return; return;
} }
if (operation_code == DEG_OPCODE_OPERATION) { if (operation_code == DEG_OPCODE_OPERATION) {
component_node->tag_update(graph); component_node->tag_update(graph, DEG_UPDATE_SOURCE_USER_EDIT);
} }
else { else {
OperationDepsNode *operation_node = OperationDepsNode *operation_node =
component_node->find_operation(operation_code); component_node->find_operation(operation_code);
if (operation_node != NULL) { if (operation_node != NULL) {
operation_node->tag_update(graph); operation_node->tag_update(graph, DEG_UPDATE_SOURCE_USER_EDIT);
} }
} }
/* If component depends on copy-on-write, tag it as well. */ /* If component depends on copy-on-write, tag it as well. */
if (component_node->need_tag_cow_before_update()) { if (component_node->need_tag_cow_before_update()) {
ComponentDepsNode *cow_comp = ComponentDepsNode *cow_comp =
id_node->find_component(DEG_NODE_TYPE_COPY_ON_WRITE); id_node->find_component(DEG_NODE_TYPE_COPY_ON_WRITE);
cow_comp->tag_update(graph); cow_comp->tag_update(graph, DEG_UPDATE_SOURCE_USER_EDIT);
id_node->id_orig->recalc |= ID_RECALC_COPY_ON_WRITE; id_node->id_orig->recalc |= ID_RECALC_COPY_ON_WRITE;
} }
} }
@ -364,7 +368,7 @@ static void deg_graph_id_tag_update_single_flag(Main *bmain,
} }
/* Tag corresponding dependency graph operation for update. */ /* Tag corresponding dependency graph operation for update. */
if (component_type == DEG_NODE_TYPE_ID_REF) { if (component_type == DEG_NODE_TYPE_ID_REF) {
id_node->tag_update(graph); id_node->tag_update(graph, DEG_UPDATE_SOURCE_USER_EDIT);
} }
else { else {
depsgraph_tag_component(graph, id_node, component_type, operation_code); depsgraph_tag_component(graph, id_node, component_type, operation_code);
@ -427,7 +431,7 @@ void deg_graph_node_tag_zero(Main *bmain, Depsgraph *graph, IDDepsNode *id_node)
if (comp_node->type == DEG_NODE_TYPE_ANIMATION) { if (comp_node->type == DEG_NODE_TYPE_ANIMATION) {
continue; continue;
} }
comp_node->tag_update(graph); comp_node->tag_update(graph, DEG_UPDATE_SOURCE_USER_EDIT);
} }
GHASH_FOREACH_END(); GHASH_FOREACH_END();
deg_graph_id_tag_legacy_compat(bmain, graph, id, (eDepsgraph_Tag)0); deg_graph_id_tag_legacy_compat(bmain, graph, id, (eDepsgraph_Tag)0);
@ -463,6 +467,11 @@ void deg_graph_id_tag_update(Main *bmain, Depsgraph *graph, ID *id, int flag)
} }
/* Special case for nested node tree datablocks. */ /* Special case for nested node tree datablocks. */
id_tag_update_ntree_special(bmain, graph, id, flag); id_tag_update_ntree_special(bmain, graph, id, flag);
/* Direct update tags means that something outside of simulated/cached
* physics did change and that cache is to be invalidated.
*/
deg_graph_id_tag_update_single_flag(
bmain, graph, id, id_node, DEG_TAG_POINT_CACHE_UPDATE);
} }
void deg_id_tag_update(Main *bmain, ID *id, int flag) void deg_id_tag_update(Main *bmain, ID *id, int flag)
@ -515,7 +524,7 @@ void deg_graph_on_visible_update(Main *bmain, Depsgraph *graph)
deg_graph_id_tag_update(bmain, graph, id_node->id_orig, flag); deg_graph_id_tag_update(bmain, graph, id_node->id_orig, flag);
if (id_type == ID_SCE) { if (id_type == ID_SCE) {
/* Make sure collection properties are up to date. */ /* Make sure collection properties are up to date. */
id_node->tag_update(graph); id_node->tag_update(graph, DEG_UPDATE_SOURCE_VISIBILITY);
} }
/* Now when ID is updated to the new visibility state, prevent it from /* Now when ID is updated to the new visibility state, prevent it from
* being re-tagged again. Simplest way to do so is to pretend that it * being re-tagged again. Simplest way to do so is to pretend that it
@ -590,6 +599,7 @@ const char *DEG_update_tag_as_string(eDepsgraph_Tag flag)
case DEG_TAG_SHADING_UPDATE: return "SHADING_UPDATE"; case DEG_TAG_SHADING_UPDATE: return "SHADING_UPDATE";
case DEG_TAG_SELECT_UPDATE: return "SELECT_UPDATE"; case DEG_TAG_SELECT_UPDATE: return "SELECT_UPDATE";
case DEG_TAG_BASE_FLAGS_UPDATE: return "BASE_FLAGS_UPDATE"; case DEG_TAG_BASE_FLAGS_UPDATE: return "BASE_FLAGS_UPDATE";
case DEG_TAG_POINT_CACHE_UPDATE: return "POINT_CACHE_UPDATE";
case DEG_TAG_EDITORS_UPDATE: return "EDITORS_UPDATE"; case DEG_TAG_EDITORS_UPDATE: return "EDITORS_UPDATE";
} }
BLI_assert(!"Unhandled update flag, should never happen!"); BLI_assert(!"Unhandled update flag, should never happen!");

@ -100,6 +100,7 @@ const char *nodeTypeAsString(eDepsNode_Type type)
STRINGIFY_TYPE(SHADING); STRINGIFY_TYPE(SHADING);
STRINGIFY_TYPE(SHADING_PARAMETERS); STRINGIFY_TYPE(SHADING_PARAMETERS);
STRINGIFY_TYPE(CACHE); STRINGIFY_TYPE(CACHE);
STRINGIFY_TYPE(POINT_CACHE);
STRINGIFY_TYPE(BATCH_CACHE); STRINGIFY_TYPE(BATCH_CACHE);
/* Duplication. */ /* Duplication. */
STRINGIFY_TYPE(DUPLI); STRINGIFY_TYPE(DUPLI);
@ -139,7 +140,6 @@ const char *operationCodeAsString(eDepsOperation_Code opcode)
STRINGIFY_OPCODE(RIGIDBODY_TRANSFORM_COPY); STRINGIFY_OPCODE(RIGIDBODY_TRANSFORM_COPY);
/* Geometry. */ /* Geometry. */
STRINGIFY_OPCODE(GEOMETRY_UBEREVAL); STRINGIFY_OPCODE(GEOMETRY_UBEREVAL);
STRINGIFY_OPCODE(GEOMETRY_CLOTH_MODIFIER);
STRINGIFY_OPCODE(GEOMETRY_SHAPEKEY); STRINGIFY_OPCODE(GEOMETRY_SHAPEKEY);
/* Object data. */ /* Object data. */
STRINGIFY_OPCODE(LIGHT_PROBE_EVAL); STRINGIFY_OPCODE(LIGHT_PROBE_EVAL);

@ -150,7 +150,10 @@ typedef enum eDepsNode_Type {
/* Material Shading Component */ /* Material Shading Component */
DEG_NODE_TYPE_SHADING, DEG_NODE_TYPE_SHADING,
DEG_NODE_TYPE_SHADING_PARAMETERS, DEG_NODE_TYPE_SHADING_PARAMETERS,
/* Point cache Component */
DEG_NODE_TYPE_POINT_CACHE,
/* Cache Component */ /* Cache Component */
/* TODO(sergey); Verify that we really need this. */
DEG_NODE_TYPE_CACHE, DEG_NODE_TYPE_CACHE,
/* Batch Cache Component - TODO (dfelinto/sergey) rename to make it more generic. */ /* Batch Cache Component - TODO (dfelinto/sergey) rename to make it more generic. */
DEG_NODE_TYPE_BATCH_CACHE, DEG_NODE_TYPE_BATCH_CACHE,
@ -209,9 +212,10 @@ typedef enum eDepsOperation_Code {
DEG_OPCODE_RIGIDBODY_TRANSFORM_COPY, DEG_OPCODE_RIGIDBODY_TRANSFORM_COPY,
/* Geometry. ---------------------------------------- */ /* Geometry. ---------------------------------------- */
/* Evaluate the whole geometry, including modifiers. */ /* Evaluate the whole geometry, including modifiers. */
DEG_OPCODE_GEOMETRY_UBEREVAL, DEG_OPCODE_GEOMETRY_UBEREVAL,
DEG_OPCODE_GEOMETRY_CLOTH_MODIFIER, /* Evaluation of a shape key. */
DEG_OPCODE_GEOMETRY_SHAPEKEY, DEG_OPCODE_GEOMETRY_SHAPEKEY,
/* Object data. ------------------------------------- */ /* Object data. ------------------------------------- */
@ -287,4 +291,19 @@ typedef enum eDepsOperation_Code {
} eDepsOperation_Code; } eDepsOperation_Code;
const char *operationCodeAsString(eDepsOperation_Code opcode); const char *operationCodeAsString(eDepsOperation_Code opcode);
/* Source of the dependency graph node update tag.
*
* NOTE: This is a bit mask, so accumulation of sources is possible.
*/
typedef enum eDepsTag_Source {
/* Update is caused by a time change. */
DEG_UPDATE_SOURCE_TIME = (1 << 0),
/* Update caused by user directly or indirectly influencing the node. */
DEG_UPDATE_SOURCE_USER_EDIT = (1 << 1),
/* Update is happening as a special response for the relations update. */
DEG_UPDATE_SOURCE_RELATIONS = (1 << 2),
/* Update is happening due to visibility change. */
DEG_UPDATE_SOURCE_VISIBILITY = (1 << 3),
} eDepsTag_Source;
} // namespace DEG } // namespace DEG

@ -202,19 +202,32 @@ BLI_INLINE OperationDepsNode *flush_schedule_children(
{ {
OperationDepsNode *result = NULL; OperationDepsNode *result = NULL;
foreach (DepsRelation *rel, op_node->outlinks) { foreach (DepsRelation *rel, op_node->outlinks) {
/* Flush is forbidden, completely. */
if (rel->flag & DEPSREL_FLAG_NO_FLUSH) { if (rel->flag & DEPSREL_FLAG_NO_FLUSH) {
continue; continue;
} }
OperationDepsNode *to_node = (OperationDepsNode *)rel->to; /* Relation only allows flushes on user changes, but the node was not
if (to_node->scheduled == false) { * affected by user. */
if (result != NULL) { if ((rel->flag & DEPSREL_FLAG_FLUSH_USER_EDIT_ONLY) &&
queue->push_front(to_node); (op_node->flag & DEPSOP_FLAG_USER_MODIFIED) == 0)
} {
else { continue;
result = to_node;
}
to_node->scheduled = true;
} }
OperationDepsNode *to_node = (OperationDepsNode *)rel->to;
/* Always flush flushable flags, so children always know what happened
* to their parents. */
to_node->flag |= (op_node->flag & DEPSOP_FLAG_FLUSH);
/* Flush update over the relation, if it was not flushed yet. */
if (to_node->scheduled) {
continue;
}
if (result != NULL) {
queue->push_front(to_node);
}
else {
result = to_node;
}
to_node->scheduled = true;
} }
return result; return result;
} }
@ -408,7 +421,9 @@ static void graph_clear_operation_func(
Depsgraph *graph = (Depsgraph *)data_v; Depsgraph *graph = (Depsgraph *)data_v;
OperationDepsNode *node = graph->operations[i]; OperationDepsNode *node = graph->operations[i];
/* Clear node's "pending update" settings. */ /* Clear node's "pending update" settings. */
node->flag &= ~(DEPSOP_FLAG_DIRECTLY_MODIFIED | DEPSOP_FLAG_NEEDS_UPDATE); node->flag &= ~(DEPSOP_FLAG_DIRECTLY_MODIFIED |
DEPSOP_FLAG_NEEDS_UPDATE |
DEPSOP_FLAG_USER_MODIFIED);
} }
/* Clear tags from all operation nodes. */ /* Clear tags from all operation nodes. */

@ -98,7 +98,8 @@ struct DepsNode {
virtual void init(const ID * /*id*/, virtual void init(const ID * /*id*/,
const char * /*subdata*/) {} const char * /*subdata*/) {}
virtual void tag_update(Depsgraph * /*graph*/) {} virtual void tag_update(Depsgraph * /*graph*/,
eDepsTag_Source /*source*/) {}
virtual OperationDepsNode *get_entry_operation() { return NULL; } virtual OperationDepsNode *get_entry_operation() { return NULL; }
virtual OperationDepsNode *get_exit_operation() { return NULL; } virtual OperationDepsNode *get_exit_operation() { return NULL; }

@ -283,20 +283,20 @@ void ComponentDepsNode::clear_operations()
operations.clear(); operations.clear();
} }
void ComponentDepsNode::tag_update(Depsgraph *graph) void ComponentDepsNode::tag_update(Depsgraph *graph, eDepsTag_Source source)
{ {
OperationDepsNode *entry_op = get_entry_operation(); OperationDepsNode *entry_op = get_entry_operation();
if (entry_op != NULL && entry_op->flag & DEPSOP_FLAG_NEEDS_UPDATE) { if (entry_op != NULL && entry_op->flag & DEPSOP_FLAG_NEEDS_UPDATE) {
return; return;
} }
foreach (OperationDepsNode *op_node, operations) { foreach (OperationDepsNode *op_node, operations) {
op_node->tag_update(graph); op_node->tag_update(graph, source);
} }
// It is possible that tag happens before finalization. // It is possible that tag happens before finalization.
if (operations_map != NULL) { if (operations_map != NULL) {
GHASH_FOREACH_BEGIN(OperationDepsNode *, op_node, operations_map) GHASH_FOREACH_BEGIN(OperationDepsNode *, op_node, operations_map)
{ {
op_node->tag_update(graph); op_node->tag_update(graph, source);
} }
GHASH_FOREACH_END(); GHASH_FOREACH_END();
} }
@ -392,8 +392,9 @@ DEG_COMPONENT_NODE_DEFINE(Geometry, GEOMETRY, ID_RECALC_GEOME
DEG_COMPONENT_NODE_DEFINE(LayerCollections, LAYER_COLLECTIONS, 0); DEG_COMPONENT_NODE_DEFINE(LayerCollections, LAYER_COLLECTIONS, 0);
DEG_COMPONENT_NODE_DEFINE(Parameters, PARAMETERS, ID_RECALC); DEG_COMPONENT_NODE_DEFINE(Parameters, PARAMETERS, ID_RECALC);
DEG_COMPONENT_NODE_DEFINE(Particles, EVAL_PARTICLES, ID_RECALC_GEOMETRY); DEG_COMPONENT_NODE_DEFINE(Particles, EVAL_PARTICLES, ID_RECALC_GEOMETRY);
DEG_COMPONENT_NODE_DEFINE(Proxy, PROXY, ID_RECALC_GEOMETRY); DEG_COMPONENT_NODE_DEFINE(PointCache, POINT_CACHE, 0);
DEG_COMPONENT_NODE_DEFINE(Pose, EVAL_POSE, ID_RECALC_GEOMETRY); DEG_COMPONENT_NODE_DEFINE(Pose, EVAL_POSE, ID_RECALC_GEOMETRY);
DEG_COMPONENT_NODE_DEFINE(Proxy, PROXY, ID_RECALC_GEOMETRY);
DEG_COMPONENT_NODE_DEFINE(Sequencer, SEQUENCER, ID_RECALC); DEG_COMPONENT_NODE_DEFINE(Sequencer, SEQUENCER, ID_RECALC);
DEG_COMPONENT_NODE_DEFINE(Shading, SHADING, ID_RECALC_DRAW); DEG_COMPONENT_NODE_DEFINE(Shading, SHADING, ID_RECALC_DRAW);
DEG_COMPONENT_NODE_DEFINE(ShadingParameters, SHADING_PARAMETERS, ID_RECALC_DRAW); DEG_COMPONENT_NODE_DEFINE(ShadingParameters, SHADING_PARAMETERS, ID_RECALC_DRAW);
@ -414,6 +415,7 @@ void deg_register_component_depsnodes()
deg_register_node_typeinfo(&DNTI_LAYER_COLLECTIONS); deg_register_node_typeinfo(&DNTI_LAYER_COLLECTIONS);
deg_register_node_typeinfo(&DNTI_PARAMETERS); deg_register_node_typeinfo(&DNTI_PARAMETERS);
deg_register_node_typeinfo(&DNTI_EVAL_PARTICLES); deg_register_node_typeinfo(&DNTI_EVAL_PARTICLES);
deg_register_node_typeinfo(&DNTI_POINT_CACHE);
deg_register_node_typeinfo(&DNTI_PROXY); deg_register_node_typeinfo(&DNTI_PROXY);
deg_register_node_typeinfo(&DNTI_EVAL_POSE); deg_register_node_typeinfo(&DNTI_EVAL_POSE);
deg_register_node_typeinfo(&DNTI_SEQUENCER); deg_register_node_typeinfo(&DNTI_SEQUENCER);

@ -69,9 +69,9 @@ struct ComponentDepsNode : public DepsNode {
ComponentDepsNode(); ComponentDepsNode();
~ComponentDepsNode(); ~ComponentDepsNode();
void init(const ID *id, const char *subdata); void init(const ID *id, const char *subdata) override;
virtual string identifier() const; virtual string identifier() const override;
/* Find an existing operation, if requested operation does not exist /* Find an existing operation, if requested operation does not exist
* NULL will be returned. * NULL will be returned.
@ -120,10 +120,10 @@ struct ComponentDepsNode : public DepsNode {
void clear_operations(); void clear_operations();
void tag_update(Depsgraph *graph); virtual void tag_update(Depsgraph *graph, eDepsTag_Source source) override;
OperationDepsNode *get_entry_operation(); virtual OperationDepsNode *get_entry_operation() override;
OperationDepsNode *get_exit_operation(); virtual OperationDepsNode *get_exit_operation() override;
void finalize_build(Depsgraph *graph); void finalize_build(Depsgraph *graph);
@ -191,8 +191,9 @@ DEG_COMPONENT_NODE_DECLARE_GENERIC(Geometry);
DEG_COMPONENT_NODE_DECLARE_GENERIC(LayerCollections); DEG_COMPONENT_NODE_DECLARE_GENERIC(LayerCollections);
DEG_COMPONENT_NODE_DECLARE_GENERIC(Parameters); DEG_COMPONENT_NODE_DECLARE_GENERIC(Parameters);
DEG_COMPONENT_NODE_DECLARE_GENERIC(Particles); DEG_COMPONENT_NODE_DECLARE_GENERIC(Particles);
DEG_COMPONENT_NODE_DECLARE_GENERIC(Proxy);
DEG_COMPONENT_NODE_DECLARE_GENERIC(Pose); DEG_COMPONENT_NODE_DECLARE_GENERIC(Pose);
DEG_COMPONENT_NODE_DECLARE_GENERIC(PointCache);
DEG_COMPONENT_NODE_DECLARE_GENERIC(Proxy);
DEG_COMPONENT_NODE_DECLARE_GENERIC(Sequencer); DEG_COMPONENT_NODE_DECLARE_GENERIC(Sequencer);
DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_UPDATE(Shading); DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_UPDATE(Shading);
DEG_COMPONENT_NODE_DECLARE_GENERIC(ShadingParameters); DEG_COMPONENT_NODE_DECLARE_GENERIC(ShadingParameters);

@ -204,11 +204,11 @@ ComponentDepsNode *IDDepsNode::add_component(eDepsNode_Type type,
return comp_node; return comp_node;
} }
void IDDepsNode::tag_update(Depsgraph *graph) void IDDepsNode::tag_update(Depsgraph *graph, eDepsTag_Source source)
{ {
GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp_node, components) GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp_node, components)
{ {
comp_node->tag_update(graph); comp_node->tag_update(graph, source);
} }
GHASH_FOREACH_END(); GHASH_FOREACH_END();
} }

@ -49,19 +49,19 @@ struct IDDepsNode : public DepsNode {
const char *name; const char *name;
}; };
void init(const ID *id, const char *subdata); virtual void init(const ID *id, const char *subdata) override;
void init_copy_on_write(ID *id_cow_hint = NULL); void init_copy_on_write(ID *id_cow_hint = NULL);
~IDDepsNode(); ~IDDepsNode();
void destroy(); void destroy();
virtual string identifier() const; virtual string identifier() const override;
ComponentDepsNode *find_component(eDepsNode_Type type, ComponentDepsNode *find_component(eDepsNode_Type type,
const char *name = "") const; const char *name = "") const;
ComponentDepsNode *add_component(eDepsNode_Type type, ComponentDepsNode *add_component(eDepsNode_Type type,
const char *name = ""); const char *name = "");
void tag_update(Depsgraph *graph); virtual void tag_update(Depsgraph *graph, eDepsTag_Source source) override;
void finalize_build(Depsgraph *graph); void finalize_build(Depsgraph *graph);

@ -75,14 +75,23 @@ string OperationDepsNode::full_identifier() const
return owner_str + "." + identifier(); return owner_str + "." + identifier();
} }
void OperationDepsNode::tag_update(Depsgraph *graph) void OperationDepsNode::tag_update(Depsgraph *graph, eDepsTag_Source source)
{ {
if (flag & DEPSOP_FLAG_NEEDS_UPDATE) { if ((flag & DEPSOP_FLAG_NEEDS_UPDATE) == 0) {
return; graph->add_entry_tag(this);
} }
/* Tag for update, but also note that this was the source of an update. */ /* Tag for update, but also note that this was the source of an update. */
flag |= (DEPSOP_FLAG_NEEDS_UPDATE | DEPSOP_FLAG_DIRECTLY_MODIFIED); flag |= (DEPSOP_FLAG_NEEDS_UPDATE | DEPSOP_FLAG_DIRECTLY_MODIFIED);
graph->add_entry_tag(this); switch (source) {
case DEG_UPDATE_SOURCE_TIME:
case DEG_UPDATE_SOURCE_RELATIONS:
case DEG_UPDATE_SOURCE_VISIBILITY:
/* Currently nothing. */
break;
case DEG_UPDATE_SOURCE_USER_EDIT:
flag |= DEPSOP_FLAG_USER_MODIFIED;
break;
}
} }
void OperationDepsNode::set_as_entry() void OperationDepsNode::set_as_entry()

@ -40,13 +40,17 @@ namespace DEG {
struct ComponentDepsNode; struct ComponentDepsNode;
/* Flags for Depsgraph Nodes */ /* Flags for Depsgraph Nodes. */
typedef enum eDepsOperation_Flag { typedef enum eDepsOperation_Flag {
/* node needs to be updated */ /* Node needs to be updated. */
DEPSOP_FLAG_NEEDS_UPDATE = (1 << 0), DEPSOP_FLAG_NEEDS_UPDATE = (1 << 0),
/* Node was directly modified, causing need for update. */
/* node was directly modified, causing need for update */
DEPSOP_FLAG_DIRECTLY_MODIFIED = (1 << 1), DEPSOP_FLAG_DIRECTLY_MODIFIED = (1 << 1),
/* Node was updated due to user input. */
DEPSOP_FLAG_USER_MODIFIED = (1 << 2),
/* Set of flags which gets flushed along the relations. */
DEPSOP_FLAG_FLUSH = (DEPSOP_FLAG_USER_MODIFIED)
} eDepsOperation_Flag; } eDepsOperation_Flag;
/* Atomic Operation - Base type for all operations */ /* Atomic Operation - Base type for all operations */
@ -54,17 +58,21 @@ struct OperationDepsNode : public DepsNode {
OperationDepsNode(); OperationDepsNode();
~OperationDepsNode(); ~OperationDepsNode();
string identifier() const; virtual string identifier() const override;
string full_identifier() const; string full_identifier() const;
void tag_update(Depsgraph *graph); virtual void tag_update(Depsgraph *graph, eDepsTag_Source source) override;
bool is_noop() const { return (bool)evaluate == false; } bool is_noop() const { return (bool)evaluate == false; }
OperationDepsNode *get_entry_operation() { return this; } virtual OperationDepsNode *get_entry_operation() override {
OperationDepsNode *get_exit_operation() { return this; } return this;
}
virtual OperationDepsNode *get_exit_operation() override {
return this;
}
/* Set this operation as compoonent's entry/exit operation. */ /* Set this operation as component's entry/exit operation. */
void set_as_entry(); void set_as_entry();
void set_as_exit(); void set_as_exit();

@ -37,11 +37,12 @@
namespace DEG { namespace DEG {
void TimeSourceDepsNode::tag_update(Depsgraph *graph) void TimeSourceDepsNode::tag_update(Depsgraph *graph,
eDepsTag_Source /*source*/)
{ {
foreach (DepsRelation *rel, outlinks) { foreach (DepsRelation *rel, outlinks) {
DepsNode *node = rel->to; DepsNode *node = rel->to;
node->tag_update(graph); node->tag_update(graph, DEG_UPDATE_SOURCE_TIME);
} }
} }

@ -44,7 +44,7 @@ struct TimeSourceDepsNode : public DepsNode {
// TODO: evaluate() operation needed // TODO: evaluate() operation needed
void tag_update(Depsgraph *graph); virtual void tag_update(Depsgraph *graph, eDepsTag_Source source) override;
DEG_DEPSNODE_DECLARE; DEG_DEPSNODE_DECLARE;
}; };