Fix T97262: Crash with specific view layer setup

Originally was noticed when using a linked background scene and a scene
camera from another (local) scene.

The root issue was that relation from view layer to object's base flags
evaluation was using wrong view layer. This is because the relation was
created between object and currently built view layer, and it only was
happening once (since the object-level relations are only built once).
Depending on order in which `build_object` was called it was possible
that relation from a wrong view layer was used.

Now the code is better split to indicate which parts of object relations
are built when object comes from a base in the view layer, and which ones
are built on indirect linking of object to the dependency graph.

This patch makes relations correct in the cases when the same object is
used as a base in both active and set scenes. But, the operation which
handles object-level flags might not behave correctly as there is no
known design of what is the proper thing to do in this case. Making a
clear design and implementation of case when object is shared between
active and set scene is outside of the scope of this patch.

Differential Revision: https://developer.blender.org/D14626
This commit is contained in:
Sergey Sharybin 2022-04-12 12:36:48 +02:00
parent 1440074cac
commit 31b2b84b3c
Notes: blender-bot 2023-08-16 11:48:47 +02:00
Referenced by issue #97262, Crash when using a linked background scene and a scene camera from another (local) scene
Referenced by issue #111165, Regression: Blender Crashes On Scene Switch
3 changed files with 35 additions and 8 deletions

View File

@ -699,7 +699,7 @@ void DepsgraphRelationBuilder::build_object(Object *object)
OperationKey ob_eval_key(&object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_EVAL);
add_relation(init_transform_key, local_transform_key, "Transform Init");
/* Various flags, flushing from bases/collections. */
build_object_from_layer_relations(object);
build_object_layer_component_relations(object);
/* Parenting. */
if (object->parent != nullptr) {
/* Make sure parent object's relations are built. */
@ -787,7 +787,37 @@ void DepsgraphRelationBuilder::build_object(Object *object)
build_parameters(&object->id);
}
void DepsgraphRelationBuilder::build_object_from_layer_relations(Object *object)
/* NOTE: Implies that the object has base in the current view layer. */
void DepsgraphRelationBuilder::build_object_from_view_layer_base(Object *object)
{
/* It is possible to have situation when an object is pulled into the dependency graph in a
* few different ways:
*
* - Indirect driver dependency, which doesn't have a Base (or, Base is unknown).
* - Via a base from a view layer (view layer of the graph, or view layer of a set scene).
* - Possibly other ways, which are not important for decision making here.
*
* There needs to be a relation from view layer which has a base with the object so that the
* order of flags evaluation is correct (object-level base flags evaluation requires view layer
* to be evaluated first).
*
* This build call handles situation when object comes from a view layer, hence has a base, and
* needs a relation from the view layer. Do the relation prior to check of whether the object
* relations are built so that the relation is created from every view layer which has a base
* with this object. */
OperationKey view_layer_done_key(
&scene_->id, NodeType::LAYER_COLLECTIONS, OperationCode::VIEW_LAYER_EVAL);
OperationKey object_from_layer_entry_key(
&object->id, NodeType::OBJECT_FROM_LAYER, OperationCode::OBJECT_FROM_LAYER_ENTRY);
add_relation(view_layer_done_key, object_from_layer_entry_key, "View Layer flags to Object");
/* Regular object building. */
build_object(object);
}
void DepsgraphRelationBuilder::build_object_layer_component_relations(Object *object)
{
OperationKey object_from_layer_entry_key(
&object->id, NodeType::OBJECT_FROM_LAYER, OperationCode::OBJECT_FROM_LAYER_ENTRY);
@ -810,10 +840,6 @@ void DepsgraphRelationBuilder::build_object_from_layer_relations(Object *object)
OperationKey synchronize_key(
&object->id, NodeType::SYNCHRONIZATION, OperationCode::SYNCHRONIZE_TO_ORIGINAL);
add_relation(object_from_layer_exit_key, synchronize_key, "Synchronize to Original");
OperationKey view_layer_done_key(
&scene_->id, NodeType::LAYER_COLLECTIONS, OperationCode::VIEW_LAYER_EVAL);
add_relation(view_layer_done_key, object_from_layer_entry_key, "View Layer flags to Object");
}
void DepsgraphRelationBuilder::build_object_data(Object *object)

View File

@ -200,7 +200,8 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder {
Object *object,
Collection *collection);
virtual void build_object(Object *object);
virtual void build_object_from_layer_relations(Object *object);
virtual void build_object_from_view_layer_base(Object *object);
virtual void build_object_layer_component_relations(Object *object);
virtual void build_object_data(Object *object);
virtual void build_object_data_camera(Object *object);
virtual void build_object_data_geometry(Object *object);

View File

@ -81,7 +81,7 @@ void DepsgraphRelationBuilder::build_view_layer(Scene *scene,
* do nullptr-pointer check of the base, so it's fine to pass original one. */
LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
if (need_pull_base_into_graph(base)) {
build_object(base->object);
build_object_from_view_layer_base(base->object);
}
}