diff options
Diffstat (limited to 'source/blender/depsgraph/intern/eval/deg_eval_flush.cc')
-rw-r--r-- | source/blender/depsgraph/intern/eval/deg_eval_flush.cc | 128 |
1 files changed, 71 insertions, 57 deletions
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc index daf008ddb7d..c0d5e08b80f 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc @@ -36,6 +36,7 @@ #include <deque> #include "BLI_utildefines.h" +#include "BLI_listbase.h" #include "BLI_task.h" #include "BLI_ghash.h" @@ -51,6 +52,7 @@ extern "C" { #include "intern/nodes/deg_node_operation.h" #include "intern/depsgraph_intern.h" +#include "intern/eval/deg_eval_copy_on_write.h" #include "util/deg_util_foreach.h" namespace DEG { @@ -70,19 +72,6 @@ typedef std::deque<OperationDepsNode *> FlushQueue; namespace { -// TODO(sergey): De-duplicate with depsgraph_tag,cc -void lib_id_recalc_tag(Main *bmain, ID *id) -{ - id->recalc |= ID_RECALC; - DEG_id_type_tag(bmain, GS(id->name)); -} - -void lib_id_recalc_data_tag(Main *bmain, ID *id) -{ - id->recalc |= ID_RECALC_DATA; - DEG_id_type_tag(bmain, GS(id->name)); -} - void flush_init_operation_node_func( void *__restrict data_v, const int i, @@ -146,9 +135,10 @@ BLI_INLINE void flush_handle_id_node(IDDepsNode *id_node) } /* TODO(sergey): We can reduce number of arguments here. */ -BLI_INLINE void flush_handle_component_node(Depsgraph * /*graph*/, +BLI_INLINE void flush_handle_component_node(Depsgraph *graph, IDDepsNode *id_node, ComponentDepsNode *comp_node, + bool use_copy_on_write, FlushQueue *queue) { /* We only handle component once. */ @@ -156,46 +146,27 @@ BLI_INLINE void flush_handle_component_node(Depsgraph * /*graph*/, return; } comp_node->done = COMPONENT_STATE_DONE; + /* Currently this is needed to get object->mesh to be replaced with + * original mesh (rather than being evaluated_mesh). + * + * TODO(sergey): This is something we need to avoid. + */ + if (use_copy_on_write && comp_node->depends_on_cow()) { + ComponentDepsNode *cow_comp = + id_node->find_component(DEG_NODE_TYPE_COPY_ON_WRITE); + cow_comp->tag_update(graph); + } /* Tag all required operations in component for update. */ foreach (OperationDepsNode *op, comp_node->operations) { - op->flag |= DEPSOP_FLAG_NEEDS_UPDATE; - } - if (GS(id_node->id->name) == ID_OB) { - Object *object = (Object *)id_node->id; - /* This code is used to preserve those areas which does - * direct object update, + /* We don't want to flush tags in "upstream" direction for + * certain types of operations. * - * Plus it ensures visibility changes and relations and - * layers visibility update has proper flags to work with. + * TODO(sergey): Need a more generic solution for this. */ - switch (comp_node->type) { - case DEG_NODE_TYPE_UNDEFINED: - case DEG_NODE_TYPE_OPERATION: - case DEG_NODE_TYPE_TIMESOURCE: - case DEG_NODE_TYPE_ID_REF: - case DEG_NODE_TYPE_SEQUENCER: - case NUM_DEG_NODE_TYPES: - /* Ignore, does not translate to object component. */ - BLI_assert(!"This should never happen!"); - break; - case DEG_NODE_TYPE_ANIMATION: - object->recalc |= OB_RECALC_TIME; - break; - case DEG_NODE_TYPE_TRANSFORM: - object->recalc |= OB_RECALC_OB; - break; - case DEG_NODE_TYPE_GEOMETRY: - case DEG_NODE_TYPE_EVAL_POSE: - case DEG_NODE_TYPE_BONE: - case DEG_NODE_TYPE_EVAL_PARTICLES: - case DEG_NODE_TYPE_SHADING: - case DEG_NODE_TYPE_CACHE: - case DEG_NODE_TYPE_PROXY: - object->recalc |= OB_RECALC_DATA; - break; - case DEG_NODE_TYPE_PARAMETERS: - break; + if (op->opcode == DEG_OPCODE_PARTICLE_SETTINGS_EVAL) { + continue; } + op->flag |= DEPSOP_FLAG_NEEDS_UPDATE; } /* When some target changes bone, we might need to re-run the * whole IK solver, otherwise result might be unpredictable. @@ -237,19 +208,54 @@ BLI_INLINE OperationDepsNode *flush_schedule_children( return result; } -BLI_INLINE void flush_editors_id_update(Main *bmain, - Depsgraph *graph) +void flush_engine_data_update(ID *id) +{ + if (GS(id->name) != ID_OB) { + return; + } + Object *object = (Object *)id; + BLI_LISTBASE_FOREACH(ObjectEngineData *, engine_data, &object->drawdata) { + engine_data->recalc |= id->recalc; + } +} + +/* NOTE: It will also accumulate flags from changed components. */ +void flush_editors_id_update(Main *bmain, + Depsgraph *graph, + const DEGEditorUpdateContext *update_ctx) { foreach (IDDepsNode *id_node, graph->id_nodes) { if (id_node->done != ID_STATE_MODIFIED) { continue; } + DEG_id_type_tag(bmain, GS(id_node->id_orig->name)); /* TODO(sergey): Do we need to pass original or evaluated ID here? */ - ID *id = id_node->id; - deg_editors_id_update(bmain, id); - lib_id_recalc_tag(bmain, id); - /* TODO(sergey): For until we've got proper data nodes in the graph. */ - lib_id_recalc_data_tag(bmain, id); + ID *id_orig = id_node->id_orig; + ID *id_cow = id_node->id_cow; + /* Copy tag from original data to CoW storage. + * This is because DEG_id_tag_update() sets tags on original + * data. + */ + id_cow->recalc |= (id_orig->recalc & ID_RECALC_ALL); + /* Gather recalc flags from all changed components. */ + GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp_node, id_node->components) + { + if (comp_node->done != COMPONENT_STATE_DONE) { + continue; + } + DepsNodeFactory *factory = deg_type_get_factory(comp_node->type); + BLI_assert(factory != NULL); + id_cow->recalc |= factory->id_recalc_tag(); + } + GHASH_FOREACH_END(); + DEG_DEBUG_PRINTF("Accumulated recalc bits for %s: %u\n", + id_orig->name, (unsigned int)id_cow->recalc); + /* Inform editors. */ + if (deg_copy_on_write_is_expanded(id_cow)) { + deg_editors_id_update(update_ctx, id_cow); + /* Inform draw engines that something was changed. */ + flush_engine_data_update(id_cow); + } } } @@ -260,6 +266,7 @@ BLI_INLINE void flush_editors_id_update(Main *bmain, */ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph) { + const bool use_copy_on_write = DEG_depsgraph_use_copy_on_write(); /* Sanity checks. */ BLI_assert(bmain != NULL); BLI_assert(graph != NULL); @@ -272,6 +279,12 @@ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph) /* Starting from the tagged "entry" nodes, flush outwards. */ FlushQueue queue; flush_schedule_entrypoints(graph, &queue); + /* Prepare update context for editors. */ + DEGEditorUpdateContext update_ctx; + update_ctx.bmain = bmain; + update_ctx.depsgraph = (::Depsgraph *)graph; + update_ctx.scene = graph->scene; + update_ctx.view_layer = graph->view_layer; /* Do actual flush. */ while (!queue.empty()) { OperationDepsNode *op_node = queue.front(); @@ -286,13 +299,14 @@ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph) flush_handle_component_node(graph, id_node, comp_node, + use_copy_on_write, &queue); /* Flush to nodes along links. */ op_node = flush_schedule_children(op_node, &queue); } } /* Inform editors about all changes. */ - flush_editors_id_update(bmain, graph); + flush_editors_id_update(bmain, graph, &update_ctx); } static void graph_clear_func( |