Fix T74984: Crash opening specific production files

More detailed symptoms: there was no curve cache created for an object
which was used by draw manager.

A bit tricky situation, which involves collection instances and their
proxies.

The root of the problem in the dependency graph was that instanced
collections visibility was not updated when object is requested with
different visibility. So what was happening is that one of the objects
was pulled as an indirect dependency of something invisible, so it
built instanced collections as if the instancer is invisible. After
that the same object was built as visible. Before this fix this was
only update object flags, the instanced collections still believed they
are invisible. Since there is no path via relations which would connect
visible object with instanced objects the visibility flush which is
happening during graph finalization did not "fix" the visibility flags.

This change makes it so instanced collections are updating their
visibility when their instancer's visibility is changing to truth.
This is similar to how collections will accumulate their visibility
when same collection is used from multiple ones with different
visibility.

However, this alone wasn't enough to get crash fixed. This marked
collections as visible, but the geometry component of the curve object
was still considering self as invisible.

This is something tricky, since the code which is responsible for this
issue was added as an optimization in afb4da6650. This looks like like
an oversight in that commit since it's rather weird that ID node's
flag would depend on construction order (in "normal" object builder the
ID node's directly_visible flag is initialized to object's visibility).
So it seems logical to get this part of code in sync between "regular"
and "accumulative" object builder.

And last but not least the naming is_directly_visible is old and does
not really represent what it actually mans now: a more correct name
would be "will be used by the draw manager".

Differential Revision: https://developer.blender.org/D7217
This commit is contained in:
Sergey Sharybin 2020-03-23 11:38:07 +01:00
parent 58ac113b76
commit ed386507e1
Notes: blender-bot 2023-02-14 00:20:19 +01:00
Referenced by issue #77894, Collection Instance Crash
Referenced by issue #74984, Curve cache not created - crash with production file
2 changed files with 26 additions and 10 deletions

View File

@ -551,21 +551,28 @@ void DepsgraphNodeBuilder::build_object(int base_index,
object->proxy->proxy_from = object;
}
const bool has_object = built_map_.checkIsBuiltAndTag(object);
/* Skip rest of components if the ID node was already there. */
/* When there is already object in the dependency graph accumulate visibility an linked state
* flags. Only do it on the object itself (apart from very special cases) and leave dealing with
* visibility of dependnecies to the visibility flush step which happens at the end of the build
* process. */
if (has_object) {
IDNode *id_node = find_id_node(&object->id);
/* We need to build some extra stuff if object becomes linked
* directly. */
if (id_node->linked_state == DEG_ID_LINKED_INDIRECTLY) {
build_object_flags(base_index, object, linked_state);
}
id_node->linked_state = max(id_node->linked_state, linked_state);
if (id_node->linked_state == DEG_ID_LINKED_DIRECTLY) {
id_node->is_directly_visible |= is_visible;
}
id_node->is_directly_visible |= is_visible;
id_node->has_base |= (base_index != -1);
/* There is no relation path which will connect current object with all the ones which come
* via the instanced collection, so build the collection again. Note that it will do check
* whether visibility update is needed on its own. */
build_object_instance_collection(object, is_visible);
return;
}
/* Create ID node for object and begin init. */
IDNode *id_node = add_id_node(&object->id);
Object *object_cow = get_cow_datablock(object);
@ -636,10 +643,7 @@ void DepsgraphNodeBuilder::build_object(int base_index,
build_object_proxy_group(object, is_visible);
/* Object dupligroup. */
if (object->instance_collection != nullptr) {
const bool is_current_parent_collection_visible = is_parent_collection_visible_;
is_parent_collection_visible_ = is_visible;
build_collection(nullptr, object->instance_collection);
is_parent_collection_visible_ = is_current_parent_collection_visible;
build_object_instance_collection(object, is_visible);
OperationNode *op_node = add_operation_node(
&object->id, NodeType::DUPLI, OperationCode::DUPLI);
op_node->flag |= OperationFlag::DEPSOP_FLAG_PINNED;
@ -690,6 +694,17 @@ void DepsgraphNodeBuilder::build_object_proxy_group(Object *object, bool is_visi
build_object(-1, object->proxy_group, DEG_ID_LINKED_INDIRECTLY, is_visible);
}
void DepsgraphNodeBuilder::build_object_instance_collection(Object *object, bool is_object_visible)
{
if (object->instance_collection == nullptr) {
return;
}
const bool is_current_parent_collection_visible = is_parent_collection_visible_;
is_parent_collection_visible_ = is_object_visible;
build_collection(nullptr, object->instance_collection);
is_parent_collection_visible_ = is_current_parent_collection_visible;
}
void DepsgraphNodeBuilder::build_object_data(Object *object, bool is_object_visible)
{
if (object->data == nullptr) {

View File

@ -164,6 +164,7 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder {
bool is_visible);
virtual void build_object_proxy_from(Object *object, bool is_object_visible);
virtual void build_object_proxy_group(Object *object, bool is_object_visible);
virtual void build_object_instance_collection(Object *object, bool is_object_visible);
virtual void build_object_flags(int base_index,
Object *object,
eDepsNode_LinkedState_Type linked_state);