diff options
11 files changed, 196 insertions, 116 deletions
diff --git a/source/blender/depsgraph/intern/builder/deg_builder.cc b/source/blender/depsgraph/intern/builder/deg_builder.cc index 8f5925a5ce3..0549ec76f3c 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder.cc @@ -34,6 +34,8 @@ #include "DNA_object_types.h" #include "DNA_ID.h" +#include "BLI_stack.h" + extern "C" { #include "BKE_animsys.h" } @@ -43,6 +45,8 @@ extern "C" { #include "intern/eval/deg_eval_copy_on_write.h" #include "intern/nodes/deg_node.h" #include "intern/nodes/deg_node_id.h" +#include "intern/nodes/deg_node_component.h" +#include "intern/nodes/deg_node_operation.h" #include "util/deg_util_foreach.h" @@ -50,8 +54,61 @@ extern "C" { namespace DEG { +namespace { + +void deg_graph_build_flush_layers(Depsgraph *graph) +{ + BLI_Stack *stack = BLI_stack_new(sizeof(OperationDepsNode*), + "DEG flush layers stack"); + foreach (OperationDepsNode *op_node, graph->operations) { + op_node->done = 0; + op_node->num_links_pending = 0; + foreach (DepsRelation *rel, op_node->outlinks) { + if ((rel->from->type == DEG_NODE_TYPE_OPERATION) && + (rel->flag & DEPSREL_FLAG_CYCLIC) == 0) + { + ++op_node->num_links_pending; + } + } + if (op_node->num_links_pending == 0) { + BLI_stack_push(stack, &op_node); + op_node->done = 1; + } + } + while (!BLI_stack_is_empty(stack)) { + OperationDepsNode *op_node; + BLI_stack_pop(stack, &op_node); + /* Flush layers to parents. */ + foreach (DepsRelation *rel, op_node->inlinks) { + if (rel->from->type == DEG_NODE_TYPE_OPERATION) { + OperationDepsNode *op_from = (OperationDepsNode *)rel->from; + op_from->owner->owner->is_visible |= + op_node->owner->owner->is_visible; + } + } + /* Schedule parent nodes. */ + foreach (DepsRelation *rel, op_node->inlinks) { + if (rel->from->type == DEG_NODE_TYPE_OPERATION) { + OperationDepsNode *op_from = (OperationDepsNode *)rel->from; + if ((rel->flag & DEPSREL_FLAG_CYCLIC) == 0) { + BLI_assert(op_from->num_links_pending > 0); + --op_from->num_links_pending; + } + if (op_from->num_links_pending == 0 && op_from->done == 0) { + BLI_stack_push(stack, &op_from); + op_from->done = 1; + } + } + } + } + BLI_stack_free(stack); +} + +} // namespace + void deg_graph_build_finalize(Main *bmain, Depsgraph *graph) { + deg_graph_build_flush_layers(graph); /* Re-tag IDs for update if it was tagged before the relations * update tag. */ diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index 8d2960d1587..45c8bb5c93d 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -141,6 +141,8 @@ DepsgraphNodeBuilder::DepsgraphNodeBuilder(Main *bmain, Depsgraph *graph) graph_(graph), scene_(NULL), view_layer_(NULL), + view_layer_index_(-1), + collection_(NULL), cow_id_hash_(NULL) { } @@ -394,7 +396,7 @@ void DepsgraphNodeBuilder::build_id(ID *id) { build_camera((Camera *)id); break; case ID_GR: - build_collection(DEG_COLLECTION_OWNER_UNKNOWN, (Collection *)id); + build_collection((Collection *)id); break; case ID_OB: build_object(-1, (Object *)id, DEG_ID_LINKED_INDIRECTLY); @@ -445,46 +447,49 @@ void DepsgraphNodeBuilder::build_id(ID *id) { } } -void DepsgraphNodeBuilder::build_collection( - eDepsNode_CollectionOwner owner_type, - Collection *collection) +void DepsgraphNodeBuilder::build_collection(Collection *collection) { if (built_map_.checkIsBuiltAndTag(collection)) { + /* NOTE: Currently collections restrict flags only depend on collection + * itself and do not depend on a "context" (like, particle system + * visibility). + * + * If we ever change this, we need to update restrict flag here for an + * already built collection. + */ return; } - const bool allow_restrict_flags = (owner_type == DEG_COLLECTION_OWNER_SCENE); - if (allow_restrict_flags) { - const int restrict_flag = (graph_->mode == DAG_EVAL_VIEWPORT) - ? COLLECTION_RESTRICT_VIEW - : COLLECTION_RESTRICT_RENDER; - if (collection->flag & restrict_flag) { - return; - } - } + Collection *current_state_collection = collection_; + collection_ = collection; + const int restrict_flag = (graph_->mode == DAG_EVAL_VIEWPORT) + ? COLLECTION_RESTRICT_VIEW + : COLLECTION_RESTRICT_RENDER; + const bool is_parent_collection_restricted = + (current_state_collection == NULL) + ? false + : (current_state_collection->flag & restrict_flag); + const bool is_collection_restricted = (collection->flag & restrict_flag); + const bool is_collection_visible = + !is_collection_restricted && !is_parent_collection_restricted; /* Collection itself. */ - add_id_node(&collection->id); + IDDepsNode *id_node = add_id_node(&collection->id); + id_node->is_visible = is_collection_visible; /* Build collection objects. */ LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) { - if (allow_restrict_flags) { - const int restrict_flag = ( - (graph_->mode == DAG_EVAL_VIEWPORT) ? - OB_RESTRICT_VIEW : - OB_RESTRICT_RENDER); - if (cob->ob->restrictflag & restrict_flag) { - continue; - } - } - build_object(-1, cob->ob, DEG_ID_LINKED_INDIRECTLY); + build_object( + -1, cob->ob, DEG_ID_LINKED_INDIRECTLY, is_collection_visible); } /* Build child collections. */ LISTBASE_FOREACH (CollectionChild *, child, &collection->children) { - build_collection(owner_type, child->collection); + build_collection(child->collection); } + collection_ = current_state_collection; } void DepsgraphNodeBuilder::build_object(int base_index, Object *object, - eDepsNode_LinkedState_Type linked_state) + eDepsNode_LinkedState_Type linked_state, + bool is_visible) { const bool has_object = built_map_.checkIsBuiltAndTag(object); /* Skip rest of components if the ID node was already there. */ @@ -497,11 +502,13 @@ void DepsgraphNodeBuilder::build_object(int base_index, build_object_flags(base_index, object, linked_state); } id_node->linked_state = max(id_node->linked_state, linked_state); + id_node->is_visible |= is_visible; return; } /* Create ID node for object and begin init. */ IDDepsNode *id_node = add_id_node(&object->id); id_node->linked_state = linked_state; + id_node->is_visible = is_visible; object->customdata_mask = 0; /* Various flags, flushing from bases/collections. */ build_object_flags(base_index, object, linked_state); @@ -562,7 +569,7 @@ void DepsgraphNodeBuilder::build_object(int base_index, } /* Object dupligroup. */ if (object->dup_group != NULL) { - build_collection(DEG_COLLECTION_OWNER_OBJECT, object->dup_group); + build_collection(object->dup_group); } } @@ -953,7 +960,7 @@ void DepsgraphNodeBuilder::build_rigidbody(Scene *scene) /* objects - simulation participants */ if (rbw->group) { - build_collection(DEG_COLLECTION_OWNER_OBJECT, rbw->group); + build_collection(rbw->group); FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->group, object) { @@ -1029,7 +1036,7 @@ void DepsgraphNodeBuilder::build_particles(Object *object) break; case PART_DRAW_GR: if (part->dup_group != NULL) { - build_collection(DEG_COLLECTION_OWNER_OBJECT, part->dup_group); + build_collection(part->dup_group); } break; } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h index 66293a91e85..aacb0670a41 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h @@ -163,11 +163,11 @@ struct DepsgraphNodeBuilder { void build_view_layer(Scene *scene, ViewLayer *view_layer, eDepsNode_LinkedState_Type linked_state); - void build_collection(eDepsNode_CollectionOwner owner_type, - Collection *collection); + void build_collection(Collection *collection); void build_object(int base_index, Object *object, - eDepsNode_LinkedState_Type linked_state); + eDepsNode_LinkedState_Type linked_state, + bool is_visible = true); void build_object_flags(int base_index, Object *object, eDepsNode_LinkedState_Type linked_state); @@ -245,6 +245,10 @@ protected: Scene *scene_; ViewLayer *view_layer_; int view_layer_index_; + /* NOTE: Collection are possibly built recursively, so be careful when + * setting the current state. + */ + Collection *collection_; GHash *cow_id_hash_; BuilderMap built_map_; diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc index 3d7b2d6d232..409df45de27 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc @@ -75,7 +75,7 @@ void DepsgraphNodeBuilder::build_layer_collections(ListBase *lb) continue; } if ((lc->flag & LAYER_COLLECTION_EXCLUDE) == 0) { - build_collection(DEG_COLLECTION_OWNER_SCENE, lc->collection); + build_collection(lc->collection); } build_layer_collections(&lc->layer_collections); } @@ -108,10 +108,9 @@ void DepsgraphNodeBuilder::build_view_layer( BASE_ENABLED_VIEWPORT : BASE_ENABLED_RENDER; LISTBASE_FOREACH(Base *, base, &view_layer->object_bases) { /* object itself */ - if (base->flag & base_flag) { - build_object(base_index, base->object, linked_state); - base->object->select_color = select_color++; - } + const bool is_object_visible = (base->flag & base_flag); + build_object(base_index, base->object, linked_state, is_object_visible); + base->object->select_color = select_color++; ++base_index; } build_layer_collections(&view_layer->layer_collections); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 2efe14557a6..f4259803c91 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -409,7 +409,7 @@ void DepsgraphRelationBuilder::build_id(ID *id) build_camera((Camera *)id); break; case ID_GR: - build_collection(DEG_COLLECTION_OWNER_UNKNOWN, NULL, (Collection *)id); + build_collection(NULL, (Collection *)id); break; case ID_OB: build_object(NULL, (Object *)id); @@ -458,37 +458,19 @@ void DepsgraphRelationBuilder::build_id(ID *id) } void DepsgraphRelationBuilder::build_collection( - eDepsNode_CollectionOwner owner_type, Object *object, Collection *collection) { - const bool allow_restrict_flags = (owner_type == DEG_COLLECTION_OWNER_SCENE); - if (allow_restrict_flags) { - const int restrict_flag = (graph_->mode == DAG_EVAL_VIEWPORT) - ? COLLECTION_RESTRICT_VIEW - : COLLECTION_RESTRICT_RENDER; - if (collection->flag & restrict_flag) { - return; - } - } const bool group_done = built_map_.checkIsBuiltAndTag(collection); OperationKey object_transform_final_key(object != NULL ? &object->id : NULL, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL); if (!group_done) { LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) { - if (allow_restrict_flags) { - const int restrict_flag = (graph_->mode == DAG_EVAL_VIEWPORT) - ? OB_RESTRICT_VIEW - : OB_RESTRICT_RENDER; - if (cob->ob->restrictflag & restrict_flag) { - continue; - } - } build_object(NULL, cob->ob); } LISTBASE_FOREACH (CollectionChild *, child, &collection->children) { - build_collection(owner_type, NULL, child->collection); + build_collection(NULL, child->collection); } } if (object != NULL) { @@ -617,7 +599,7 @@ void DepsgraphRelationBuilder::build_object(Base *base, Object *object) } /* Object dupligroup. */ if (object->dup_group != NULL) { - build_collection(DEG_COLLECTION_OWNER_OBJECT, object, object->dup_group); + build_collection(object, object->dup_group); } } @@ -1495,7 +1477,7 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene) /* objects - simulation participants */ if (rbw->group) { - build_collection(DEG_COLLECTION_OWNER_OBJECT, NULL, rbw->group); + build_collection(NULL, rbw->group); FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->group, object) { @@ -1677,7 +1659,7 @@ void DepsgraphRelationBuilder::build_particles(Object *object) break; case PART_DRAW_GR: if (part->dup_group != NULL) { - build_collection(DEG_COLLECTION_OWNER_OBJECT, NULL, part->dup_group); + build_collection(NULL, part->dup_group); LISTBASE_FOREACH (CollectionObject *, go, &part->dup_group->gobject) { build_particles_visualization_object(object, psys, diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h index d4f1271b217..20b425c81e3 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h @@ -203,9 +203,7 @@ struct DepsgraphRelationBuilder void build_id(ID *id); void build_layer_collections(ListBase *lb); void build_view_layer(Scene *scene, ViewLayer *view_layer); - void build_collection(eDepsNode_CollectionOwner owner_type, - Object *object, - Collection *collection); + void build_collection(Object *object, Collection *collection); void build_object(Base *base, Object *object); void build_object_flags(Base *base, Object *object); void build_object_data(Object *object); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc index 78d1a930eb7..360e823d1bd 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc @@ -79,7 +79,7 @@ void DepsgraphRelationBuilder::build_layer_collections(ListBase *lb) continue; } if ((lc->flag & LAYER_COLLECTION_EXCLUDE) == 0) { - build_collection(DEG_COLLECTION_OWNER_SCENE, NULL, lc->collection); + build_collection(NULL, lc->collection); } build_layer_collections(&lc->layer_collections); } @@ -94,12 +94,8 @@ void DepsgraphRelationBuilder::build_view_layer(Scene *scene, ViewLayer *view_la * passed to the evaluation functions. During relations builder we only * do NULL-pointer check of the base, so it's fine to pass original one. */ - const int base_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ? - BASE_ENABLED_VIEWPORT : BASE_ENABLED_RENDER; LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { - if (base->flag & base_flag) { - build_object(base, base->object); - } + build_object(base, base->object); } build_layer_collections(&view_layer->layer_collections); diff --git a/source/blender/depsgraph/intern/depsgraph_types.h b/source/blender/depsgraph/intern/depsgraph_types.h index b19eb619fac..534376653e9 100644 --- a/source/blender/depsgraph/intern/depsgraph_types.h +++ b/source/blender/depsgraph/intern/depsgraph_types.h @@ -280,15 +280,4 @@ typedef enum eDepsOperation_Code { } eDepsOperation_Code; const char *operationCodeAsString(eDepsOperation_Code opcode); -typedef enum eDepsNode_CollectionOwner { - /* Unknown owner of collection, collection is pulled directly, maybe - * via driver. - */ - DEG_COLLECTION_OWNER_UNKNOWN, - /* Collection belongs to a scene. */ - DEG_COLLECTION_OWNER_SCENE, - /* Collection is used by object, as a dupli-system. */ - DEG_COLLECTION_OWNER_OBJECT, -} eDepsNode_CollectionOwner; - } // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval.cc b/source/blender/depsgraph/intern/eval/deg_eval.cc index f911383b273..fb8b8e73ef6 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval.cc @@ -103,6 +103,19 @@ typedef struct CalculatePengindData { Depsgraph *graph; } CalculatePengindData; +static bool check_operation_node_visible(OperationDepsNode *op_node) +{ + const ComponentDepsNode *comp_node = op_node->owner; + /* Special exception, copy on write component is to be always evaluated, + * to keep copied "database" in a consistent state. + */ + if (comp_node->type == DEG_NODE_TYPE_COPY_ON_WRITE) { + return true; + } + const IDDepsNode *id_node = comp_node->owner; + return id_node->is_visible; +} + static void calculate_pending_func( void *__restrict data_v, const int i, @@ -111,21 +124,35 @@ static void calculate_pending_func( CalculatePengindData *data = (CalculatePengindData *)data_v; Depsgraph *graph = data->graph; OperationDepsNode *node = graph->operations[i]; - + /* Update counters, applies for both visible and invisible IDs. */ node->num_links_pending = 0; node->scheduled = false; - - /* count number of inputs that need updates */ - if ((node->flag & DEPSOP_FLAG_NEEDS_UPDATE) != 0) { - foreach (DepsRelation *rel, node->inlinks) { - if (rel->from->type == DEG_NODE_TYPE_OPERATION && - (rel->flag & DEPSREL_FLAG_CYCLIC) == 0) - { - OperationDepsNode *from = (OperationDepsNode *)rel->from; - if ((from->flag & DEPSOP_FLAG_NEEDS_UPDATE) != 0) { - ++node->num_links_pending; - } + /* Invisible IDs requires no pending operations. */ + if (!check_operation_node_visible(node)) { + return; + } + /* No need to bother with anything if node is not tagged for update. */ + if ((node->flag & DEPSOP_FLAG_NEEDS_UPDATE) == 0) { + return; + } + foreach (DepsRelation *rel, node->inlinks) { + if (rel->from->type == DEG_NODE_TYPE_OPERATION && + (rel->flag & DEPSREL_FLAG_CYCLIC) == 0) + { + OperationDepsNode *from = (OperationDepsNode *)rel->from; + /* TODO(sergey): This is how old layer system was checking for the + * calculation, but how is it possible that visible object depends + * on an invisible? This is something what is prohibited after + * deg_graph_build_flush_layers(). + */ + if (!check_operation_node_visible(from)) { + continue; + } + /* No need to vait for operation which is up to date. */ + if ((from->flag & DEPSOP_FLAG_NEEDS_UPDATE) == 0) { + continue; } + ++node->num_links_pending; } } } @@ -166,30 +193,44 @@ static void schedule_node(TaskPool *pool, Depsgraph *graph, OperationDepsNode *node, bool dec_parents, const int thread_id) { - if ((node->flag & DEPSOP_FLAG_NEEDS_UPDATE) != 0) { - if (dec_parents) { - BLI_assert(node->num_links_pending > 0); - atomic_sub_and_fetch_uint32(&node->num_links_pending, 1); + /* No need to schedule nodes of invisible ID. */ + if (!check_operation_node_visible(node)) { + return; + } + /* No need to schedule operations which are not tagged for update, they are + * considered to be up to date. + */ + if ((node->flag & DEPSOP_FLAG_NEEDS_UPDATE) == 0) { + return; + } + /* TODO(sergey): This is not strictly speaking safe to read + * num_links_pending. + */ + if (dec_parents) { + BLI_assert(node->num_links_pending > 0); + atomic_sub_and_fetch_uint32(&node->num_links_pending, 1); + } + /* Cal not schedule operation while its dependencies are not yet + * evaluated. + */ + if (node->num_links_pending != 0) { + return; + } + bool is_scheduled = atomic_fetch_and_or_uint8( + (uint8_t *)&node->scheduled, (uint8_t)true); + if (!is_scheduled) { + if (node->is_noop()) { + /* skip NOOP node, schedule children right away */ + schedule_children(pool, graph, node, thread_id); } - - if (node->num_links_pending == 0) { - bool is_scheduled = atomic_fetch_and_or_uint8( - (uint8_t *)&node->scheduled, (uint8_t)true); - if (!is_scheduled) { - if (node->is_noop()) { - /* skip NOOP node, schedule children right away */ - schedule_children(pool, graph, node, thread_id); - } - else { - /* children are scheduled once this task is completed */ - BLI_task_pool_push_from_thread(pool, - deg_task_run_func, - node, - false, - TASK_PRIORITY_HIGH, - thread_id); - } - } + else { + /* children are scheduled once this task is completed */ + BLI_task_pool_push_from_thread(pool, + deg_task_run_func, + node, + false, + TASK_PRIORITY_HIGH, + thread_id); } } } diff --git a/source/blender/depsgraph/intern/nodes/deg_node_id.cc b/source/blender/depsgraph/intern/nodes/deg_node_id.cc index 3a164a50692..f2464cf98bd 100644 --- a/source/blender/depsgraph/intern/nodes/deg_node_id.cc +++ b/source/blender/depsgraph/intern/nodes/deg_node_id.cc @@ -104,6 +104,7 @@ void IDDepsNode::init(const ID *id, const char *UNUSED(subdata)) id_orig = (ID *)id; eval_flags = 0; linked_state = DEG_ID_LINKED_INDIRECTLY; + is_visible = true; components = BLI_ghash_new(id_deps_node_hash_key, id_deps_node_hash_key_cmp, @@ -171,7 +172,8 @@ string IDDepsNode::identifier() const BLI_snprintf(orig_ptr, sizeof(orig_ptr), "%p", id_orig); BLI_snprintf(cow_ptr, sizeof(cow_ptr), "%p", id_cow); return string(nodeTypeAsString(type)) + " : " + name + - " (orig: " + orig_ptr + ", eval: " + cow_ptr + ")"; + " (orig: " + orig_ptr + ", eval: " + cow_ptr + + ", is_visible " + (is_visible ? "true" : "false") + ")"; } ComponentDepsNode *IDDepsNode::find_component(eDepsNode_Type type, diff --git a/source/blender/depsgraph/intern/nodes/deg_node_id.h b/source/blender/depsgraph/intern/nodes/deg_node_id.h index 12dbc16b4fa..8af7b80973b 100644 --- a/source/blender/depsgraph/intern/nodes/deg_node_id.h +++ b/source/blender/depsgraph/intern/nodes/deg_node_id.h @@ -77,6 +77,11 @@ struct IDDepsNode : public DepsNode { eDepsNode_LinkedState_Type linked_state; + /* Indicates the datablock is visible, meaning, it is to be evaluated by + * the dependency graph. + */ + bool is_visible; + DEG_DEPSNODE_DECLARE; }; |