Fix #136615: Disallow writeback callbacks that are not cleared
Adding "writeback" callbacks to the depsgraph should be temporary, since these callbacks can bind pointers that become invalid. In this case: the evaluated nodes modifier bound by a bake node callback. These callbacks are cleared after being added in the `deg_flush_updates_and_refresh` function, but there are other cases where depsgraph updates are executed which don't support writeback callbacks (`object_force_modifier_update_for_bind` run by the smooth modifier "bind" function). To prevent dangling invalid pointers in outdated callbacks, disallow adding callbacks in any case other than the `deg_flush_updates_and_refresh` function. Since callbacks can be added from any depsgraph update, the safest way to prevent adding them is in the depsgraph itself. If the `use_writeback_callbacks` flag is not set, any callback is simply discarded. Pull Request: https://projects.blender.org/blender/blender/pulls/137083
This commit is contained in:
@@ -53,6 +53,7 @@ Depsgraph::Depsgraph(Main *bmain, Scene *scene, ViewLayer *view_layer, eEvaluati
|
||||
ctime(BKE_scene_ctime_get(scene)),
|
||||
scene_cow(nullptr),
|
||||
is_active(false),
|
||||
sync_writeback(DEG_EVALUATE_SYNC_WRITEBACK_NO),
|
||||
use_visibility_optimization(true),
|
||||
is_evaluating(false),
|
||||
is_render_pipeline_depsgraph(false),
|
||||
|
||||
@@ -178,6 +178,8 @@ struct Depsgraph {
|
||||
/* The number of times this graph has been evaluated. */
|
||||
uint64_t update_count;
|
||||
|
||||
/* If this mode does not allow writing back to original data any callbacks will be discarded. */
|
||||
DepsgraphEvaluateSyncWriteback sync_writeback;
|
||||
/**
|
||||
* Stores functions that can be called after depsgraph evaluation to writeback some changes to
|
||||
* original data. Also see `DEG_depsgraph_writeback_sync.hh`.
|
||||
|
||||
@@ -37,15 +37,16 @@ static void deg_flush_updates_and_refresh(deg::Depsgraph *deg_graph,
|
||||
|
||||
deg::graph_tag_ids_for_visible_update(deg_graph);
|
||||
deg::deg_graph_flush_updates(deg_graph);
|
||||
BLI_assert(deg_graph->sync_writeback_callbacks.is_empty());
|
||||
deg_graph->sync_writeback = sync_writeback;
|
||||
deg::deg_evaluate_on_refresh(deg_graph);
|
||||
|
||||
if (sync_writeback == DEG_EVALUATE_SYNC_WRITEBACK_YES) {
|
||||
if (deg_graph->is_active) {
|
||||
for (std::function<void()> &fn : deg_graph->sync_writeback_callbacks) {
|
||||
fn();
|
||||
}
|
||||
if ((deg_graph->sync_writeback == DEG_EVALUATE_SYNC_WRITEBACK_YES) && deg_graph->is_active) {
|
||||
for (std::function<void()> &fn : deg_graph->sync_writeback_callbacks) {
|
||||
fn();
|
||||
}
|
||||
}
|
||||
deg_graph->sync_writeback = DEG_EVALUATE_SYNC_WRITEBACK_NO;
|
||||
deg_graph->sync_writeback_callbacks.clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace blender::deg::sync_writeback {
|
||||
void add(::Depsgraph &depsgraph, std::function<void()> fn)
|
||||
{
|
||||
deg::Depsgraph °_graph = reinterpret_cast<deg::Depsgraph &>(depsgraph);
|
||||
if (!deg_graph.is_active) {
|
||||
if (!deg_graph.is_active || deg_graph.sync_writeback == DEG_EVALUATE_SYNC_WRITEBACK_NO) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user