Fix T101004: Crash when invisible object becomes visible

A regression since ac20970bc2

The issue was caused by depsgraph clearing all id->recalc flags
wrongly assuming that all IDs are fully evaluated.

This change makes it so the depsgraph becomes aware of possibly
incompletely evaluated IDs.

Differential Revision: https://developer.blender.org/D15946
This commit is contained in:
2022-09-12 16:30:07 +02:00
parent a45c36efae
commit bb3a021427
6 changed files with 30 additions and 0 deletions

View File

@@ -155,12 +155,14 @@ IDNode *DepsgraphNodeBuilder::add_id_node(ID *id)
IDComponentsMask previously_visible_components_mask = 0;
uint32_t previous_eval_flags = 0;
DEGCustomDataMeshMasks previous_customdata_masks;
int id_invisible_recalc = 0;
IDInfo *id_info = id_info_hash_.lookup_default(id->session_uuid, nullptr);
if (id_info != nullptr) {
id_cow = id_info->id_cow;
previously_visible_components_mask = id_info->previously_visible_components_mask;
previous_eval_flags = id_info->previous_eval_flags;
previous_customdata_masks = id_info->previous_customdata_masks;
id_invisible_recalc = id_info->id_invisible_recalc;
/* Tag ID info to not free the CoW ID pointer. */
id_info->id_cow = nullptr;
}
@@ -168,6 +170,7 @@ IDNode *DepsgraphNodeBuilder::add_id_node(ID *id)
id_node->previously_visible_components_mask = previously_visible_components_mask;
id_node->previous_eval_flags = previous_eval_flags;
id_node->previous_customdata_masks = previous_customdata_masks;
id_node->id_invisible_recalc = id_invisible_recalc;
/* NOTE: Zero number of components indicates that ID node was just created. */
const bool is_newly_created = id_node->components.is_empty();
@@ -366,6 +369,7 @@ void DepsgraphNodeBuilder::begin_build()
id_info->previously_visible_components_mask = id_node->visible_components_mask;
id_info->previous_eval_flags = id_node->eval_flags;
id_info->previous_customdata_masks = id_node->customdata_masks;
id_info->id_invisible_recalc = id_node->id_invisible_recalc;
BLI_assert(!id_info_hash_.contains(id_node->id_orig_session_uuid));
id_info_hash_.add_new(id_node->id_orig_session_uuid, id_info);
id_node->id_cow = nullptr;

View File

@@ -250,6 +250,8 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder {
IDComponentsMask previously_visible_components_mask;
/* Special evaluation flag mask from the previous depsgraph. */
uint32_t previous_eval_flags;
/* Recalculation flags which were not evaluated for the ID in the previous depsgraph. */
int id_invisible_recalc;
/* Mesh CustomData mask from the previous depsgraph. */
DEGCustomDataMeshMasks previous_customdata_masks;
};

View File

@@ -890,6 +890,13 @@ void DEG_ids_clear_recalc(Depsgraph *depsgraph, const bool backup)
}
/* Go over all ID nodes, clearing tags. */
for (deg::IDNode *id_node : deg_graph->id_nodes) {
if (!id_node->is_enabled_on_eval) {
id_node->id_invisible_recalc |= id_node->id_cow->recalc;
}
else {
id_node->id_invisible_recalc = 0;
}
if (backup) {
id_node->id_cow_recalc_backup |= id_node->id_cow->recalc;
}

View File

@@ -31,6 +31,7 @@
#include "intern/debug/deg_debug.h"
#include "intern/depsgraph.h"
#include "intern/depsgraph_relation.h"
#include "intern/depsgraph_tag.h"
#include "intern/depsgraph_type.h"
#include "intern/depsgraph_update.h"
#include "intern/node/deg_node.h"
@@ -99,6 +100,18 @@ inline void flush_prepare(Depsgraph *graph)
inline void flush_schedule_entrypoints(Depsgraph *graph, FlushQueue *queue)
{
/* Something changed in the scene, so re-tag IDs with flags which were previously ignored due to
* ID being hidden. This will ensure the ID is properly evaluated when it becomes visible. */
for (IDNode *node : graph->id_nodes) {
if (node->id_invisible_recalc) {
graph_id_tag_update(graph->bmain,
graph,
node->id_orig,
node->id_invisible_recalc,
DEG_UPDATE_SOURCE_VISIBILITY);
}
}
for (OperationNode *op_node : graph->entry_tags) {
queue->push_back(op_node);
op_node->scheduled = true;

View File

@@ -75,6 +75,7 @@ void IDNode::init(const ID *id, const char *UNUSED(subdata))
has_base = false;
is_user_modified = false;
id_cow_recalc_backup = 0;
id_invisible_recalc = 0;
visible_components_mask = 0;
previously_visible_components_mask = 0;

View File

@@ -123,6 +123,9 @@ struct IDNode : public Node {
/* Accumulate recalc flags from multiple update passes. */
int id_cow_recalc_backup;
/* Flags which components were not evaluated due to ID being invisible. */
int id_invisible_recalc;
IDComponentsMask visible_components_mask;
IDComponentsMask previously_visible_components_mask;