Fix #104798: Slow frame-change & scrubbing with many objects #104801

Manually merged
Campbell Barton merged 2 commits from ideasman42/blender:pr-scene-collection-skip-on-cow into main 2024-04-18 05:52:21 +02:00
3 changed files with 25 additions and 8 deletions

View File

@ -291,7 +291,9 @@ static void deg_debug_graphviz_relation_arrowhead(const Relation *rel, dot::Dire
OperationNode *op_from = (OperationNode *)rel->from;
OperationNode *op_to = (OperationNode *)rel->to;
if (op_from->owner->type == NodeType::COPY_ON_EVAL &&
!op_to->owner->need_tag_cow_before_update())
/* The #ID::recalc flag depends on run-time state which is not valid at this point in time.
* Pass in all flags although there may be a better way to represent this. */
!op_to->owner->need_tag_cow_before_update(ID_RECALC_ALL))
{
shape = shape_no_cow;
}

View File

@ -296,7 +296,7 @@ void depsgraph_tag_component(Depsgraph *graph,
}
}
/* If component depends on copy-on-evaluation, tag it as well. */
if (component_node->need_tag_cow_before_update()) {
if (component_node->need_tag_cow_before_update(IDRecalcFlag(id_node->id_cow->recalc))) {
depsgraph_id_tag_copy_on_write(graph, id_node, update_source);
}
if (component_type == NodeType::COPY_ON_EVAL) {
@ -531,8 +531,12 @@ void deg_graph_tag_parameters_if_needed(Main *bmain,
}
/* Clear flags which are known to not affect parameters usable by drivers. */
const uint clean_flags = flags & ~(ID_RECALC_SYNC_TO_EVAL | ID_RECALC_SELECT |
ID_RECALC_BASE_FLAGS | ID_RECALC_SHADING);
const uint clean_flags = flags &
~(ID_RECALC_SYNC_TO_EVAL | ID_RECALC_SELECT | ID_RECALC_BASE_FLAGS |
ID_RECALC_SHADING |
/* While drivers may use the current-frame, this value is assigned
explicitly and doesn't require a the scene to be copied again. */
ID_RECALC_FRAME_CHANGE);
if (clean_flags == 0) {
/* Changes are limited to only things which are not usable by drivers. */

View File

@ -132,7 +132,7 @@ struct ComponentNode : public Node {
/* Denotes whether copy-on-eval component is to be tagged when this component
* is tagged for update. */
virtual bool need_tag_cow_before_update()
virtual bool need_tag_cow_before_update(const IDRecalcFlag /*tag*/)
{
return true;
}
@ -170,7 +170,7 @@ struct ComponentNode : public Node {
#define DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_UPDATE(name) \
struct name##ComponentNode : public ComponentNode { \
DEG_COMPONENT_NODE_DECLARE; \
virtual bool need_tag_cow_before_update() \
virtual bool need_tag_cow_before_update(const IDRecalcFlag /*tag*/) \
{ \
return false; \
} \
@ -204,7 +204,6 @@ DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_UPDATE(ObjectFromLayer);
DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_UPDATE(Hierarchy);
DEG_COMPONENT_NODE_DECLARE_GENERIC(Instancing);
DEG_COMPONENT_NODE_DECLARE_GENERIC(Synchronization);
DEG_COMPONENT_NODE_DECLARE_GENERIC(Audio);
DEG_COMPONENT_NODE_DECLARE_GENERIC(Armature);
DEG_COMPONENT_NODE_DECLARE_GENERIC(GenericDatablock);
DEG_COMPONENT_NODE_DECLARE_GENERIC(Scene);
@ -226,7 +225,7 @@ struct BoneComponentNode : public ComponentNode {
/* Eventually we would not tag parameters in all cases.
* Support for this each ID needs to be added on an individual basis. */
struct ParametersComponentNode : public ComponentNode {
virtual bool need_tag_cow_before_update() override
virtual bool need_tag_cow_before_update(const IDRecalcFlag /*tag*/) override
{
if (ID_TYPE_SUPPORTS_PARAMS_WITHOUT_COW(owner->id_type)) {
/* Disabled as this is not true for newly added objects, needs investigation. */
@ -239,6 +238,18 @@ struct ParametersComponentNode : public ComponentNode {
DEG_COMPONENT_NODE_DECLARE;
};
/* Audio component. */
struct AudioComponentNode : public ComponentNode {
virtual bool need_tag_cow_before_update(const IDRecalcFlag tag) override
ideasman42 marked this conversation as resolved Outdated

const IDRecalcFlag flag

`const IDRecalcFlag flag`
{
/* Frame change doesn't require a copy of the scene, doing so can be a heavy operation
* especially when the collection contains many objects, see #104798. */
return (tag != ID_RECALC_FRAME_CHANGE);
ideasman42 marked this conversation as resolved Outdated

Personally I'd prefer return tag != ID_RECALC_FRAME_CHANGE;

No strong feelings, it mostly depends on how likely it is that other cases will be added. If you keep the if, I think it's better to put the explanation inside the conditional block.

Personally I'd prefer `return tag != ID_RECALC_FRAME_CHANGE;` No strong feelings, it mostly depends on how likely it is that other cases will be added. If you keep the `if`, I think it's better to put the explanation inside the conditional block.
}
DEG_COMPONENT_NODE_DECLARE;
};
void deg_register_component_depsnodes();
} // namespace blender::deg